diff options
519 files changed, 36452 insertions, 8266 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..685949bb8838 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 |
@@ -5061,9 +5043,8 @@ S: Maintained | |||
5061 | F: drivers/net/ethernet/marvell/sk* | 5043 | F: drivers/net/ethernet/marvell/sk* |
5062 | 5044 | ||
5063 | MARVELL LIBERTAS WIRELESS DRIVER | 5045 | MARVELL LIBERTAS WIRELESS DRIVER |
5064 | M: Dan Williams <dcbw@redhat.com> | ||
5065 | L: libertas-dev@lists.infradead.org | 5046 | L: libertas-dev@lists.infradead.org |
5066 | S: Maintained | 5047 | S: Orphan |
5067 | F: drivers/net/wireless/libertas/ | 5048 | F: drivers/net/wireless/libertas/ |
5068 | 5049 | ||
5069 | MARVELL MV643XX ETHERNET DRIVER | 5050 | MARVELL MV643XX ETHERNET DRIVER |
@@ -8504,7 +8485,7 @@ F: drivers/usb/gadget/*uvc*.c | |||
8504 | F: drivers/usb/gadget/webcam.c | 8485 | F: drivers/usb/gadget/webcam.c |
8505 | 8486 | ||
8506 | USB WIRELESS RNDIS DRIVER (rndis_wlan) | 8487 | USB WIRELESS RNDIS DRIVER (rndis_wlan) |
8507 | M: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 8488 | M: Jussi Kivilinna <jussi.kivilinna@iki.fi> |
8508 | L: linux-wireless@vger.kernel.org | 8489 | L: linux-wireless@vger.kernel.org |
8509 | S: Maintained | 8490 | S: Maintained |
8510 | F: drivers/net/wireless/rndis_wlan.c | 8491 | 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_chipcommon.c b/drivers/bcma/driver_chipcommon.c index 28fa50ad87be..036c6744b39b 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c | |||
@@ -25,13 +25,14 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, | |||
25 | return value; | 25 | return value; |
26 | } | 26 | } |
27 | 27 | ||
28 | static u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc) | 28 | u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc) |
29 | { | 29 | { |
30 | if (cc->capabilities & BCMA_CC_CAP_PMU) | 30 | if (cc->capabilities & BCMA_CC_CAP_PMU) |
31 | return bcma_pmu_get_alp_clock(cc); | 31 | return bcma_pmu_get_alp_clock(cc); |
32 | 32 | ||
33 | return 20000000; | 33 | return 20000000; |
34 | } | 34 | } |
35 | EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock); | ||
35 | 36 | ||
36 | static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc) | 37 | static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc) |
37 | { | 38 | { |
@@ -213,6 +214,7 @@ u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) | |||
213 | 214 | ||
214 | return res; | 215 | return res; |
215 | } | 216 | } |
217 | EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out); | ||
216 | 218 | ||
217 | u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) | 219 | u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) |
218 | { | 220 | { |
@@ -225,6 +227,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) | |||
225 | 227 | ||
226 | return res; | 228 | return res; |
227 | } | 229 | } |
230 | EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen); | ||
228 | 231 | ||
229 | /* | 232 | /* |
230 | * If the bit is set to 0, chipcommon controlls this GPIO, | 233 | * If the bit is set to 0, chipcommon controlls this GPIO, |
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 932b101dee36..edca73af3cc0 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c | |||
@@ -174,19 +174,35 @@ u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc) | |||
174 | struct bcma_bus *bus = cc->core->bus; | 174 | struct bcma_bus *bus = cc->core->bus; |
175 | 175 | ||
176 | switch (bus->chipinfo.id) { | 176 | switch (bus->chipinfo.id) { |
177 | case BCMA_CHIP_ID_BCM4313: | ||
178 | case BCMA_CHIP_ID_BCM43224: | ||
179 | case BCMA_CHIP_ID_BCM43225: | ||
180 | case BCMA_CHIP_ID_BCM43227: | ||
181 | case BCMA_CHIP_ID_BCM43228: | ||
182 | case BCMA_CHIP_ID_BCM4331: | ||
183 | case BCMA_CHIP_ID_BCM43421: | ||
184 | case BCMA_CHIP_ID_BCM43428: | ||
185 | case BCMA_CHIP_ID_BCM43431: | ||
177 | case BCMA_CHIP_ID_BCM4716: | 186 | case BCMA_CHIP_ID_BCM4716: |
178 | case BCMA_CHIP_ID_BCM4748: | ||
179 | case BCMA_CHIP_ID_BCM47162: | 187 | case BCMA_CHIP_ID_BCM47162: |
180 | case BCMA_CHIP_ID_BCM4313: | 188 | case BCMA_CHIP_ID_BCM4748: |
181 | case BCMA_CHIP_ID_BCM5357: | ||
182 | case BCMA_CHIP_ID_BCM4749: | 189 | case BCMA_CHIP_ID_BCM4749: |
190 | case BCMA_CHIP_ID_BCM5357: | ||
183 | case BCMA_CHIP_ID_BCM53572: | 191 | case BCMA_CHIP_ID_BCM53572: |
192 | case BCMA_CHIP_ID_BCM6362: | ||
184 | /* always 20Mhz */ | 193 | /* always 20Mhz */ |
185 | return 20000 * 1000; | 194 | return 20000 * 1000; |
186 | case BCMA_CHIP_ID_BCM5356: | ||
187 | case BCMA_CHIP_ID_BCM4706: | 195 | case BCMA_CHIP_ID_BCM4706: |
196 | case BCMA_CHIP_ID_BCM5356: | ||
188 | /* always 25Mhz */ | 197 | /* always 25Mhz */ |
189 | return 25000 * 1000; | 198 | return 25000 * 1000; |
199 | case BCMA_CHIP_ID_BCM43460: | ||
200 | case BCMA_CHIP_ID_BCM4352: | ||
201 | case BCMA_CHIP_ID_BCM4360: | ||
202 | if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ) | ||
203 | return 40000 * 1000; | ||
204 | else | ||
205 | return 20000 * 1000; | ||
190 | default: | 206 | default: |
191 | bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", | 207 | bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", |
192 | bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); | 208 | bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); |
@@ -373,7 +389,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
373 | tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; | 389 | tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; |
374 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); | 390 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); |
375 | 391 | ||
376 | tmp = 1 << 10; | 392 | tmp = BCMA_CC_PMU_CTL_PLL_UPD; |
377 | break; | 393 | break; |
378 | 394 | ||
379 | case BCMA_CHIP_ID_BCM4331: | 395 | case BCMA_CHIP_ID_BCM4331: |
@@ -394,7 +410,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
394 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | 410 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, |
395 | 0x03000a08); | 411 | 0x03000a08); |
396 | } | 412 | } |
397 | tmp = 1 << 10; | 413 | tmp = BCMA_CC_PMU_CTL_PLL_UPD; |
398 | break; | 414 | break; |
399 | 415 | ||
400 | case BCMA_CHIP_ID_BCM43224: | 416 | case BCMA_CHIP_ID_BCM43224: |
@@ -427,7 +443,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
427 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, | 443 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, |
428 | 0x88888815); | 444 | 0x88888815); |
429 | } | 445 | } |
430 | tmp = 1 << 10; | 446 | tmp = BCMA_CC_PMU_CTL_PLL_UPD; |
431 | break; | 447 | break; |
432 | 448 | ||
433 | case BCMA_CHIP_ID_BCM4716: | 449 | case BCMA_CHIP_ID_BCM4716: |
@@ -461,7 +477,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
461 | 0x88888815); | 477 | 0x88888815); |
462 | } | 478 | } |
463 | 479 | ||
464 | tmp = 3 << 9; | 480 | tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; |
465 | break; | 481 | break; |
466 | 482 | ||
467 | case BCMA_CHIP_ID_BCM43227: | 483 | case BCMA_CHIP_ID_BCM43227: |
@@ -497,7 +513,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
497 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, | 513 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, |
498 | 0x88888815); | 514 | 0x88888815); |
499 | } | 515 | } |
500 | tmp = 1 << 10; | 516 | tmp = BCMA_CC_PMU_CTL_PLL_UPD; |
501 | break; | 517 | break; |
502 | default: | 518 | default: |
503 | bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", | 519 | bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", |
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/bcma/scan.c b/drivers/bcma/scan.c index 8d0b57164018..bca9c80056fe 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c | |||
@@ -137,19 +137,19 @@ static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr) | |||
137 | addr); | 137 | addr); |
138 | } | 138 | } |
139 | 139 | ||
140 | static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr) | 140 | static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 __iomem **eromptr) |
141 | { | 141 | { |
142 | u32 ent = readl(*eromptr); | 142 | u32 ent = readl(*eromptr); |
143 | (*eromptr)++; | 143 | (*eromptr)++; |
144 | return ent; | 144 | return ent; |
145 | } | 145 | } |
146 | 146 | ||
147 | static void bcma_erom_push_ent(u32 **eromptr) | 147 | static void bcma_erom_push_ent(u32 __iomem **eromptr) |
148 | { | 148 | { |
149 | (*eromptr)--; | 149 | (*eromptr)--; |
150 | } | 150 | } |
151 | 151 | ||
152 | static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr) | 152 | static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 __iomem **eromptr) |
153 | { | 153 | { |
154 | u32 ent = bcma_erom_get_ent(bus, eromptr); | 154 | u32 ent = bcma_erom_get_ent(bus, eromptr); |
155 | if (!(ent & SCAN_ER_VALID)) | 155 | if (!(ent & SCAN_ER_VALID)) |
@@ -159,14 +159,14 @@ static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr) | |||
159 | return ent; | 159 | return ent; |
160 | } | 160 | } |
161 | 161 | ||
162 | static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr) | 162 | static bool bcma_erom_is_end(struct bcma_bus *bus, u32 __iomem **eromptr) |
163 | { | 163 | { |
164 | u32 ent = bcma_erom_get_ent(bus, eromptr); | 164 | u32 ent = bcma_erom_get_ent(bus, eromptr); |
165 | bcma_erom_push_ent(eromptr); | 165 | bcma_erom_push_ent(eromptr); |
166 | return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)); | 166 | return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)); |
167 | } | 167 | } |
168 | 168 | ||
169 | static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr) | 169 | static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 __iomem **eromptr) |
170 | { | 170 | { |
171 | u32 ent = bcma_erom_get_ent(bus, eromptr); | 171 | u32 ent = bcma_erom_get_ent(bus, eromptr); |
172 | bcma_erom_push_ent(eromptr); | 172 | bcma_erom_push_ent(eromptr); |
@@ -175,7 +175,7 @@ static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr) | |||
175 | ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); | 175 | ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); |
176 | } | 176 | } |
177 | 177 | ||
178 | static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr) | 178 | static void bcma_erom_skip_component(struct bcma_bus *bus, u32 __iomem **eromptr) |
179 | { | 179 | { |
180 | u32 ent; | 180 | u32 ent; |
181 | while (1) { | 181 | while (1) { |
@@ -189,7 +189,7 @@ static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr) | |||
189 | bcma_erom_push_ent(eromptr); | 189 | bcma_erom_push_ent(eromptr); |
190 | } | 190 | } |
191 | 191 | ||
192 | static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr) | 192 | static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr) |
193 | { | 193 | { |
194 | u32 ent = bcma_erom_get_ent(bus, eromptr); | 194 | u32 ent = bcma_erom_get_ent(bus, eromptr); |
195 | if (!(ent & SCAN_ER_VALID)) | 195 | if (!(ent & SCAN_ER_VALID)) |
@@ -199,7 +199,7 @@ static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr) | |||
199 | return ent; | 199 | return ent; |
200 | } | 200 | } |
201 | 201 | ||
202 | static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr, | 202 | static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr, |
203 | u32 type, u8 port) | 203 | u32 type, u8 port) |
204 | { | 204 | { |
205 | u32 addrl, addrh, sizel, sizeh = 0; | 205 | u32 addrl, addrh, sizel, sizeh = 0; |
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 4adf9ef9a113..8934298a638d 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
@@ -217,6 +217,7 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | |||
217 | } | 217 | } |
218 | 218 | ||
219 | SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); | 219 | SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); |
220 | SPEX(board_type, SSB_SPROM1_SPID, ~0, 0); | ||
220 | 221 | ||
221 | SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, | 222 | SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, |
222 | SSB_SPROM4_TXPID2G0_SHIFT); | 223 | SSB_SPROM4_TXPID2G0_SHIFT); |
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index a8a41e07a221..6aab00ef4379 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -73,9 +73,13 @@ static struct usb_device_id ath3k_table[] = { | |||
73 | { USB_DEVICE(0x03F0, 0x311D) }, | 73 | { USB_DEVICE(0x03F0, 0x311D) }, |
74 | 74 | ||
75 | /* Atheros AR3012 with sflash firmware*/ | 75 | /* Atheros AR3012 with sflash firmware*/ |
76 | { USB_DEVICE(0x0CF3, 0x0036) }, | ||
76 | { USB_DEVICE(0x0CF3, 0x3004) }, | 77 | { USB_DEVICE(0x0CF3, 0x3004) }, |
78 | { USB_DEVICE(0x0CF3, 0x3008) }, | ||
77 | { USB_DEVICE(0x0CF3, 0x311D) }, | 79 | { USB_DEVICE(0x0CF3, 0x311D) }, |
80 | { USB_DEVICE(0x0CF3, 0x817a) }, | ||
78 | { USB_DEVICE(0x13d3, 0x3375) }, | 81 | { USB_DEVICE(0x13d3, 0x3375) }, |
82 | { USB_DEVICE(0x04CA, 0x3004) }, | ||
79 | { USB_DEVICE(0x04CA, 0x3005) }, | 83 | { USB_DEVICE(0x04CA, 0x3005) }, |
80 | { USB_DEVICE(0x04CA, 0x3006) }, | 84 | { USB_DEVICE(0x04CA, 0x3006) }, |
81 | { USB_DEVICE(0x04CA, 0x3008) }, | 85 | { USB_DEVICE(0x04CA, 0x3008) }, |
@@ -105,9 +109,13 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); | |||
105 | static struct usb_device_id ath3k_blist_tbl[] = { | 109 | static struct usb_device_id ath3k_blist_tbl[] = { |
106 | 110 | ||
107 | /* Atheros AR3012 with sflash firmware*/ | 111 | /* Atheros AR3012 with sflash firmware*/ |
112 | { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, | ||
108 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | 113 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, |
114 | { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||
109 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, | 115 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, |
116 | { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, | ||
110 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 117 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
118 | { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, | ||
111 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | 119 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
112 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, | 120 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, |
113 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, | 121 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, |
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 9959d4cb23dc..1cb51839912d 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
@@ -83,8 +83,8 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = { | |||
83 | }; | 83 | }; |
84 | 84 | ||
85 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { | 85 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { |
86 | .helper = "sd8688_helper.bin", | 86 | .helper = "mrvl/sd8688_helper.bin", |
87 | .firmware = "sd8688.bin", | 87 | .firmware = "mrvl/sd8688.bin", |
88 | .reg = &btmrvl_reg_8688, | 88 | .reg = &btmrvl_reg_8688, |
89 | .sd_blksz_fw_dl = 64, | 89 | .sd_blksz_fw_dl = 64, |
90 | }; | 90 | }; |
@@ -1185,7 +1185,7 @@ MODULE_AUTHOR("Marvell International Ltd."); | |||
1185 | MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION); | 1185 | MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION); |
1186 | MODULE_VERSION(VERSION); | 1186 | MODULE_VERSION(VERSION); |
1187 | MODULE_LICENSE("GPL v2"); | 1187 | MODULE_LICENSE("GPL v2"); |
1188 | MODULE_FIRMWARE("sd8688_helper.bin"); | 1188 | MODULE_FIRMWARE("mrvl/sd8688_helper.bin"); |
1189 | MODULE_FIRMWARE("sd8688.bin"); | 1189 | MODULE_FIRMWARE("mrvl/sd8688.bin"); |
1190 | MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); | 1190 | MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); |
1191 | MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); | 1191 | MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 7e351e345476..2cc5f774a29c 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -131,9 +131,13 @@ static struct usb_device_id blacklist_table[] = { | |||
131 | { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, | 131 | { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, |
132 | 132 | ||
133 | /* Atheros 3012 with sflash firmware */ | 133 | /* Atheros 3012 with sflash firmware */ |
134 | { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, | ||
134 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | 135 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, |
136 | { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||
135 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, | 137 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, |
138 | { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, | ||
136 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 139 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
140 | { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, | ||
137 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | 141 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
138 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, | 142 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, |
139 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, | 143 | { 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/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index f60b3899afc4..1b3a34f7f224 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile | |||
@@ -10,6 +10,7 @@ ath5k-y += phy.o | |||
10 | ath5k-y += reset.o | 10 | ath5k-y += reset.o |
11 | ath5k-y += attach.o | 11 | ath5k-y += attach.o |
12 | ath5k-y += base.o | 12 | ath5k-y += base.o |
13 | CFLAGS_base.o += -I$(src) | ||
13 | ath5k-y += led.o | 14 | ath5k-y += led.o |
14 | ath5k-y += rfkill.o | 15 | ath5k-y += rfkill.o |
15 | ath5k-y += ani.o | 16 | ath5k-y += ani.o |
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/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h index 00f015819344..c6eef519bb61 100644 --- a/drivers/net/wireless/ath/ath5k/trace.h +++ b/drivers/net/wireless/ath/ath5k/trace.h | |||
@@ -97,7 +97,7 @@ TRACE_EVENT(ath5k_tx_complete, | |||
97 | #if defined(CONFIG_ATH5K_TRACER) && !defined(__CHECKER__) | 97 | #if defined(CONFIG_ATH5K_TRACER) && !defined(__CHECKER__) |
98 | 98 | ||
99 | #undef TRACE_INCLUDE_PATH | 99 | #undef TRACE_INCLUDE_PATH |
100 | #define TRACE_INCLUDE_PATH ../../drivers/net/wireless/ath/ath5k | 100 | #define TRACE_INCLUDE_PATH . |
101 | #undef TRACE_INCLUDE_FILE | 101 | #undef TRACE_INCLUDE_FILE |
102 | #define TRACE_INCLUDE_FILE trace | 102 | #define TRACE_INCLUDE_FILE trace |
103 | 103 | ||
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 28c413f861a2..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 | } |
@@ -3661,7 +3663,6 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, | |||
3661 | vif->sme_state = SME_DISCONNECTED; | 3663 | vif->sme_state = SME_DISCONNECTED; |
3662 | set_bit(WLAN_ENABLED, &vif->flags); | 3664 | set_bit(WLAN_ENABLED, &vif->flags); |
3663 | ar->wlan_pwr_state = WLAN_POWER_STATE_ON; | 3665 | ar->wlan_pwr_state = WLAN_POWER_STATE_ON; |
3664 | set_bit(NETDEV_REGISTERED, &vif->flags); | ||
3665 | 3666 | ||
3666 | if (type == NL80211_IFTYPE_ADHOC) | 3667 | if (type == NL80211_IFTYPE_ADHOC) |
3667 | 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..1a1ea7881b4d --- /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 %zd", | ||
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 %zd", | ||
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 %zd\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 %zd\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 %zd\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 %zd\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 %zd\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/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index fd69376ecc83..391da5ad6a99 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "hw-ops.h" | 18 | #include "hw-ops.h" |
19 | #include "../regd.h" | 19 | #include "../regd.h" |
20 | #include "ar9002_phy.h" | 20 | #include "ar9002_phy.h" |
21 | #include "ar5008_initvals.h" | ||
21 | 22 | ||
22 | /* All code below is for AR5008, AR9001, AR9002 */ | 23 | /* All code below is for AR5008, AR9001, AR9002 */ |
23 | 24 | ||
@@ -43,23 +44,16 @@ static const int m2ThreshLowExt_off = 127; | |||
43 | static const int m1ThreshExt_off = 127; | 44 | static const int m1ThreshExt_off = 127; |
44 | static const int m2ThreshExt_off = 127; | 45 | static const int m2ThreshExt_off = 127; |
45 | 46 | ||
47 | static const struct ar5416IniArray bank0 = STATIC_INI_ARRAY(ar5416Bank0); | ||
48 | static const struct ar5416IniArray bank1 = STATIC_INI_ARRAY(ar5416Bank1); | ||
49 | static const struct ar5416IniArray bank2 = STATIC_INI_ARRAY(ar5416Bank2); | ||
50 | static const struct ar5416IniArray bank3 = STATIC_INI_ARRAY(ar5416Bank3); | ||
51 | static const struct ar5416IniArray bank7 = STATIC_INI_ARRAY(ar5416Bank7); | ||
46 | 52 | ||
47 | static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array, | 53 | static void ar5008_write_bank6(struct ath_hw *ah, unsigned int *writecnt) |
48 | int col) | ||
49 | { | ||
50 | int i; | ||
51 | |||
52 | for (i = 0; i < array->ia_rows; i++) | ||
53 | bank[i] = INI_RA(array, i, col); | ||
54 | } | ||
55 | |||
56 | |||
57 | #define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \ | ||
58 | ar5008_write_rf_array(ah, iniarray, regData, &(regWr)) | ||
59 | |||
60 | static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array, | ||
61 | u32 *data, unsigned int *writecnt) | ||
62 | { | 54 | { |
55 | struct ar5416IniArray *array = &ah->iniBank6; | ||
56 | u32 *data = ah->analogBank6Data; | ||
63 | int r; | 57 | int r; |
64 | 58 | ||
65 | ENABLE_REGWRITE_BUFFER(ah); | 59 | ENABLE_REGWRITE_BUFFER(ah); |
@@ -165,7 +159,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq) | |||
165 | ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); | 159 | ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); |
166 | 160 | ||
167 | /* write Bank 6 with new params */ | 161 | /* write Bank 6 with new params */ |
168 | REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes); | 162 | ar5008_write_bank6(ah, ®_writes); |
169 | } | 163 | } |
170 | 164 | ||
171 | /** | 165 | /** |
@@ -469,31 +463,16 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah, | |||
469 | */ | 463 | */ |
470 | static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) | 464 | static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) |
471 | { | 465 | { |
472 | #define ATH_ALLOC_BANK(bank, size) do { \ | 466 | int size = ah->iniBank6.ia_rows * sizeof(u32); |
473 | bank = devm_kzalloc(ah->dev, sizeof(u32) * size, GFP_KERNEL); \ | ||
474 | if (!bank) \ | ||
475 | goto error; \ | ||
476 | } while (0); | ||
477 | |||
478 | struct ath_common *common = ath9k_hw_common(ah); | ||
479 | 467 | ||
480 | if (AR_SREV_9280_20_OR_LATER(ah)) | 468 | if (AR_SREV_9280_20_OR_LATER(ah)) |
481 | return 0; | 469 | return 0; |
482 | 470 | ||
483 | ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); | 471 | ah->analogBank6Data = devm_kzalloc(ah->dev, size, GFP_KERNEL); |
484 | ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); | 472 | if (!ah->analogBank6Data) |
485 | ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows); | 473 | return -ENOMEM; |
486 | ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows); | ||
487 | ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows); | ||
488 | ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows); | ||
489 | ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows); | ||
490 | ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows); | ||
491 | 474 | ||
492 | return 0; | 475 | return 0; |
493 | #undef ATH_ALLOC_BANK | ||
494 | error: | ||
495 | ath_err(common, "Cannot allocate RF banks\n"); | ||
496 | return -ENOMEM; | ||
497 | } | 476 | } |
498 | 477 | ||
499 | 478 | ||
@@ -517,6 +496,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, | |||
517 | u32 ob5GHz = 0, db5GHz = 0; | 496 | u32 ob5GHz = 0, db5GHz = 0; |
518 | u32 ob2GHz = 0, db2GHz = 0; | 497 | u32 ob2GHz = 0, db2GHz = 0; |
519 | int regWrites = 0; | 498 | int regWrites = 0; |
499 | int i; | ||
520 | 500 | ||
521 | /* | 501 | /* |
522 | * Software does not need to program bank data | 502 | * Software does not need to program bank data |
@@ -529,25 +509,8 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, | |||
529 | /* Setup rf parameters */ | 509 | /* Setup rf parameters */ |
530 | eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); | 510 | eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); |
531 | 511 | ||
532 | /* Setup Bank 0 Write */ | 512 | for (i = 0; i < ah->iniBank6.ia_rows; i++) |
533 | ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1); | 513 | ah->analogBank6Data[i] = INI_RA(&ah->iniBank6, i, modesIndex); |
534 | |||
535 | /* Setup Bank 1 Write */ | ||
536 | ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1); | ||
537 | |||
538 | /* Setup Bank 2 Write */ | ||
539 | ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1); | ||
540 | |||
541 | /* Setup Bank 6 Write */ | ||
542 | ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3, | ||
543 | modesIndex); | ||
544 | { | ||
545 | int i; | ||
546 | for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) { | ||
547 | ah->analogBank6Data[i] = | ||
548 | INI_RA(&ah->iniBank6TPC, i, modesIndex); | ||
549 | } | ||
550 | } | ||
551 | 514 | ||
552 | /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ | 515 | /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ |
553 | if (eepMinorRev >= 2) { | 516 | if (eepMinorRev >= 2) { |
@@ -568,22 +531,13 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, | |||
568 | } | 531 | } |
569 | } | 532 | } |
570 | 533 | ||
571 | /* Setup Bank 7 Setup */ | ||
572 | ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1); | ||
573 | |||
574 | /* Write Analog registers */ | 534 | /* Write Analog registers */ |
575 | REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, | 535 | REG_WRITE_ARRAY(&bank0, 1, regWrites); |
576 | regWrites); | 536 | REG_WRITE_ARRAY(&bank1, 1, regWrites); |
577 | REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, | 537 | REG_WRITE_ARRAY(&bank2, 1, regWrites); |
578 | regWrites); | 538 | REG_WRITE_ARRAY(&bank3, modesIndex, regWrites); |
579 | REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data, | 539 | ar5008_write_bank6(ah, ®Writes); |
580 | regWrites); | 540 | REG_WRITE_ARRAY(&bank7, 1, regWrites); |
581 | REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data, | ||
582 | regWrites); | ||
583 | REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data, | ||
584 | regWrites); | ||
585 | REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data, | ||
586 | regWrites); | ||
587 | 541 | ||
588 | return true; | 542 | return true; |
589 | } | 543 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index c55e5bbafc46..9f589744a9f9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -731,7 +731,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
731 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | 731 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, |
732 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { | 732 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { |
733 | ath_dbg(common, CALIBRATE, | 733 | ath_dbg(common, CALIBRATE, |
734 | "offset calibration failed to complete in 1ms; noisy environment?\n"); | 734 | "offset calibration failed to complete in %d ms; noisy environment?\n", |
735 | AH_WAIT_TIMEOUT / 1000); | ||
735 | return false; | 736 | return false; |
736 | } | 737 | } |
737 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); | 738 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); |
@@ -745,7 +746,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
745 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | 746 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, |
746 | 0, AH_WAIT_TIMEOUT)) { | 747 | 0, AH_WAIT_TIMEOUT)) { |
747 | ath_dbg(common, CALIBRATE, | 748 | ath_dbg(common, CALIBRATE, |
748 | "offset calibration failed to complete in 1ms; noisy environment?\n"); | 749 | "offset calibration failed to complete in %d ms; noisy environment?\n", |
750 | AH_WAIT_TIMEOUT / 1000); | ||
749 | return false; | 751 | return false; |
750 | } | 752 | } |
751 | 753 | ||
@@ -841,7 +843,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
841 | AR_PHY_AGC_CONTROL_CAL, | 843 | AR_PHY_AGC_CONTROL_CAL, |
842 | 0, AH_WAIT_TIMEOUT)) { | 844 | 0, AH_WAIT_TIMEOUT)) { |
843 | ath_dbg(common, CALIBRATE, | 845 | ath_dbg(common, CALIBRATE, |
844 | "offset calibration failed to complete in 1ms; noisy environment?\n"); | 846 | "offset calibration failed to complete in %d ms; noisy environment?\n", |
847 | AH_WAIT_TIMEOUT / 1000); | ||
845 | return false; | 848 | return false; |
846 | } | 849 | } |
847 | 850 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index f053d978540e..830daa12feb6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -67,12 +67,10 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah) | |||
67 | } else if (AR_SREV_9100_OR_LATER(ah)) { | 67 | } else if (AR_SREV_9100_OR_LATER(ah)) { |
68 | INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100); | 68 | INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100); |
69 | INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100); | 69 | INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100); |
70 | INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100); | ||
71 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100); | 70 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100); |
72 | } else { | 71 | } else { |
73 | INIT_INI_ARRAY(&ah->iniModes, ar5416Modes); | 72 | INIT_INI_ARRAY(&ah->iniModes, ar5416Modes); |
74 | INIT_INI_ARRAY(&ah->iniCommon, ar5416Common); | 73 | INIT_INI_ARRAY(&ah->iniCommon, ar5416Common); |
75 | INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC); | ||
76 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac); | 74 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac); |
77 | } | 75 | } |
78 | 76 | ||
@@ -80,20 +78,11 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah) | |||
80 | /* Common for AR5416, AR913x, AR9160 */ | 78 | /* Common for AR5416, AR913x, AR9160 */ |
81 | INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain); | 79 | INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain); |
82 | 80 | ||
83 | INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0); | ||
84 | INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1); | ||
85 | INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2); | ||
86 | INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3); | ||
87 | INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7); | ||
88 | |||
89 | /* Common for AR5416, AR9160 */ | ||
90 | if (!AR_SREV_9100(ah)) | ||
91 | INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6); | ||
92 | |||
93 | /* Common for AR913x, AR9160 */ | 81 | /* Common for AR913x, AR9160 */ |
94 | if (!AR_SREV_5416(ah)) | 82 | if (!AR_SREV_5416(ah)) |
95 | INIT_INI_ARRAY(&ah->iniBank6TPC, | 83 | INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100); |
96 | ar5416Bank6TPC_9100); | 84 | else |
85 | INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC); | ||
97 | } | 86 | } |
98 | 87 | ||
99 | /* iniAddac needs to be modified for these chips */ | 88 | /* iniAddac needs to be modified for these chips */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 4cc13940c895..639ba7d18ea4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -1023,6 +1023,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
1023 | AR_PHY_AGC_CONTROL_FLTR_CAL | | 1023 | AR_PHY_AGC_CONTROL_FLTR_CAL | |
1024 | AR_PHY_AGC_CONTROL_PKDET_CAL; | 1024 | AR_PHY_AGC_CONTROL_PKDET_CAL; |
1025 | 1025 | ||
1026 | /* Use chip chainmask only for calibration */ | ||
1026 | ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); | 1027 | ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); |
1027 | 1028 | ||
1028 | if (rtt) { | 1029 | if (rtt) { |
@@ -1125,7 +1126,8 @@ skip_tx_iqcal: | |||
1125 | ar9003_hw_rtt_disable(ah); | 1126 | ar9003_hw_rtt_disable(ah); |
1126 | 1127 | ||
1127 | ath_dbg(common, CALIBRATE, | 1128 | ath_dbg(common, CALIBRATE, |
1128 | "offset calibration failed to complete in 1ms; noisy environment?\n"); | 1129 | "offset calibration failed to complete in %d ms; noisy environment?\n", |
1130 | AH_WAIT_TIMEOUT / 1000); | ||
1129 | return false; | 1131 | return false; |
1130 | } | 1132 | } |
1131 | 1133 | ||
@@ -1150,6 +1152,9 @@ skip_tx_iqcal: | |||
1150 | ar9003_hw_rtt_disable(ah); | 1152 | ar9003_hw_rtt_disable(ah); |
1151 | } | 1153 | } |
1152 | 1154 | ||
1155 | /* Revert chainmask to runtime parameters */ | ||
1156 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); | ||
1157 | |||
1153 | /* Initialize list pointers */ | 1158 | /* Initialize list pointers */ |
1154 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 1159 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
1155 | 1160 | ||
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/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index a56b2416e2f9..86d35726edb4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -311,6 +311,7 @@ struct ath_rx_edma { | |||
311 | struct ath_rx { | 311 | struct ath_rx { |
312 | u8 defant; | 312 | u8 defant; |
313 | u8 rxotherant; | 313 | u8 rxotherant; |
314 | bool discard_next; | ||
314 | u32 *rxlink; | 315 | u32 *rxlink; |
315 | u32 num_pkts; | 316 | u32 num_pkts; |
316 | unsigned int rxfilter; | 317 | unsigned int rxfilter; |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index b184f1ff0d38..7304e7585009 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/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 60dcb6c22db9..3d70b8c2bcdd 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -33,6 +33,12 @@ struct ar5416IniArray { | |||
33 | u32 ia_columns; | 33 | u32 ia_columns; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | #define STATIC_INI_ARRAY(array) { \ | ||
37 | .ia_array = (u32 *)(array), \ | ||
38 | .ia_rows = ARRAY_SIZE(array), \ | ||
39 | .ia_columns = ARRAY_SIZE(array[0]), \ | ||
40 | } | ||
41 | |||
36 | #define INIT_INI_ARRAY(iniarray, array) do { \ | 42 | #define INIT_INI_ARRAY(iniarray, array) do { \ |
37 | (iniarray)->ia_array = (u32 *)(array); \ | 43 | (iniarray)->ia_array = (u32 *)(array); \ |
38 | (iniarray)->ia_rows = ARRAY_SIZE(array); \ | 44 | (iniarray)->ia_rows = ARRAY_SIZE(array); \ |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 6c78fe7ca54d..344fdde1d7a3 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -27,20 +27,6 @@ MODULE_AUTHOR("Atheros Communications"); | |||
27 | MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards."); | 27 | MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards."); |
28 | MODULE_LICENSE("Dual BSD/GPL"); | 28 | MODULE_LICENSE("Dual BSD/GPL"); |
29 | 29 | ||
30 | int ath9k_cmn_padpos(__le16 frame_control) | ||
31 | { | ||
32 | int padpos = 24; | ||
33 | if (ieee80211_has_a4(frame_control)) { | ||
34 | padpos += ETH_ALEN; | ||
35 | } | ||
36 | if (ieee80211_is_data_qos(frame_control)) { | ||
37 | padpos += IEEE80211_QOS_CTL_LEN; | ||
38 | } | ||
39 | |||
40 | return padpos; | ||
41 | } | ||
42 | EXPORT_SYMBOL(ath9k_cmn_padpos); | ||
43 | |||
44 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) | 30 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) |
45 | { | 31 | { |
46 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 32 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 5f845beeb18b..207d06995b15 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,9 +40,8 @@ | |||
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); | ||
46 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 45 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
47 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, | 46 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, |
48 | struct ieee80211_channel *chan, | 47 | struct ieee80211_channel *chan, |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 3714b971d18e..e6307b86363a 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); |
@@ -2067,7 +2072,7 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
2067 | &fops_modal_eeprom); | 2072 | &fops_modal_eeprom); |
2068 | sc->rfs_chan_spec_scan = relay_open("spectral_scan", | 2073 | sc->rfs_chan_spec_scan = relay_open("spectral_scan", |
2069 | sc->debug.debugfs_phy, | 2074 | sc->debug.debugfs_phy, |
2070 | 262144, 4, &rfs_spec_scan_cb, | 2075 | 1024, 256, &rfs_spec_scan_cb, |
2071 | NULL); | 2076 | NULL); |
2072 | debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, | 2077 | debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, |
2073 | sc->debug.debugfs_phy, sc, | 2078 | sc->debug.debugfs_phy, sc, |
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/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c index ecc81792f2dc..508f8b33f0ef 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.c +++ b/drivers/net/wireless/ath/ath9k/dfs.c | |||
@@ -193,9 +193,7 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | |||
193 | DFS_STAT_INC(sc, pulses_processed); | 193 | DFS_STAT_INC(sc, pulses_processed); |
194 | if (pd != NULL && pd->add_pulse(pd, &pe)) { | 194 | if (pd != NULL && pd->add_pulse(pd, &pe)) { |
195 | DFS_STAT_INC(sc, radar_detected); | 195 | DFS_STAT_INC(sc, radar_detected); |
196 | /* | 196 | ieee80211_radar_detected(sc->hw); |
197 | * TODO: forward radar event to DFS management layer | ||
198 | */ | ||
199 | } | 197 | } |
200 | } | 198 | } |
201 | } | 199 | } |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c index 55d28072adeb..b7611b7bbe43 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.c +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c | |||
@@ -105,6 +105,24 @@ static ssize_t write_file_dfs(struct file *file, const char __user *user_buf, | |||
105 | return count; | 105 | return count; |
106 | } | 106 | } |
107 | 107 | ||
108 | static ssize_t write_file_simulate_radar(struct file *file, | ||
109 | const char __user *user_buf, | ||
110 | size_t count, loff_t *ppos) | ||
111 | { | ||
112 | struct ath_softc *sc = file->private_data; | ||
113 | |||
114 | ieee80211_radar_detected(sc->hw); | ||
115 | |||
116 | return count; | ||
117 | } | ||
118 | |||
119 | static const struct file_operations fops_simulate_radar = { | ||
120 | .write = write_file_simulate_radar, | ||
121 | .open = simple_open, | ||
122 | .owner = THIS_MODULE, | ||
123 | .llseek = default_llseek, | ||
124 | }; | ||
125 | |||
108 | static const struct file_operations fops_dfs_stats = { | 126 | static const struct file_operations fops_dfs_stats = { |
109 | .read = read_file_dfs, | 127 | .read = read_file_dfs, |
110 | .write = write_file_dfs, | 128 | .write = write_file_dfs, |
@@ -117,4 +135,6 @@ void ath9k_dfs_init_debug(struct ath_softc *sc) | |||
117 | { | 135 | { |
118 | debugfs_create_file("dfs_stats", S_IRUSR, | 136 | debugfs_create_file("dfs_stats", S_IRUSR, |
119 | sc->debug.debugfs_phy, sc, &fops_dfs_stats); | 137 | sc->debug.debugfs_phy, sc, &fops_dfs_stats); |
138 | debugfs_create_file("dfs_simulate_radar", S_IWUSR, | ||
139 | sc->debug.debugfs_phy, sc, &fops_simulate_radar); | ||
120 | } | 140 | } |
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_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index d0ce1f5bba10..f13f458dd656 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -308,7 +308,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, | |||
308 | while(skb) { | 308 | while(skb) { |
309 | hdr = (struct ieee80211_hdr *) skb->data; | 309 | hdr = (struct ieee80211_hdr *) skb->data; |
310 | 310 | ||
311 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 311 | padpos = ieee80211_hdrlen(hdr->frame_control); |
312 | padsize = padpos & 3; | 312 | padsize = padpos & 3; |
313 | if (padsize && skb->len > padpos) { | 313 | if (padsize && skb->len > padpos) { |
314 | if (skb_headroom(skb) < padsize) { | 314 | if (skb_headroom(skb) < padsize) { |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 098e3545e512..0743a47cef8f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -866,7 +866,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, | |||
866 | hdr = (struct ieee80211_hdr *) skb->data; | 866 | hdr = (struct ieee80211_hdr *) skb->data; |
867 | 867 | ||
868 | /* Add the padding after the header if this is not already done */ | 868 | /* Add the padding after the header if this is not already done */ |
869 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 869 | padpos = ieee80211_hdrlen(hdr->frame_control); |
870 | padsize = padpos & 3; | 870 | padsize = padpos & 3; |
871 | if (padsize && skb->len > padpos) { | 871 | if (padsize && skb->len > padpos) { |
872 | if (skb_headroom(skb) < padsize) { | 872 | if (skb_headroom(skb) < padsize) { |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 306c55019e77..6bd0e92ea2aa 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -966,7 +966,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
966 | struct sk_buff *skb = rxbuf->skb; | 966 | struct sk_buff *skb = rxbuf->skb; |
967 | struct ath_common *common = ath9k_hw_common(priv->ah); | 967 | struct ath_common *common = ath9k_hw_common(priv->ah); |
968 | struct ath_htc_rx_status *rxstatus; | 968 | struct ath_htc_rx_status *rxstatus; |
969 | int hdrlen, padpos, padsize; | 969 | int hdrlen, padsize; |
970 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | 970 | int last_rssi = ATH_RSSI_DUMMY_MARKER; |
971 | __le16 fc; | 971 | __le16 fc; |
972 | 972 | ||
@@ -996,11 +996,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
996 | fc = hdr->frame_control; | 996 | fc = hdr->frame_control; |
997 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 997 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
998 | 998 | ||
999 | padpos = ath9k_cmn_padpos(fc); | 999 | padsize = hdrlen & 3; |
1000 | 1000 | if (padsize && skb->len >= hdrlen+padsize+FCS_LEN) { | |
1001 | padsize = padpos & 3; | 1001 | memmove(skb->data + padsize, skb->data, hdrlen); |
1002 | if (padsize && skb->len >= padpos+padsize+FCS_LEN) { | ||
1003 | memmove(skb->data + padsize, skb->data, padpos); | ||
1004 | skb_pull(skb, padsize); | 1002 | skb_pull(skb, padsize); |
1005 | } | 1003 | } |
1006 | 1004 | ||
@@ -1067,15 +1065,19 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
1067 | 1065 | ||
1068 | last_rssi = priv->rx.last_rssi; | 1066 | last_rssi = priv->rx.last_rssi; |
1069 | 1067 | ||
1070 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 1068 | if (ieee80211_is_beacon(hdr->frame_control) && |
1071 | rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, | 1069 | !is_zero_ether_addr(common->curbssid) && |
1072 | ATH_RSSI_EP_MULTIPLIER); | 1070 | ether_addr_equal(hdr->addr3, common->curbssid)) { |
1071 | s8 rssi = rxbuf->rxstatus.rs_rssi; | ||
1072 | |||
1073 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | ||
1074 | rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); | ||
1073 | 1075 | ||
1074 | if (rxbuf->rxstatus.rs_rssi < 0) | 1076 | if (rssi < 0) |
1075 | rxbuf->rxstatus.rs_rssi = 0; | 1077 | rssi = 0; |
1076 | 1078 | ||
1077 | if (ieee80211_is_beacon(fc)) | 1079 | priv->ah->stats.avgbrssi = rssi; |
1078 | priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; | 1080 | } |
1079 | 1081 | ||
1080 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); | 1082 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); |
1081 | rx_status->band = hw->conf.chandef.chan->band; | 1083 | rx_status->band = hw->conf.chandef.chan->band; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index d5e6a38fe74b..8a980a4bf4ec 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1464,7 +1464,9 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, | |||
1464 | reset_type = ATH9K_RESET_POWER_ON; | 1464 | reset_type = ATH9K_RESET_POWER_ON; |
1465 | else | 1465 | else |
1466 | reset_type = ATH9K_RESET_COLD; | 1466 | reset_type = ATH9K_RESET_COLD; |
1467 | } | 1467 | } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) || |
1468 | (REG_READ(ah, AR_CR) & AR_CR_RXE)) | ||
1469 | reset_type = ATH9K_RESET_COLD; | ||
1468 | 1470 | ||
1469 | if (!ath9k_hw_set_reset_reg(ah, reset_type)) | 1471 | if (!ath9k_hw_set_reset_reg(ah, reset_type)) |
1470 | return false; | 1472 | return false; |
@@ -1668,6 +1670,104 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) | |||
1668 | } | 1670 | } |
1669 | EXPORT_SYMBOL(ath9k_hw_check_alive); | 1671 | EXPORT_SYMBOL(ath9k_hw_check_alive); |
1670 | 1672 | ||
1673 | static void ath9k_hw_init_mfp(struct ath_hw *ah) | ||
1674 | { | ||
1675 | /* Setup MFP options for CCMP */ | ||
1676 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
1677 | /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt | ||
1678 | * frames when constructing CCMP AAD. */ | ||
1679 | REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, | ||
1680 | 0xc7ff); | ||
1681 | ah->sw_mgmt_crypto = false; | ||
1682 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
1683 | /* Disable hardware crypto for management frames */ | ||
1684 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, | ||
1685 | AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); | ||
1686 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, | ||
1687 | AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); | ||
1688 | ah->sw_mgmt_crypto = true; | ||
1689 | } else { | ||
1690 | ah->sw_mgmt_crypto = true; | ||
1691 | } | ||
1692 | } | ||
1693 | |||
1694 | static void ath9k_hw_reset_opmode(struct ath_hw *ah, | ||
1695 | u32 macStaId1, u32 saveDefAntenna) | ||
1696 | { | ||
1697 | struct ath_common *common = ath9k_hw_common(ah); | ||
1698 | |||
1699 | ENABLE_REGWRITE_BUFFER(ah); | ||
1700 | |||
1701 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); | ||
1702 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) | ||
1703 | | macStaId1 | ||
1704 | | AR_STA_ID1_RTS_USE_DEF | ||
1705 | | (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | ||
1706 | | ah->sta_id1_defaults); | ||
1707 | ath_hw_setbssidmask(common); | ||
1708 | REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); | ||
1709 | ath9k_hw_write_associd(ah); | ||
1710 | REG_WRITE(ah, AR_ISR, ~0); | ||
1711 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | ||
1712 | |||
1713 | REGWRITE_BUFFER_FLUSH(ah); | ||
1714 | |||
1715 | ath9k_hw_set_operating_mode(ah, ah->opmode); | ||
1716 | } | ||
1717 | |||
1718 | static void ath9k_hw_init_queues(struct ath_hw *ah) | ||
1719 | { | ||
1720 | int i; | ||
1721 | |||
1722 | ENABLE_REGWRITE_BUFFER(ah); | ||
1723 | |||
1724 | for (i = 0; i < AR_NUM_DCU; i++) | ||
1725 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | ||
1726 | |||
1727 | REGWRITE_BUFFER_FLUSH(ah); | ||
1728 | |||
1729 | ah->intr_txqs = 0; | ||
1730 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1731 | ath9k_hw_resettxqueue(ah, i); | ||
1732 | } | ||
1733 | |||
1734 | /* | ||
1735 | * For big endian systems turn on swapping for descriptors | ||
1736 | */ | ||
1737 | static void ath9k_hw_init_desc(struct ath_hw *ah) | ||
1738 | { | ||
1739 | struct ath_common *common = ath9k_hw_common(ah); | ||
1740 | |||
1741 | if (AR_SREV_9100(ah)) { | ||
1742 | u32 mask; | ||
1743 | mask = REG_READ(ah, AR_CFG); | ||
1744 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { | ||
1745 | ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n", | ||
1746 | mask); | ||
1747 | } else { | ||
1748 | mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; | ||
1749 | REG_WRITE(ah, AR_CFG, mask); | ||
1750 | ath_dbg(common, RESET, "Setting CFG 0x%x\n", | ||
1751 | REG_READ(ah, AR_CFG)); | ||
1752 | } | ||
1753 | } else { | ||
1754 | if (common->bus_ops->ath_bus_type == ATH_USB) { | ||
1755 | /* Configure AR9271 target WLAN */ | ||
1756 | if (AR_SREV_9271(ah)) | ||
1757 | REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); | ||
1758 | else | ||
1759 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1760 | } | ||
1761 | #ifdef __BIG_ENDIAN | ||
1762 | else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || | ||
1763 | AR_SREV_9550(ah)) | ||
1764 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); | ||
1765 | else | ||
1766 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1767 | #endif | ||
1768 | } | ||
1769 | } | ||
1770 | |||
1671 | /* | 1771 | /* |
1672 | * Fast channel change: | 1772 | * Fast channel change: |
1673 | * (Change synthesizer based on channel freq without resetting chip) | 1773 | * (Change synthesizer based on channel freq without resetting chip) |
@@ -1745,7 +1845,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1745 | u32 saveDefAntenna; | 1845 | u32 saveDefAntenna; |
1746 | u32 macStaId1; | 1846 | u32 macStaId1; |
1747 | u64 tsf = 0; | 1847 | u64 tsf = 0; |
1748 | int i, r; | 1848 | int r; |
1749 | bool start_mci_reset = false; | 1849 | bool start_mci_reset = false; |
1750 | bool save_fullsleep = ah->chip_fullsleep; | 1850 | bool save_fullsleep = ah->chip_fullsleep; |
1751 | 1851 | ||
@@ -1762,10 +1862,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1762 | ath9k_hw_getnf(ah, ah->curchan); | 1862 | ath9k_hw_getnf(ah, ah->curchan); |
1763 | 1863 | ||
1764 | ah->caldata = caldata; | 1864 | ah->caldata = caldata; |
1765 | if (caldata && | 1865 | if (caldata && (chan->channel != caldata->channel || |
1766 | (chan->channel != caldata->channel || | 1866 | chan->channelFlags != caldata->channelFlags)) { |
1767 | (chan->channelFlags & ~CHANNEL_CW_INT) != | ||
1768 | (caldata->channelFlags & ~CHANNEL_CW_INT))) { | ||
1769 | /* Operating channel changed, reset channel calibration data */ | 1867 | /* Operating channel changed, reset channel calibration data */ |
1770 | memset(caldata, 0, sizeof(*caldata)); | 1868 | memset(caldata, 0, sizeof(*caldata)); |
1771 | ath9k_init_nfcal_hist_buffer(ah, chan); | 1869 | ath9k_init_nfcal_hist_buffer(ah, chan); |
@@ -1852,22 +1950,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1852 | ath9k_hw_settsf64(ah, tsf); | 1950 | ath9k_hw_settsf64(ah, tsf); |
1853 | } | 1951 | } |
1854 | 1952 | ||
1855 | /* Setup MFP options for CCMP */ | 1953 | ath9k_hw_init_mfp(ah); |
1856 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
1857 | /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt | ||
1858 | * frames when constructing CCMP AAD. */ | ||
1859 | REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, | ||
1860 | 0xc7ff); | ||
1861 | ah->sw_mgmt_crypto = false; | ||
1862 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
1863 | /* Disable hardware crypto for management frames */ | ||
1864 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, | ||
1865 | AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); | ||
1866 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, | ||
1867 | AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); | ||
1868 | ah->sw_mgmt_crypto = true; | ||
1869 | } else | ||
1870 | ah->sw_mgmt_crypto = true; | ||
1871 | 1954 | ||
1872 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | 1955 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) |
1873 | ath9k_hw_set_delta_slope(ah, chan); | 1956 | ath9k_hw_set_delta_slope(ah, chan); |
@@ -1875,24 +1958,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1875 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1958 | ath9k_hw_spur_mitigate_freq(ah, chan); |
1876 | ah->eep_ops->set_board_values(ah, chan); | 1959 | ah->eep_ops->set_board_values(ah, chan); |
1877 | 1960 | ||
1878 | ENABLE_REGWRITE_BUFFER(ah); | 1961 | ath9k_hw_reset_opmode(ah, macStaId1, saveDefAntenna); |
1879 | |||
1880 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); | ||
1881 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) | ||
1882 | | macStaId1 | ||
1883 | | AR_STA_ID1_RTS_USE_DEF | ||
1884 | | (ah->config. | ||
1885 | ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | ||
1886 | | ah->sta_id1_defaults); | ||
1887 | ath_hw_setbssidmask(common); | ||
1888 | REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); | ||
1889 | ath9k_hw_write_associd(ah); | ||
1890 | REG_WRITE(ah, AR_ISR, ~0); | ||
1891 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | ||
1892 | |||
1893 | REGWRITE_BUFFER_FLUSH(ah); | ||
1894 | |||
1895 | ath9k_hw_set_operating_mode(ah, ah->opmode); | ||
1896 | 1962 | ||
1897 | r = ath9k_hw_rf_set_freq(ah, chan); | 1963 | r = ath9k_hw_rf_set_freq(ah, chan); |
1898 | if (r) | 1964 | if (r) |
@@ -1900,17 +1966,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1900 | 1966 | ||
1901 | ath9k_hw_set_clockrate(ah); | 1967 | ath9k_hw_set_clockrate(ah); |
1902 | 1968 | ||
1903 | ENABLE_REGWRITE_BUFFER(ah); | 1969 | ath9k_hw_init_queues(ah); |
1904 | |||
1905 | for (i = 0; i < AR_NUM_DCU; i++) | ||
1906 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | ||
1907 | |||
1908 | REGWRITE_BUFFER_FLUSH(ah); | ||
1909 | |||
1910 | ah->intr_txqs = 0; | ||
1911 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1912 | ath9k_hw_resettxqueue(ah, i); | ||
1913 | |||
1914 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); | 1970 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); |
1915 | ath9k_hw_ani_cache_ini_regs(ah); | 1971 | ath9k_hw_ani_cache_ini_regs(ah); |
1916 | ath9k_hw_init_qos(ah); | 1972 | ath9k_hw_init_qos(ah); |
@@ -1965,38 +2021,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1965 | 2021 | ||
1966 | REGWRITE_BUFFER_FLUSH(ah); | 2022 | REGWRITE_BUFFER_FLUSH(ah); |
1967 | 2023 | ||
1968 | /* | 2024 | ath9k_hw_init_desc(ah); |
1969 | * For big endian systems turn on swapping for descriptors | ||
1970 | */ | ||
1971 | if (AR_SREV_9100(ah)) { | ||
1972 | u32 mask; | ||
1973 | mask = REG_READ(ah, AR_CFG); | ||
1974 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { | ||
1975 | ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n", | ||
1976 | mask); | ||
1977 | } else { | ||
1978 | mask = | ||
1979 | INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; | ||
1980 | REG_WRITE(ah, AR_CFG, mask); | ||
1981 | ath_dbg(common, RESET, "Setting CFG 0x%x\n", | ||
1982 | REG_READ(ah, AR_CFG)); | ||
1983 | } | ||
1984 | } else { | ||
1985 | if (common->bus_ops->ath_bus_type == ATH_USB) { | ||
1986 | /* Configure AR9271 target WLAN */ | ||
1987 | if (AR_SREV_9271(ah)) | ||
1988 | REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); | ||
1989 | else | ||
1990 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1991 | } | ||
1992 | #ifdef __BIG_ENDIAN | ||
1993 | else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || | ||
1994 | AR_SREV_9550(ah)) | ||
1995 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); | ||
1996 | else | ||
1997 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1998 | #endif | ||
1999 | } | ||
2000 | 2025 | ||
2001 | if (ath9k_hw_btcoex_is_enabled(ah)) | 2026 | if (ath9k_hw_btcoex_is_enabled(ah)) |
2002 | ath9k_hw_btcoex_enable(ah); | 2027 | ath9k_hw_btcoex_enable(ah); |
@@ -2009,7 +2034,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2009 | 2034 | ||
2010 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 2035 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
2011 | ar9003_hw_bb_watchdog_config(ah); | 2036 | ar9003_hw_bb_watchdog_config(ah); |
2012 | |||
2013 | ar9003_hw_disable_phy_restart(ah); | 2037 | ar9003_hw_disable_phy_restart(ah); |
2014 | } | 2038 | } |
2015 | 2039 | ||
@@ -2357,8 +2381,11 @@ static bool ath9k_hw_dfs_tested(struct ath_hw *ah) | |||
2357 | { | 2381 | { |
2358 | 2382 | ||
2359 | switch (ah->hw_version.macVersion) { | 2383 | switch (ah->hw_version.macVersion) { |
2384 | /* for temporary testing DFS with 9280 */ | ||
2385 | case AR_SREV_VERSION_9280: | ||
2360 | /* AR9580 will likely be our first target to get testing on */ | 2386 | /* AR9580 will likely be our first target to get testing on */ |
2361 | case AR_SREV_VERSION_9580: | 2387 | case AR_SREV_VERSION_9580: |
2388 | return true; | ||
2362 | default: | 2389 | default: |
2363 | return false; | 2390 | return false; |
2364 | } | 2391 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 784e81ccb903..ae3034374bc4 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 |
@@ -848,14 +847,7 @@ struct ath_hw { | |||
848 | struct ath_hw_ops ops; | 847 | struct ath_hw_ops ops; |
849 | 848 | ||
850 | /* Used to program the radio on non single-chip devices */ | 849 | /* Used to program the radio on non single-chip devices */ |
851 | u32 *analogBank0Data; | ||
852 | u32 *analogBank1Data; | ||
853 | u32 *analogBank2Data; | ||
854 | u32 *analogBank3Data; | ||
855 | u32 *analogBank6Data; | 850 | u32 *analogBank6Data; |
856 | u32 *analogBank6TPCData; | ||
857 | u32 *analogBank7Data; | ||
858 | u32 *bank6Temp; | ||
859 | 851 | ||
860 | int coverage_class; | 852 | int coverage_class; |
861 | u32 slottime; | 853 | u32 slottime; |
@@ -886,14 +878,8 @@ struct ath_hw { | |||
886 | 878 | ||
887 | struct ar5416IniArray iniModes; | 879 | struct ar5416IniArray iniModes; |
888 | struct ar5416IniArray iniCommon; | 880 | struct ar5416IniArray iniCommon; |
889 | struct ar5416IniArray iniBank0; | ||
890 | struct ar5416IniArray iniBB_RfGain; | 881 | struct ar5416IniArray iniBB_RfGain; |
891 | struct ar5416IniArray iniBank1; | ||
892 | struct ar5416IniArray iniBank2; | ||
893 | struct ar5416IniArray iniBank3; | ||
894 | struct ar5416IniArray iniBank6; | 882 | struct ar5416IniArray iniBank6; |
895 | struct ar5416IniArray iniBank6TPC; | ||
896 | struct ar5416IniArray iniBank7; | ||
897 | struct ar5416IniArray iniAddac; | 883 | struct ar5416IniArray iniAddac; |
898 | struct ar5416IniArray iniPcieSerdes; | 884 | struct ar5416IniArray iniPcieSerdes; |
899 | #ifdef CONFIG_PM_SLEEP | 885 | #ifdef CONFIG_PM_SLEEP |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index af932c9444de..3be2eb0da84a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -319,6 +319,10 @@ static void ath9k_reg_notifier(struct wiphy *wiphy, | |||
319 | ath9k_ps_wakeup(sc); | 319 | ath9k_ps_wakeup(sc); |
320 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); | 320 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); |
321 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; | 321 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; |
322 | /* synchronize DFS detector if regulatory domain changed */ | ||
323 | if (sc->dfs_detector != NULL) | ||
324 | sc->dfs_detector->set_dfs_domain(sc->dfs_detector, | ||
325 | request->dfs_region); | ||
322 | ath9k_ps_restore(sc); | 326 | ath9k_ps_restore(sc); |
323 | } | 327 | } |
324 | } | 328 | } |
@@ -727,12 +731,28 @@ static const struct ieee80211_iface_limit if_limits[] = { | |||
727 | BIT(NL80211_IFTYPE_P2P_GO) }, | 731 | BIT(NL80211_IFTYPE_P2P_GO) }, |
728 | }; | 732 | }; |
729 | 733 | ||
730 | static const struct ieee80211_iface_combination if_comb = { | 734 | |
731 | .limits = if_limits, | 735 | static const struct ieee80211_iface_limit if_dfs_limits[] = { |
732 | .n_limits = ARRAY_SIZE(if_limits), | 736 | { .max = 1, .types = BIT(NL80211_IFTYPE_AP) }, |
733 | .max_interfaces = 2048, | 737 | }; |
734 | .num_different_channels = 1, | 738 | |
735 | .beacon_int_infra_match = true, | 739 | static const struct ieee80211_iface_combination if_comb[] = { |
740 | { | ||
741 | .limits = if_limits, | ||
742 | .n_limits = ARRAY_SIZE(if_limits), | ||
743 | .max_interfaces = 2048, | ||
744 | .num_different_channels = 1, | ||
745 | .beacon_int_infra_match = true, | ||
746 | }, | ||
747 | { | ||
748 | .limits = if_dfs_limits, | ||
749 | .n_limits = ARRAY_SIZE(if_dfs_limits), | ||
750 | .max_interfaces = 1, | ||
751 | .num_different_channels = 1, | ||
752 | .beacon_int_infra_match = true, | ||
753 | .radar_detect_widths = BIT(NL80211_CHAN_NO_HT) | | ||
754 | BIT(NL80211_CHAN_HT20), | ||
755 | } | ||
736 | }; | 756 | }; |
737 | 757 | ||
738 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | 758 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) |
@@ -763,8 +783,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
763 | BIT(NL80211_IFTYPE_ADHOC) | | 783 | BIT(NL80211_IFTYPE_ADHOC) | |
764 | BIT(NL80211_IFTYPE_MESH_POINT); | 784 | BIT(NL80211_IFTYPE_MESH_POINT); |
765 | 785 | ||
766 | hw->wiphy->iface_combinations = &if_comb; | 786 | hw->wiphy->iface_combinations = if_comb; |
767 | hw->wiphy->n_iface_combinations = 1; | 787 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); |
768 | 788 | ||
769 | if (AR_SREV_5416(sc->sc_ah)) | 789 | if (AR_SREV_5416(sc->sc_ah)) |
770 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 790 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index b1433f561cd2..849259b07370 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
@@ -28,21 +28,21 @@ void ath_tx_complete_poll_work(struct work_struct *work) | |||
28 | int i; | 28 | int i; |
29 | bool needreset = false; | 29 | bool needreset = false; |
30 | 30 | ||
31 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 31 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
32 | if (ATH_TXQ_SETUP(sc, i)) { | 32 | txq = sc->tx.txq_map[i]; |
33 | txq = &sc->tx.txq[i]; | 33 | |
34 | ath_txq_lock(sc, txq); | 34 | ath_txq_lock(sc, txq); |
35 | if (txq->axq_depth) { | 35 | if (txq->axq_depth) { |
36 | if (txq->axq_tx_inprogress) { | 36 | if (txq->axq_tx_inprogress) { |
37 | needreset = true; | 37 | needreset = true; |
38 | ath_txq_unlock(sc, txq); | 38 | ath_txq_unlock(sc, txq); |
39 | break; | 39 | break; |
40 | } else { | 40 | } else { |
41 | txq->axq_tx_inprogress = true; | 41 | txq->axq_tx_inprogress = true; |
42 | } | ||
43 | } | 42 | } |
44 | ath_txq_unlock_complete(sc, txq); | ||
45 | } | 43 | } |
44 | ath_txq_unlock_complete(sc, txq); | ||
45 | } | ||
46 | 46 | ||
47 | if (needreset) { | 47 | if (needreset) { |
48 | ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, | 48 | ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, |
@@ -170,7 +170,8 @@ void ath_rx_poll(unsigned long data) | |||
170 | { | 170 | { |
171 | struct ath_softc *sc = (struct ath_softc *)data; | 171 | struct ath_softc *sc = (struct ath_softc *)data; |
172 | 172 | ||
173 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | 173 | if (!test_bit(SC_OP_INVALID, &sc->sc_flags)) |
174 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | ||
174 | } | 175 | } |
175 | 176 | ||
176 | /* | 177 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 811007ec07a7..498fee04afa0 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -615,6 +615,14 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
615 | rs->rs_status |= ATH9K_RXERR_DECRYPT; | 615 | rs->rs_status |= ATH9K_RXERR_DECRYPT; |
616 | else if (ads.ds_rxstatus8 & AR_MichaelErr) | 616 | else if (ads.ds_rxstatus8 & AR_MichaelErr) |
617 | rs->rs_status |= ATH9K_RXERR_MIC; | 617 | rs->rs_status |= ATH9K_RXERR_MIC; |
618 | } else { | ||
619 | if (ads.ds_rxstatus8 & | ||
620 | (AR_CRCErr | AR_PHYErr | AR_DecryptCRCErr | AR_MichaelErr)) | ||
621 | rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC; | ||
622 | |||
623 | /* Only up to MCS16 supported, everything above is invalid */ | ||
624 | if (rs->rs_rate >= 0x90) | ||
625 | rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC; | ||
618 | } | 626 | } |
619 | 627 | ||
620 | if (ads.ds_rxstatus8 & AR_KeyMiss) | 628 | if (ads.ds_rxstatus8 & AR_KeyMiss) |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 1ff817061ebc..5865f92998e1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -183,6 +183,7 @@ struct ath_htc_rx_status { | |||
183 | #define ATH9K_RXERR_DECRYPT 0x08 | 183 | #define ATH9K_RXERR_DECRYPT 0x08 |
184 | #define ATH9K_RXERR_MIC 0x10 | 184 | #define ATH9K_RXERR_MIC 0x10 |
185 | #define ATH9K_RXERR_KEYMISS 0x20 | 185 | #define ATH9K_RXERR_KEYMISS 0x20 |
186 | #define ATH9K_RXERR_CORRUPT_DESC 0x40 | ||
186 | 187 | ||
187 | #define ATH9K_RX_MORE 0x01 | 188 | #define ATH9K_RX_MORE 0x01 |
188 | #define ATH9K_RX_MORE_AGGR 0x02 | 189 | #define ATH9K_RX_MORE_AGGR 0x02 |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index f984a03f912c..a383483d0387 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -280,6 +280,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
280 | if (r) { | 280 | if (r) { |
281 | ath_err(common, | 281 | ath_err(common, |
282 | "Unable to reset channel, reset status %d\n", r); | 282 | "Unable to reset channel, reset status %d\n", r); |
283 | |||
284 | ath9k_hw_enable_interrupts(ah); | ||
285 | ath9k_queue_reset(sc, RESET_TYPE_BB_HANG); | ||
286 | |||
283 | goto out; | 287 | goto out; |
284 | } | 288 | } |
285 | 289 | ||
@@ -1247,10 +1251,27 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1247 | if (old_pos >= 0) | 1251 | if (old_pos >= 0) |
1248 | ath_update_survey_nf(sc, old_pos); | 1252 | ath_update_survey_nf(sc, old_pos); |
1249 | 1253 | ||
1250 | /* perform spectral scan if requested. */ | 1254 | /* |
1251 | if (sc->scanning && sc->spectral_mode == SPECTRAL_CHANSCAN) | 1255 | * Enable radar pulse detection if on a DFS channel. Spectral |
1252 | ath9k_spectral_scan_trigger(hw); | 1256 | * scanning and radar detection can not be used concurrently. |
1253 | 1257 | */ | |
1258 | if (hw->conf.radar_enabled) { | ||
1259 | u32 rxfilter; | ||
1260 | |||
1261 | /* set HW specific DFS configuration */ | ||
1262 | ath9k_hw_set_radar_params(ah); | ||
1263 | rxfilter = ath9k_hw_getrxfilter(ah); | ||
1264 | rxfilter |= ATH9K_RX_FILTER_PHYRADAR | | ||
1265 | ATH9K_RX_FILTER_PHYERR; | ||
1266 | ath9k_hw_setrxfilter(ah, rxfilter); | ||
1267 | ath_dbg(common, DFS, "DFS enabled at freq %d\n", | ||
1268 | curchan->center_freq); | ||
1269 | } else { | ||
1270 | /* perform spectral scan if requested. */ | ||
1271 | if (sc->scanning && | ||
1272 | sc->spectral_mode == SPECTRAL_CHANSCAN) | ||
1273 | ath9k_spectral_scan_trigger(hw); | ||
1274 | } | ||
1254 | } | 1275 | } |
1255 | 1276 | ||
1256 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1277 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index c90ca57e3722..ebb8d361b981 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -381,6 +381,10 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
381 | rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | 381 | rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST |
382 | | ATH9K_RX_FILTER_MCAST; | 382 | | ATH9K_RX_FILTER_MCAST; |
383 | 383 | ||
384 | /* if operating on a DFS channel, enable radar pulse detection */ | ||
385 | if (sc->hw->conf.radar_enabled) | ||
386 | rfilt |= ATH9K_RX_FILTER_PHYRADAR | ATH9K_RX_FILTER_PHYERR; | ||
387 | |||
384 | if (sc->rx.rxfilter & FIF_PROBE_REQ) | 388 | if (sc->rx.rxfilter & FIF_PROBE_REQ) |
385 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | 389 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; |
386 | 390 | ||
@@ -723,6 +727,13 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
723 | ret = ath9k_hw_rxprocdesc(ah, tds, &trs); | 727 | ret = ath9k_hw_rxprocdesc(ah, tds, &trs); |
724 | if (ret == -EINPROGRESS) | 728 | if (ret == -EINPROGRESS) |
725 | return NULL; | 729 | return NULL; |
730 | |||
731 | /* | ||
732 | * mark descriptor as zero-length and set the 'more' | ||
733 | * flag to ensure that both buffers get discarded | ||
734 | */ | ||
735 | rs->rs_datalen = 0; | ||
736 | rs->rs_more = true; | ||
726 | } | 737 | } |
727 | 738 | ||
728 | list_del(&bf->list); | 739 | list_del(&bf->list); |
@@ -929,14 +940,20 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
929 | * up the frame up to let mac80211 handle the actual error case, be it no | 940 | * up the frame up to let mac80211 handle the actual error case, be it no |
930 | * decryption key or real decryption error. This let us keep statistics there. | 941 | * decryption key or real decryption error. This let us keep statistics there. |
931 | */ | 942 | */ |
932 | static int ath9k_rx_skb_preprocess(struct ath_common *common, | 943 | static int ath9k_rx_skb_preprocess(struct ath_softc *sc, |
933 | struct ieee80211_hw *hw, | ||
934 | struct ieee80211_hdr *hdr, | 944 | struct ieee80211_hdr *hdr, |
935 | struct ath_rx_status *rx_stats, | 945 | struct ath_rx_status *rx_stats, |
936 | struct ieee80211_rx_status *rx_status, | 946 | struct ieee80211_rx_status *rx_status, |
937 | bool *decrypt_error) | 947 | bool *decrypt_error) |
938 | { | 948 | { |
939 | struct ath_hw *ah = common->ah; | 949 | struct ieee80211_hw *hw = sc->hw; |
950 | struct ath_hw *ah = sc->sc_ah; | ||
951 | struct ath_common *common = ath9k_hw_common(ah); | ||
952 | bool discard_current = sc->rx.discard_next; | ||
953 | |||
954 | sc->rx.discard_next = rx_stats->rs_more; | ||
955 | if (discard_current) | ||
956 | return -EINVAL; | ||
940 | 957 | ||
941 | /* | 958 | /* |
942 | * everything but the rate is checked here, the rate check is done | 959 | * everything but the rate is checked here, the rate check is done |
@@ -962,6 +979,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, | |||
962 | if (rx_stats->rs_moreaggr) | 979 | if (rx_stats->rs_moreaggr) |
963 | rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; | 980 | rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; |
964 | 981 | ||
982 | sc->rx.discard_next = false; | ||
965 | return 0; | 983 | return 0; |
966 | } | 984 | } |
967 | 985 | ||
@@ -981,7 +999,7 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common, | |||
981 | hdr = (struct ieee80211_hdr *) skb->data; | 999 | hdr = (struct ieee80211_hdr *) skb->data; |
982 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1000 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
983 | fc = hdr->frame_control; | 1001 | fc = hdr->frame_control; |
984 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 1002 | padpos = ieee80211_hdrlen(fc); |
985 | 1003 | ||
986 | /* The MAC header is padded to have 32-bit boundary if the | 1004 | /* The MAC header is padded to have 32-bit boundary if the |
987 | * packet payload is non-zero. The general calculation for | 1005 | * packet payload is non-zero. The general calculation for |
@@ -1162,6 +1180,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1162 | u64 tsf = 0; | 1180 | u64 tsf = 0; |
1163 | u32 tsf_lower = 0; | 1181 | u32 tsf_lower = 0; |
1164 | unsigned long flags; | 1182 | unsigned long flags; |
1183 | dma_addr_t new_buf_addr; | ||
1165 | 1184 | ||
1166 | if (edma) | 1185 | if (edma) |
1167 | dma_type = DMA_BIDIRECTIONAL; | 1186 | dma_type = DMA_BIDIRECTIONAL; |
@@ -1228,6 +1247,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1228 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) | 1247 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) |
1229 | rxs->mactime += 0x100000000ULL; | 1248 | rxs->mactime += 0x100000000ULL; |
1230 | 1249 | ||
1250 | if (rs.rs_phyerr == ATH9K_PHYERR_RADAR) | ||
1251 | ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime); | ||
1252 | |||
1231 | if (rs.rs_status & ATH9K_RXERR_PHY) { | 1253 | if (rs.rs_status & ATH9K_RXERR_PHY) { |
1232 | if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) { | 1254 | if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) { |
1233 | RX_STAT_INC(rx_spectral); | 1255 | RX_STAT_INC(rx_spectral); |
@@ -1235,8 +1257,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1235 | } | 1257 | } |
1236 | } | 1258 | } |
1237 | 1259 | ||
1238 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | 1260 | retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs, |
1239 | rxs, &decrypt_error); | 1261 | &decrypt_error); |
1240 | if (retval) | 1262 | if (retval) |
1241 | goto requeue_drop_frag; | 1263 | goto requeue_drop_frag; |
1242 | 1264 | ||
@@ -1257,10 +1279,20 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1257 | goto requeue_drop_frag; | 1279 | goto requeue_drop_frag; |
1258 | } | 1280 | } |
1259 | 1281 | ||
1282 | /* We will now give hardware our shiny new allocated skb */ | ||
1283 | new_buf_addr = dma_map_single(sc->dev, requeue_skb->data, | ||
1284 | common->rx_bufsize, dma_type); | ||
1285 | if (unlikely(dma_mapping_error(sc->dev, new_buf_addr))) { | ||
1286 | dev_kfree_skb_any(requeue_skb); | ||
1287 | goto requeue_drop_frag; | ||
1288 | } | ||
1289 | |||
1290 | bf->bf_mpdu = requeue_skb; | ||
1291 | bf->bf_buf_addr = new_buf_addr; | ||
1292 | |||
1260 | /* Unmap the frame */ | 1293 | /* Unmap the frame */ |
1261 | dma_unmap_single(sc->dev, bf->bf_buf_addr, | 1294 | dma_unmap_single(sc->dev, bf->bf_buf_addr, |
1262 | common->rx_bufsize, | 1295 | common->rx_bufsize, dma_type); |
1263 | dma_type); | ||
1264 | 1296 | ||
1265 | skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len); | 1297 | skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len); |
1266 | if (ah->caps.rx_status_len) | 1298 | if (ah->caps.rx_status_len) |
@@ -1270,21 +1302,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1270 | ath9k_rx_skb_postprocess(common, hdr_skb, &rs, | 1302 | ath9k_rx_skb_postprocess(common, hdr_skb, &rs, |
1271 | rxs, decrypt_error); | 1303 | rxs, decrypt_error); |
1272 | 1304 | ||
1273 | /* We will now give hardware our shiny new allocated skb */ | ||
1274 | bf->bf_mpdu = requeue_skb; | ||
1275 | bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data, | ||
1276 | common->rx_bufsize, | ||
1277 | dma_type); | ||
1278 | if (unlikely(dma_mapping_error(sc->dev, | ||
1279 | bf->bf_buf_addr))) { | ||
1280 | dev_kfree_skb_any(requeue_skb); | ||
1281 | bf->bf_mpdu = NULL; | ||
1282 | bf->bf_buf_addr = 0; | ||
1283 | ath_err(common, "dma_mapping_error() on RX\n"); | ||
1284 | ieee80211_rx(hw, skb); | ||
1285 | break; | ||
1286 | } | ||
1287 | |||
1288 | if (rs.rs_more) { | 1305 | if (rs.rs_more) { |
1289 | RX_STAT_INC(rx_frags); | 1306 | RX_STAT_INC(rx_frags); |
1290 | /* | 1307 | /* |
@@ -1302,6 +1319,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1302 | sc->rx.frag = skb; | 1319 | sc->rx.frag = skb; |
1303 | goto requeue; | 1320 | goto requeue; |
1304 | } | 1321 | } |
1322 | if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC) | ||
1323 | goto requeue_drop_frag; | ||
1305 | 1324 | ||
1306 | if (sc->rx.frag) { | 1325 | if (sc->rx.frag) { |
1307 | int space = skb->len - skb_tailroom(hdr_skb); | 1326 | int space = skb->len - skb_tailroom(hdr_skb); |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 89a64411b82e..5bc580276493 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -516,8 +516,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
516 | * not a holding desc. | 516 | * not a holding desc. |
517 | */ | 517 | */ |
518 | INIT_LIST_HEAD(&bf_head); | 518 | INIT_LIST_HEAD(&bf_head); |
519 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) || | 519 | if (bf_next != NULL || !bf_last->bf_stale) |
520 | bf_next != NULL || !bf_last->bf_stale) | ||
521 | list_move_tail(&bf->list, &bf_head); | 520 | list_move_tail(&bf->list, &bf_head); |
522 | 521 | ||
523 | if (!txpending || (tid->state & AGGR_CLEANUP)) { | 522 | if (!txpending || (tid->state & AGGR_CLEANUP)) { |
@@ -537,8 +536,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
537 | !txfail); | 536 | !txfail); |
538 | } else { | 537 | } else { |
539 | /* retry the un-acked ones */ | 538 | /* retry the un-acked ones */ |
540 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && | 539 | if (bf->bf_next == NULL && bf_last->bf_stale) { |
541 | bf->bf_next == NULL && bf_last->bf_stale) { | ||
542 | struct ath_buf *tbf; | 540 | struct ath_buf *tbf; |
543 | 541 | ||
544 | tbf = ath_clone_txbuf(sc, bf_last); | 542 | tbf = ath_clone_txbuf(sc, bf_last); |
@@ -1971,7 +1969,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1971 | } | 1969 | } |
1972 | 1970 | ||
1973 | /* Add the padding after the header if this is not already done */ | 1971 | /* Add the padding after the header if this is not already done */ |
1974 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 1972 | padpos = ieee80211_hdrlen(hdr->frame_control); |
1975 | padsize = padpos & 3; | 1973 | padsize = padpos & 3; |
1976 | if (padsize && skb->len > padpos) { | 1974 | if (padsize && skb->len > padpos) { |
1977 | if (skb_headroom(skb) < padsize) | 1975 | if (skb_headroom(skb) < padsize) |
@@ -2033,7 +2031,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
2033 | /* Frame was ACKed */ | 2031 | /* Frame was ACKed */ |
2034 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 2032 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
2035 | 2033 | ||
2036 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 2034 | padpos = ieee80211_hdrlen(hdr->frame_control); |
2037 | padsize = padpos & 3; | 2035 | padsize = padpos & 3; |
2038 | if (padsize && skb->len>padpos+padsize) { | 2036 | if (padsize && skb->len>padpos+padsize) { |
2039 | /* | 2037 | /* |
@@ -2264,6 +2262,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2264 | struct ath_txq *txq; | 2262 | struct ath_txq *txq; |
2265 | struct ath_buf *bf, *lastbf; | 2263 | struct ath_buf *bf, *lastbf; |
2266 | struct list_head bf_head; | 2264 | struct list_head bf_head; |
2265 | struct list_head *fifo_list; | ||
2267 | int status; | 2266 | int status; |
2268 | 2267 | ||
2269 | for (;;) { | 2268 | for (;;) { |
@@ -2291,20 +2290,24 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2291 | 2290 | ||
2292 | TX_STAT_INC(txq->axq_qnum, txprocdesc); | 2291 | TX_STAT_INC(txq->axq_qnum, txprocdesc); |
2293 | 2292 | ||
2294 | if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { | 2293 | fifo_list = &txq->txq_fifo[txq->txq_tailidx]; |
2294 | if (list_empty(fifo_list)) { | ||
2295 | ath_txq_unlock(sc, txq); | 2295 | ath_txq_unlock(sc, txq); |
2296 | return; | 2296 | return; |
2297 | } | 2297 | } |
2298 | 2298 | ||
2299 | bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx], | 2299 | bf = list_first_entry(fifo_list, struct ath_buf, list); |
2300 | struct ath_buf, list); | 2300 | if (bf->bf_stale) { |
2301 | list_del(&bf->list); | ||
2302 | ath_tx_return_buffer(sc, bf); | ||
2303 | bf = list_first_entry(fifo_list, struct ath_buf, list); | ||
2304 | } | ||
2305 | |||
2301 | lastbf = bf->bf_lastbf; | 2306 | lastbf = bf->bf_lastbf; |
2302 | 2307 | ||
2303 | INIT_LIST_HEAD(&bf_head); | 2308 | INIT_LIST_HEAD(&bf_head); |
2304 | list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx], | 2309 | if (list_is_last(&lastbf->list, fifo_list)) { |
2305 | &lastbf->list); | 2310 | list_splice_tail_init(fifo_list, &bf_head); |
2306 | |||
2307 | if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { | ||
2308 | INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); | 2311 | INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); |
2309 | 2312 | ||
2310 | if (!list_empty(&txq->axq_q)) { | 2313 | if (!list_empty(&txq->axq_q)) { |
@@ -2315,6 +2318,11 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2315 | list_splice_tail_init(&txq->axq_q, &bf_q); | 2318 | list_splice_tail_init(&txq->axq_q, &bf_q); |
2316 | ath_tx_txqaddbuf(sc, txq, &bf_q, true); | 2319 | ath_tx_txqaddbuf(sc, txq, &bf_q, true); |
2317 | } | 2320 | } |
2321 | } else { | ||
2322 | lastbf->bf_stale = true; | ||
2323 | if (bf != lastbf) | ||
2324 | list_cut_position(&bf_head, fifo_list, | ||
2325 | lastbf->list.prev); | ||
2318 | } | 2326 | } |
2319 | 2327 | ||
2320 | ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head); | 2328 | ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head); |
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 25599741cd8a..9dce106cd6d4 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h | |||
@@ -70,12 +70,6 @@ | |||
70 | 70 | ||
71 | static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 }; | 71 | static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 }; |
72 | 72 | ||
73 | enum carl9170_rf_init_mode { | ||
74 | CARL9170_RFI_NONE, | ||
75 | CARL9170_RFI_WARM, | ||
76 | CARL9170_RFI_COLD, | ||
77 | }; | ||
78 | |||
79 | #define CARL9170_MAX_RX_BUFFER_SIZE 8192 | 73 | #define CARL9170_MAX_RX_BUFFER_SIZE 8192 |
80 | 74 | ||
81 | enum carl9170_device_state { | 75 | enum carl9170_device_state { |
@@ -599,7 +593,7 @@ int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state); | |||
599 | 593 | ||
600 | /* PHY / RF */ | 594 | /* PHY / RF */ |
601 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | 595 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, |
602 | enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi); | 596 | enum nl80211_channel_type bw); |
603 | int carl9170_get_noisefloor(struct ar9170 *ar); | 597 | int carl9170_get_noisefloor(struct ar9170 *ar); |
604 | 598 | ||
605 | /* FW */ | 599 | /* FW */ |
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c index 7741fe8e0816..3d70cd277fd7 100644 --- a/drivers/net/wireless/ath/carl9170/debug.c +++ b/drivers/net/wireless/ath/carl9170/debug.c | |||
@@ -655,8 +655,7 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf, | |||
655 | 655 | ||
656 | case 'P': | 656 | case 'P': |
657 | err = carl9170_set_channel(ar, ar->hw->conf.chandef.chan, | 657 | err = carl9170_set_channel(ar, ar->hw->conf.chandef.chan, |
658 | cfg80211_get_chandef_type(&ar->hw->conf.chandef), | 658 | cfg80211_get_chandef_type(&ar->hw->conf.chandef)); |
659 | CARL9170_RFI_COLD); | ||
660 | if (err < 0) | 659 | if (err < 0) |
661 | count = err; | 660 | count = err; |
662 | 661 | ||
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 4e268b1360d8..e9010a481dfd 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -942,7 +942,7 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) | |||
942 | goto out; | 942 | goto out; |
943 | 943 | ||
944 | err = carl9170_set_channel(ar, hw->conf.chandef.chan, | 944 | err = carl9170_set_channel(ar, hw->conf.chandef.chan, |
945 | channel_type, CARL9170_RFI_NONE); | 945 | channel_type); |
946 | if (err) | 946 | if (err) |
947 | goto out; | 947 | goto out; |
948 | 948 | ||
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index c5f1fdd1eaeb..ab4ee7d39ad3 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c | |||
@@ -1569,16 +1569,14 @@ static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type) | |||
1569 | } | 1569 | } |
1570 | 1570 | ||
1571 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | 1571 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, |
1572 | enum nl80211_channel_type _bw, | 1572 | enum nl80211_channel_type _bw) |
1573 | enum carl9170_rf_init_mode rfi) | ||
1574 | { | 1573 | { |
1575 | const struct carl9170_phy_freq_params *freqpar; | 1574 | const struct carl9170_phy_freq_params *freqpar; |
1576 | struct carl9170_rf_init_result rf_res; | 1575 | struct carl9170_rf_init_result rf_res; |
1577 | struct carl9170_rf_init rf; | 1576 | struct carl9170_rf_init rf; |
1578 | u32 cmd, tmp, offs = 0, new_ht = 0; | 1577 | u32 tmp, offs = 0, new_ht = 0; |
1579 | int err; | 1578 | int err; |
1580 | enum carl9170_bw bw; | 1579 | enum carl9170_bw bw; |
1581 | bool warm_reset; | ||
1582 | struct ieee80211_channel *old_channel = NULL; | 1580 | struct ieee80211_channel *old_channel = NULL; |
1583 | 1581 | ||
1584 | bw = nl80211_to_carl(_bw); | 1582 | bw = nl80211_to_carl(_bw); |
@@ -1592,51 +1590,27 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1592 | /* may be NULL at first setup */ | 1590 | /* may be NULL at first setup */ |
1593 | if (ar->channel) { | 1591 | if (ar->channel) { |
1594 | old_channel = ar->channel; | 1592 | old_channel = ar->channel; |
1595 | warm_reset = (old_channel->band != channel->band) || | ||
1596 | (old_channel->center_freq == | ||
1597 | channel->center_freq) || | ||
1598 | (ar->ht_settings != new_ht); | ||
1599 | |||
1600 | ar->channel = NULL; | 1593 | ar->channel = NULL; |
1601 | } else { | ||
1602 | warm_reset = true; | ||
1603 | } | 1594 | } |
1604 | 1595 | ||
1605 | /* HW workaround */ | 1596 | /* cold reset BB/ADDA */ |
1606 | if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && | 1597 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, |
1607 | channel->center_freq <= 2417) | 1598 | AR9170_PWR_RESET_BB_COLD_RESET); |
1608 | warm_reset = true; | 1599 | if (err) |
1609 | 1600 | return err; | |
1610 | if (rfi != CARL9170_RFI_NONE || warm_reset) { | ||
1611 | u32 val; | ||
1612 | |||
1613 | if (rfi == CARL9170_RFI_COLD) | ||
1614 | val = AR9170_PWR_RESET_BB_COLD_RESET; | ||
1615 | else | ||
1616 | val = AR9170_PWR_RESET_BB_WARM_RESET; | ||
1617 | |||
1618 | /* warm/cold reset BB/ADDA */ | ||
1619 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val); | ||
1620 | if (err) | ||
1621 | return err; | ||
1622 | |||
1623 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0); | ||
1624 | if (err) | ||
1625 | return err; | ||
1626 | 1601 | ||
1627 | err = carl9170_init_phy(ar, channel->band); | 1602 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0); |
1628 | if (err) | 1603 | if (err) |
1629 | return err; | 1604 | return err; |
1630 | 1605 | ||
1631 | err = carl9170_init_rf_banks_0_7(ar, | 1606 | err = carl9170_init_phy(ar, channel->band); |
1632 | channel->band == IEEE80211_BAND_5GHZ); | 1607 | if (err) |
1633 | if (err) | 1608 | return err; |
1634 | return err; | ||
1635 | 1609 | ||
1636 | cmd = CARL9170_CMD_RF_INIT; | 1610 | err = carl9170_init_rf_banks_0_7(ar, |
1637 | } else { | 1611 | channel->band == IEEE80211_BAND_5GHZ); |
1638 | cmd = CARL9170_CMD_FREQUENCY; | 1612 | if (err) |
1639 | } | 1613 | return err; |
1640 | 1614 | ||
1641 | err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL); | 1615 | err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL); |
1642 | if (err) | 1616 | if (err) |
@@ -1648,8 +1622,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1648 | return err; | 1622 | return err; |
1649 | 1623 | ||
1650 | err = carl9170_init_rf_bank4_pwr(ar, | 1624 | err = carl9170_init_rf_bank4_pwr(ar, |
1651 | channel->band == IEEE80211_BAND_5GHZ, | 1625 | channel->band == IEEE80211_BAND_5GHZ, |
1652 | channel->center_freq, bw); | 1626 | channel->center_freq, bw); |
1653 | if (err) | 1627 | if (err) |
1654 | return err; | 1628 | return err; |
1655 | 1629 | ||
@@ -1703,13 +1677,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1703 | rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man); | 1677 | rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man); |
1704 | rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi); | 1678 | rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi); |
1705 | rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi); | 1679 | rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi); |
1706 | 1680 | rf.finiteLoopCount = cpu_to_le32(2000); | |
1707 | if (rfi != CARL9170_RFI_NONE) | 1681 | err = carl9170_exec_cmd(ar, CARL9170_CMD_RF_INIT, sizeof(rf), &rf, |
1708 | rf.finiteLoopCount = cpu_to_le32(2000); | ||
1709 | else | ||
1710 | rf.finiteLoopCount = cpu_to_le32(1000); | ||
1711 | |||
1712 | err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf, | ||
1713 | sizeof(rf_res), &rf_res); | 1682 | sizeof(rf_res), &rf_res); |
1714 | if (err) | 1683 | if (err) |
1715 | return err; | 1684 | return err; |
@@ -1724,9 +1693,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1724 | old_channel->center_freq : -1, channel->center_freq, | 1693 | old_channel->center_freq : -1, channel->center_freq, |
1725 | err); | 1694 | err); |
1726 | 1695 | ||
1727 | if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) { | 1696 | if (ar->chan_fail > 3) { |
1728 | /* | 1697 | /* We have tried very hard to change to _another_ |
1729 | * We have tried very hard to change to _another_ | ||
1730 | * channel and we've failed to do so! | 1698 | * channel and we've failed to do so! |
1731 | * Chances are that the PHY/RF is no longer | 1699 | * Chances are that the PHY/RF is no longer |
1732 | * operable (due to corruptions/fatal events/bugs?) | 1700 | * operable (due to corruptions/fatal events/bugs?) |
@@ -1736,8 +1704,7 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1736 | return 0; | 1704 | return 0; |
1737 | } | 1705 | } |
1738 | 1706 | ||
1739 | err = carl9170_set_channel(ar, channel, _bw, | 1707 | err = carl9170_set_channel(ar, channel, _bw); |
1740 | CARL9170_RFI_COLD); | ||
1741 | if (err) | 1708 | if (err) |
1742 | return err; | 1709 | return err; |
1743 | } else { | 1710 | } else { |
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/key.c b/drivers/net/wireless/ath/key.c index 5c54aa43ca2d..1816b4e7dc26 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c | |||
@@ -45,7 +45,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) | |||
45 | void *ah = common->ah; | 45 | void *ah = common->ah; |
46 | 46 | ||
47 | if (entry >= common->keymax) { | 47 | if (entry >= common->keymax) { |
48 | ath_err(common, "keycache entry %u out of range\n", entry); | 48 | ath_err(common, "keyreset: keycache entry %u out of range\n", |
49 | entry); | ||
49 | return false; | 50 | return false; |
50 | } | 51 | } |
51 | 52 | ||
@@ -91,7 +92,8 @@ static bool ath_hw_keysetmac(struct ath_common *common, | |||
91 | void *ah = common->ah; | 92 | void *ah = common->ah; |
92 | 93 | ||
93 | if (entry >= common->keymax) { | 94 | if (entry >= common->keymax) { |
94 | ath_err(common, "keycache entry %u out of range\n", entry); | 95 | ath_err(common, "keysetmac: keycache entry %u out of range\n", |
96 | entry); | ||
95 | return false; | 97 | return false; |
96 | } | 98 | } |
97 | 99 | ||
@@ -133,7 +135,8 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, | |||
133 | u32 keyType; | 135 | u32 keyType; |
134 | 136 | ||
135 | if (entry >= common->keymax) { | 137 | if (entry >= common->keymax) { |
136 | ath_err(common, "keycache entry %u out of range\n", entry); | 138 | ath_err(common, "set-entry: keycache entry %u out of range\n", |
139 | entry); | ||
137 | return false; | 140 | return false; |
138 | } | 141 | } |
139 | 142 | ||
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 6a4bd8c433b4..7f3d461f7e8d 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -285,7 +285,9 @@ enum { | |||
285 | #define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */ | 285 | #define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */ |
286 | #define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */ | 286 | #define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */ |
287 | /* SHM_SHARED beacon/AP variables */ | 287 | /* SHM_SHARED beacon/AP variables */ |
288 | #define B43_SHM_SH_BT_BASE0 0x0068 /* Beacon template base 0 */ | ||
288 | #define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */ | 289 | #define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */ |
290 | #define B43_SHM_SH_BT_BASE1 0x0468 /* Beacon template base 1 */ | ||
289 | #define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */ | 291 | #define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */ |
290 | #define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */ | 292 | #define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */ |
291 | #define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */ | 293 | #define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */ |
@@ -473,6 +475,12 @@ enum { | |||
473 | #define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */ | 475 | #define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */ |
474 | #define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */ | 476 | #define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */ |
475 | 477 | ||
478 | /* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */ | ||
479 | #define B43_BCMA_CLKCTLST_80211_PLL_REQ 0x00000100 | ||
480 | #define B43_BCMA_CLKCTLST_PHY_PLL_REQ 0x00000200 | ||
481 | #define B43_BCMA_CLKCTLST_80211_PLL_ST 0x01000000 | ||
482 | #define B43_BCMA_CLKCTLST_PHY_PLL_ST 0x02000000 | ||
483 | |||
476 | /* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */ | 484 | /* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */ |
477 | #define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */ | 485 | #define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */ |
478 | #define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */ | 486 | #define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */ |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 38bc5a7997ff..122146943bf2 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -1487,8 +1487,12 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1487 | const struct b43_dma_ops *ops; | 1487 | const struct b43_dma_ops *ops; |
1488 | struct b43_dmaring *ring; | 1488 | struct b43_dmaring *ring; |
1489 | struct b43_dmadesc_meta *meta; | 1489 | struct b43_dmadesc_meta *meta; |
1490 | static const struct b43_txstatus fake; /* filled with 0 */ | ||
1491 | const struct b43_txstatus *txstat; | ||
1490 | int slot, firstused; | 1492 | int slot, firstused; |
1491 | bool frame_succeed; | 1493 | bool frame_succeed; |
1494 | int skip; | ||
1495 | static u8 err_out1, err_out2; | ||
1492 | 1496 | ||
1493 | ring = parse_cookie(dev, status->cookie, &slot); | 1497 | ring = parse_cookie(dev, status->cookie, &slot); |
1494 | if (unlikely(!ring)) | 1498 | if (unlikely(!ring)) |
@@ -1501,13 +1505,36 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1501 | firstused = ring->current_slot - ring->used_slots + 1; | 1505 | firstused = ring->current_slot - ring->used_slots + 1; |
1502 | if (firstused < 0) | 1506 | if (firstused < 0) |
1503 | firstused = ring->nr_slots + firstused; | 1507 | firstused = ring->nr_slots + firstused; |
1508 | |||
1509 | skip = 0; | ||
1504 | if (unlikely(slot != firstused)) { | 1510 | if (unlikely(slot != firstused)) { |
1505 | /* This possibly is a firmware bug and will result in | 1511 | /* This possibly is a firmware bug and will result in |
1506 | * malfunction, memory leaks and/or stall of DMA functionality. */ | 1512 | * malfunction, memory leaks and/or stall of DMA functionality. |
1507 | b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. " | 1513 | */ |
1508 | "Expected %d, but got %d\n", | 1514 | if (slot == next_slot(ring, next_slot(ring, firstused))) { |
1509 | ring->index, firstused, slot); | 1515 | /* If a single header/data pair was missed, skip over |
1510 | return; | 1516 | * the first two slots in an attempt to recover. |
1517 | */ | ||
1518 | slot = firstused; | ||
1519 | skip = 2; | ||
1520 | if (!err_out1) { | ||
1521 | /* Report the error once. */ | ||
1522 | b43dbg(dev->wl, | ||
1523 | "Skip on DMA ring %d slot %d.\n", | ||
1524 | ring->index, slot); | ||
1525 | err_out1 = 1; | ||
1526 | } | ||
1527 | } else { | ||
1528 | /* More than a single header/data pair were missed. | ||
1529 | * Report this error once. | ||
1530 | */ | ||
1531 | if (!err_out2) | ||
1532 | b43dbg(dev->wl, | ||
1533 | "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n", | ||
1534 | ring->index, firstused, slot); | ||
1535 | err_out2 = 1; | ||
1536 | return; | ||
1537 | } | ||
1511 | } | 1538 | } |
1512 | 1539 | ||
1513 | ops = ring->ops; | 1540 | ops = ring->ops; |
@@ -1522,11 +1549,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1522 | slot, firstused, ring->index); | 1549 | slot, firstused, ring->index); |
1523 | break; | 1550 | break; |
1524 | } | 1551 | } |
1552 | |||
1525 | if (meta->skb) { | 1553 | if (meta->skb) { |
1526 | struct b43_private_tx_info *priv_info = | 1554 | struct b43_private_tx_info *priv_info = |
1527 | b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); | 1555 | b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); |
1528 | 1556 | ||
1529 | unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); | 1557 | unmap_descbuffer(ring, meta->dmaaddr, |
1558 | meta->skb->len, 1); | ||
1530 | kfree(priv_info->bouncebuffer); | 1559 | kfree(priv_info->bouncebuffer); |
1531 | priv_info->bouncebuffer = NULL; | 1560 | priv_info->bouncebuffer = NULL; |
1532 | } else { | 1561 | } else { |
@@ -1538,8 +1567,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1538 | struct ieee80211_tx_info *info; | 1567 | struct ieee80211_tx_info *info; |
1539 | 1568 | ||
1540 | if (unlikely(!meta->skb)) { | 1569 | if (unlikely(!meta->skb)) { |
1541 | /* This is a scatter-gather fragment of a frame, so | 1570 | /* This is a scatter-gather fragment of a frame, |
1542 | * the skb pointer must not be NULL. */ | 1571 | * so the skb pointer must not be NULL. |
1572 | */ | ||
1543 | b43dbg(dev->wl, "TX status unexpected NULL skb " | 1573 | b43dbg(dev->wl, "TX status unexpected NULL skb " |
1544 | "at slot %d (first=%d) on ring %d\n", | 1574 | "at slot %d (first=%d) on ring %d\n", |
1545 | slot, firstused, ring->index); | 1575 | slot, firstused, ring->index); |
@@ -1550,9 +1580,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1550 | 1580 | ||
1551 | /* | 1581 | /* |
1552 | * Call back to inform the ieee80211 subsystem about | 1582 | * Call back to inform the ieee80211 subsystem about |
1553 | * the status of the transmission. | 1583 | * the status of the transmission. When skipping over |
1584 | * a missed TX status report, use a status structure | ||
1585 | * filled with zeros to indicate that the frame was not | ||
1586 | * sent (frame_count 0) and not acknowledged | ||
1554 | */ | 1587 | */ |
1555 | frame_succeed = b43_fill_txstatus_report(dev, info, status); | 1588 | if (unlikely(skip)) |
1589 | txstat = &fake; | ||
1590 | else | ||
1591 | txstat = status; | ||
1592 | |||
1593 | frame_succeed = b43_fill_txstatus_report(dev, info, | ||
1594 | txstat); | ||
1556 | #ifdef CONFIG_B43_DEBUG | 1595 | #ifdef CONFIG_B43_DEBUG |
1557 | if (frame_succeed) | 1596 | if (frame_succeed) |
1558 | ring->nr_succeed_tx_packets++; | 1597 | ring->nr_succeed_tx_packets++; |
@@ -1580,12 +1619,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1580 | /* Everything unmapped and free'd. So it's not used anymore. */ | 1619 | /* Everything unmapped and free'd. So it's not used anymore. */ |
1581 | ring->used_slots--; | 1620 | ring->used_slots--; |
1582 | 1621 | ||
1583 | if (meta->is_last_fragment) { | 1622 | if (meta->is_last_fragment && !skip) { |
1584 | /* This is the last scatter-gather | 1623 | /* This is the last scatter-gather |
1585 | * fragment of the frame. We are done. */ | 1624 | * fragment of the frame. We are done. */ |
1586 | break; | 1625 | break; |
1587 | } | 1626 | } |
1588 | slot = next_slot(ring, slot); | 1627 | slot = next_slot(ring, slot); |
1628 | if (skip > 0) | ||
1629 | --skip; | ||
1589 | } | 1630 | } |
1590 | if (ring->stopped) { | 1631 | if (ring->stopped) { |
1591 | B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME); | 1632 | B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME); |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index d135e8975f52..d377f77d30b5 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 | ||
@@ -1305,17 +1310,19 @@ static u32 b43_jssi_read(struct b43_wldev *dev) | |||
1305 | { | 1310 | { |
1306 | u32 val = 0; | 1311 | u32 val = 0; |
1307 | 1312 | ||
1308 | val = b43_shm_read16(dev, B43_SHM_SHARED, 0x08A); | 1313 | val = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1); |
1309 | val <<= 16; | 1314 | val <<= 16; |
1310 | val |= b43_shm_read16(dev, B43_SHM_SHARED, 0x088); | 1315 | val |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0); |
1311 | 1316 | ||
1312 | return val; | 1317 | return val; |
1313 | } | 1318 | } |
1314 | 1319 | ||
1315 | static void b43_jssi_write(struct b43_wldev *dev, u32 jssi) | 1320 | static void b43_jssi_write(struct b43_wldev *dev, u32 jssi) |
1316 | { | 1321 | { |
1317 | b43_shm_write16(dev, B43_SHM_SHARED, 0x088, (jssi & 0x0000FFFF)); | 1322 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0, |
1318 | b43_shm_write16(dev, B43_SHM_SHARED, 0x08A, (jssi & 0xFFFF0000) >> 16); | 1323 | (jssi & 0x0000FFFF)); |
1324 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1, | ||
1325 | (jssi & 0xFFFF0000) >> 16); | ||
1319 | } | 1326 | } |
1320 | 1327 | ||
1321 | static void b43_generate_noise_sample(struct b43_wldev *dev) | 1328 | static void b43_generate_noise_sample(struct b43_wldev *dev) |
@@ -1618,7 +1625,7 @@ static void b43_upload_beacon0(struct b43_wldev *dev) | |||
1618 | 1625 | ||
1619 | if (wl->beacon0_uploaded) | 1626 | if (wl->beacon0_uploaded) |
1620 | return; | 1627 | return; |
1621 | b43_write_beacon_template(dev, 0x68, 0x18); | 1628 | b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE0, B43_SHM_SH_BTL0); |
1622 | wl->beacon0_uploaded = true; | 1629 | wl->beacon0_uploaded = true; |
1623 | } | 1630 | } |
1624 | 1631 | ||
@@ -1628,7 +1635,7 @@ static void b43_upload_beacon1(struct b43_wldev *dev) | |||
1628 | 1635 | ||
1629 | if (wl->beacon1_uploaded) | 1636 | if (wl->beacon1_uploaded) |
1630 | return; | 1637 | return; |
1631 | b43_write_beacon_template(dev, 0x468, 0x1A); | 1638 | b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE1, B43_SHM_SH_BTL1); |
1632 | wl->beacon1_uploaded = true; | 1639 | wl->beacon1_uploaded = true; |
1633 | } | 1640 | } |
1634 | 1641 | ||
@@ -2775,9 +2782,7 @@ static int b43_gpio_init(struct b43_wldev *dev) | |||
2775 | switch (dev->dev->bus_type) { | 2782 | switch (dev->dev->bus_type) { |
2776 | #ifdef CONFIG_B43_BCMA | 2783 | #ifdef CONFIG_B43_BCMA |
2777 | case B43_BUS_BCMA: | 2784 | case B43_BUS_BCMA: |
2778 | bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL, | 2785 | bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, mask, set); |
2779 | (bcma_cc_read32(&dev->dev->bdev->bus->drv_cc, | ||
2780 | BCMA_CC_GPIOCTL) & ~mask) | set); | ||
2781 | break; | 2786 | break; |
2782 | #endif | 2787 | #endif |
2783 | #ifdef CONFIG_B43_SSB | 2788 | #ifdef CONFIG_B43_SSB |
@@ -2802,8 +2807,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev) | |||
2802 | switch (dev->dev->bus_type) { | 2807 | switch (dev->dev->bus_type) { |
2803 | #ifdef CONFIG_B43_BCMA | 2808 | #ifdef CONFIG_B43_BCMA |
2804 | case B43_BUS_BCMA: | 2809 | case B43_BUS_BCMA: |
2805 | bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL, | 2810 | bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, ~0, 0); |
2806 | 0); | ||
2807 | break; | 2811 | break; |
2808 | #endif | 2812 | #endif |
2809 | #ifdef CONFIG_B43_SSB | 2813 | #ifdef CONFIG_B43_SSB |
@@ -3111,7 +3115,7 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
3111 | 3115 | ||
3112 | /* Probe Response Timeout value */ | 3116 | /* Probe Response Timeout value */ |
3113 | /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ | 3117 | /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ |
3114 | b43_shm_write16(dev, B43_SHM_SHARED, 0x0074, 0x0000); | 3118 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 0); |
3115 | 3119 | ||
3116 | /* Initially set the wireless operation mode. */ | 3120 | /* Initially set the wireless operation mode. */ |
3117 | b43_adjust_opmode(dev); | 3121 | b43_adjust_opmode(dev); |
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 016682ea7445..83239fd87040 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/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 3ae28561f7a4..5ed352ddae9e 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
@@ -104,14 +104,8 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev) | |||
104 | maxpwr = sprom->maxpwr_bg; | 104 | maxpwr = sprom->maxpwr_bg; |
105 | lpphy->max_tx_pwr_med_band = maxpwr; | 105 | lpphy->max_tx_pwr_med_band = maxpwr; |
106 | cckpo = sprom->cck2gpo; | 106 | cckpo = sprom->cck2gpo; |
107 | /* | ||
108 | * We don't read SPROM's opo as specs say. On rev8 SPROMs | ||
109 | * opo == ofdm2gpo and we don't know any SSB with LP-PHY | ||
110 | * and SPROM rev below 8. | ||
111 | */ | ||
112 | B43_WARN_ON(sprom->revision < 8); | ||
113 | ofdmpo = sprom->ofdm2gpo; | ||
114 | if (cckpo) { | 107 | if (cckpo) { |
108 | ofdmpo = sprom->ofdm2gpo; | ||
115 | for (i = 0; i < 4; i++) { | 109 | for (i = 0; i < 4; i++) { |
116 | lpphy->tx_max_rate[i] = | 110 | lpphy->tx_max_rate[i] = |
117 | maxpwr - (ofdmpo & 0xF) * 2; | 111 | maxpwr - (ofdmpo & 0xF) * 2; |
@@ -124,11 +118,11 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev) | |||
124 | ofdmpo >>= 4; | 118 | ofdmpo >>= 4; |
125 | } | 119 | } |
126 | } else { | 120 | } else { |
127 | ofdmpo &= 0xFF; | 121 | u8 opo = sprom->opo; |
128 | for (i = 0; i < 4; i++) | 122 | for (i = 0; i < 4; i++) |
129 | lpphy->tx_max_rate[i] = maxpwr; | 123 | lpphy->tx_max_rate[i] = maxpwr; |
130 | for (i = 4; i < 15; i++) | 124 | for (i = 4; i < 15; i++) |
131 | lpphy->tx_max_rate[i] = maxpwr - ofdmpo; | 125 | lpphy->tx_max_rate[i] = maxpwr - opo; |
132 | } | 126 | } |
133 | } else { /* 5GHz */ | 127 | } else { /* 5GHz */ |
134 | lpphy->tx_isolation_low_band = sprom->tri5gl; | 128 | lpphy->tx_isolation_low_band = sprom->tri5gl; |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 949a3bdeede9..e05dd117f215 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -1564,7 +1564,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | |||
1564 | u16 clip_off[2] = { 0xFFFF, 0xFFFF }; | 1564 | u16 clip_off[2] = { 0xFFFF, 0xFFFF }; |
1565 | 1565 | ||
1566 | u8 vcm_final = 0; | 1566 | u8 vcm_final = 0; |
1567 | s8 offset[4]; | 1567 | s32 offset[4]; |
1568 | s32 results[8][4] = { }; | 1568 | s32 results[8][4] = { }; |
1569 | s32 results_min[4] = { }; | 1569 | s32 results_min[4] = { }; |
1570 | s32 poll_results[4] = { }; | 1570 | s32 poll_results[4] = { }; |
@@ -1615,7 +1615,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | |||
1615 | } | 1615 | } |
1616 | for (i = 0; i < 4; i += 2) { | 1616 | for (i = 0; i < 4; i += 2) { |
1617 | s32 curr; | 1617 | s32 curr; |
1618 | s32 mind = 40; | 1618 | s32 mind = 0x100000; |
1619 | s32 minpoll = 249; | 1619 | s32 minpoll = 249; |
1620 | u8 minvcm = 0; | 1620 | u8 minvcm = 0; |
1621 | if (2 * core != i) | 1621 | if (2 * core != i) |
@@ -1732,7 +1732,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) | |||
1732 | u8 regs_save_radio[2]; | 1732 | u8 regs_save_radio[2]; |
1733 | u16 regs_save_phy[2]; | 1733 | u16 regs_save_phy[2]; |
1734 | 1734 | ||
1735 | s8 offset[4]; | 1735 | s32 offset[4]; |
1736 | u8 core; | 1736 | u8 core; |
1737 | u8 rail; | 1737 | u8 rail; |
1738 | 1738 | ||
@@ -1799,7 +1799,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) | |||
1799 | } | 1799 | } |
1800 | 1800 | ||
1801 | for (i = 0; i < 4; i++) { | 1801 | for (i = 0; i < 4; i++) { |
1802 | s32 mind = 40; | 1802 | s32 mind = 0x100000; |
1803 | u8 minvcm = 0; | 1803 | u8 minvcm = 0; |
1804 | s32 minpoll = 249; | 1804 | s32 minpoll = 249; |
1805 | s32 curr; | 1805 | s32 curr; |
@@ -2789,10 +2789,6 @@ static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, | |||
2789 | * Tx and Rx | 2789 | * Tx and Rx |
2790 | **************************************************/ | 2790 | **************************************************/ |
2791 | 2791 | ||
2792 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) | ||
2793 | {//TODO | ||
2794 | } | ||
2795 | |||
2796 | static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev) | 2792 | static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev) |
2797 | {//TODO | 2793 | {//TODO |
2798 | } | 2794 | } |
@@ -4892,7 +4888,7 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) | |||
4892 | } | 4888 | } |
4893 | 4889 | ||
4894 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */ | 4890 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */ |
4895 | int b43_phy_initn(struct b43_wldev *dev) | 4891 | static int b43_phy_initn(struct b43_wldev *dev) |
4896 | { | 4892 | { |
4897 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | 4893 | struct ssb_sprom *sprom = dev->dev->bus_sprom; |
4898 | struct b43_phy *phy = &dev->phy; | 4894 | struct b43_phy *phy = &dev->phy; |
@@ -5104,63 +5100,11 @@ static void b43_chantab_phy_upload(struct b43_wldev *dev, | |||
5104 | /* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */ | 5100 | /* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */ |
5105 | static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid) | 5101 | static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid) |
5106 | { | 5102 | { |
5107 | struct bcma_drv_cc __maybe_unused *cc; | ||
5108 | u32 __maybe_unused pmu_ctl; | ||
5109 | |||
5110 | switch (dev->dev->bus_type) { | 5103 | switch (dev->dev->bus_type) { |
5111 | #ifdef CONFIG_B43_BCMA | 5104 | #ifdef CONFIG_B43_BCMA |
5112 | case B43_BUS_BCMA: | 5105 | case B43_BUS_BCMA: |
5113 | cc = &dev->dev->bdev->bus->drv_cc; | 5106 | bcma_pmu_spuravoid_pllupdate(&dev->dev->bdev->bus->drv_cc, |
5114 | if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) { | 5107 | avoid); |
5115 | if (avoid) { | ||
5116 | bcma_chipco_pll_write(cc, 0x0, 0x11500010); | ||
5117 | bcma_chipco_pll_write(cc, 0x1, 0x000C0C06); | ||
5118 | bcma_chipco_pll_write(cc, 0x2, 0x0F600a08); | ||
5119 | bcma_chipco_pll_write(cc, 0x3, 0x00000000); | ||
5120 | bcma_chipco_pll_write(cc, 0x4, 0x2001E920); | ||
5121 | bcma_chipco_pll_write(cc, 0x5, 0x88888815); | ||
5122 | } else { | ||
5123 | bcma_chipco_pll_write(cc, 0x0, 0x11100010); | ||
5124 | bcma_chipco_pll_write(cc, 0x1, 0x000c0c06); | ||
5125 | bcma_chipco_pll_write(cc, 0x2, 0x03000a08); | ||
5126 | bcma_chipco_pll_write(cc, 0x3, 0x00000000); | ||
5127 | bcma_chipco_pll_write(cc, 0x4, 0x200005c0); | ||
5128 | bcma_chipco_pll_write(cc, 0x5, 0x88888815); | ||
5129 | } | ||
5130 | pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD; | ||
5131 | } else if (dev->dev->chip_id == 0x4716) { | ||
5132 | if (avoid) { | ||
5133 | bcma_chipco_pll_write(cc, 0x0, 0x11500060); | ||
5134 | bcma_chipco_pll_write(cc, 0x1, 0x080C0C06); | ||
5135 | bcma_chipco_pll_write(cc, 0x2, 0x0F600000); | ||
5136 | bcma_chipco_pll_write(cc, 0x3, 0x00000000); | ||
5137 | bcma_chipco_pll_write(cc, 0x4, 0x2001E924); | ||
5138 | bcma_chipco_pll_write(cc, 0x5, 0x88888815); | ||
5139 | } else { | ||
5140 | bcma_chipco_pll_write(cc, 0x0, 0x11100060); | ||
5141 | bcma_chipco_pll_write(cc, 0x1, 0x080c0c06); | ||
5142 | bcma_chipco_pll_write(cc, 0x2, 0x03000000); | ||
5143 | bcma_chipco_pll_write(cc, 0x3, 0x00000000); | ||
5144 | bcma_chipco_pll_write(cc, 0x4, 0x200005c0); | ||
5145 | bcma_chipco_pll_write(cc, 0x5, 0x88888815); | ||
5146 | } | ||
5147 | pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD | | ||
5148 | BCMA_CC_PMU_CTL_NOILPONW; | ||
5149 | } else if (dev->dev->chip_id == 0x4322 || | ||
5150 | dev->dev->chip_id == 0x4340 || | ||
5151 | dev->dev->chip_id == 0x4341) { | ||
5152 | bcma_chipco_pll_write(cc, 0x0, 0x11100070); | ||
5153 | bcma_chipco_pll_write(cc, 0x1, 0x1014140a); | ||
5154 | bcma_chipco_pll_write(cc, 0x5, 0x88888854); | ||
5155 | if (avoid) | ||
5156 | bcma_chipco_pll_write(cc, 0x2, 0x05201828); | ||
5157 | else | ||
5158 | bcma_chipco_pll_write(cc, 0x2, 0x05001828); | ||
5159 | pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD; | ||
5160 | } else { | ||
5161 | return; | ||
5162 | } | ||
5163 | bcma_cc_set32(cc, BCMA_CC_PMU_CTL, pmu_ctl); | ||
5164 | break; | 5108 | break; |
5165 | #endif | 5109 | #endif |
5166 | #ifdef CONFIG_B43_SSB | 5110 | #ifdef CONFIG_B43_SSB |
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c index ce037fb6789a..b4fd9345d673 100644 --- a/drivers/net/wireless/b43/radio_2056.c +++ b/drivers/net/wireless/b43/radio_2056.c | |||
@@ -2980,7 +2980,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev8_rx[] = { | |||
2980 | .rx = prefix##_rx, \ | 2980 | .rx = prefix##_rx, \ |
2981 | .rx_length = ARRAY_SIZE(prefix##_rx) | 2981 | .rx_length = ARRAY_SIZE(prefix##_rx) |
2982 | 2982 | ||
2983 | struct b2056_inittabs_pts b2056_inittabs[] = { | 2983 | static const struct b2056_inittabs_pts b2056_inittabs[] = { |
2984 | [3] = { INITTABSPTS(b2056_inittab_rev3) }, | 2984 | [3] = { INITTABSPTS(b2056_inittab_rev3) }, |
2985 | [4] = { INITTABSPTS(b2056_inittab_rev4) }, | 2985 | [4] = { INITTABSPTS(b2056_inittab_rev4) }, |
2986 | [5] = { INITTABSPTS(b2056_inittab_rev5) }, | 2986 | [5] = { INITTABSPTS(b2056_inittab_rev5) }, |
@@ -9035,7 +9035,7 @@ static void b2056_upload_inittab(struct b43_wldev *dev, bool ghz5, | |||
9035 | void b2056_upload_inittabs(struct b43_wldev *dev, | 9035 | void b2056_upload_inittabs(struct b43_wldev *dev, |
9036 | bool ghz5, bool ignore_uploadflag) | 9036 | bool ghz5, bool ignore_uploadflag) |
9037 | { | 9037 | { |
9038 | struct b2056_inittabs_pts *pts; | 9038 | const struct b2056_inittabs_pts *pts; |
9039 | 9039 | ||
9040 | if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) { | 9040 | if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) { |
9041 | B43_WARN_ON(1); | 9041 | B43_WARN_ON(1); |
@@ -9057,7 +9057,7 @@ void b2056_upload_inittabs(struct b43_wldev *dev, | |||
9057 | 9057 | ||
9058 | void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5) | 9058 | void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5) |
9059 | { | 9059 | { |
9060 | struct b2056_inittabs_pts *pts; | 9060 | const struct b2056_inittabs_pts *pts; |
9061 | const struct b2056_inittab_entry *e; | 9061 | const struct b2056_inittab_entry *e; |
9062 | 9062 | ||
9063 | if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) { | 9063 | if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) { |
diff --git a/drivers/net/wireless/b43/sdio.h b/drivers/net/wireless/b43/sdio.h index fb633094403a..1e93926f388f 100644 --- a/drivers/net/wireless/b43/sdio.h +++ b/drivers/net/wireless/b43/sdio.h | |||
@@ -25,12 +25,12 @@ void b43_sdio_exit(void); | |||
25 | #else /* CONFIG_B43_SDIO */ | 25 | #else /* CONFIG_B43_SDIO */ |
26 | 26 | ||
27 | 27 | ||
28 | int b43_sdio_request_irq(struct b43_wldev *dev, | 28 | static inline int b43_sdio_request_irq(struct b43_wldev *dev, |
29 | void (*handler)(struct b43_wldev *dev)) | 29 | void (*handler)(struct b43_wldev *dev)) |
30 | { | 30 | { |
31 | return -ENODEV; | 31 | return -ENODEV; |
32 | } | 32 | } |
33 | void b43_sdio_free_irq(struct b43_wldev *dev) | 33 | static inline void b43_sdio_free_irq(struct b43_wldev *dev) |
34 | { | 34 | { |
35 | } | 35 | } |
36 | static inline int b43_sdio_init(void) | 36 | static inline int b43_sdio_init(void) |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index aaca60c6f575..110510d53958 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -2800,7 +2800,7 @@ static const struct nphy_rf_control_override_rev7 | |||
2800 | { 0x0010, 0x344, 0x345, 0x0010, 4 }, | 2800 | { 0x0010, 0x344, 0x345, 0x0010, 4 }, |
2801 | }; | 2801 | }; |
2802 | 2802 | ||
2803 | struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = { | 2803 | static struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = { |
2804 | { 10, 14, 19, 27 }, | 2804 | { 10, 14, 19, 27 }, |
2805 | { -5, 6, 10, 15 }, | 2805 | { -5, 6, 10, 15 }, |
2806 | { 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA }, | 2806 | { 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA }, |
@@ -2811,7 +2811,7 @@ struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = { | |||
2811 | 0x18, 0x18, 0x18, | 2811 | 0x18, 0x18, 0x18, |
2812 | 0x01D0, 0x5, | 2812 | 0x01D0, 0x5, |
2813 | }; | 2813 | }; |
2814 | struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][4] = { | 2814 | static struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][4] = { |
2815 | { /* 2GHz */ | 2815 | { /* 2GHz */ |
2816 | { /* PHY rev 3 */ | 2816 | { /* PHY rev 3 */ |
2817 | { 7, 11, 16, 23 }, | 2817 | { 7, 11, 16, 23 }, |
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c index 5176363cadf2..e347b8d80ea4 100644 --- a/drivers/net/wireless/b43/tables_phy_lcn.c +++ b/drivers/net/wireless/b43/tables_phy_lcn.c | |||
@@ -313,7 +313,7 @@ static const u32 b43_lcntab_0x18[] = { | |||
313 | * TX gain. | 313 | * TX gain. |
314 | **************************************************/ | 314 | **************************************************/ |
315 | 315 | ||
316 | const struct b43_lcntab_tx_gain_tbl_entry | 316 | static const struct b43_lcntab_tx_gain_tbl_entry |
317 | b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = { | 317 | b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = { |
318 | { 0x03, 0x00, 0x1f, 0x0, 0x48 }, | 318 | { 0x03, 0x00, 0x1f, 0x0, 0x48 }, |
319 | { 0x03, 0x00, 0x1f, 0x0, 0x46 }, | 319 | { 0x03, 0x00, 0x1f, 0x0, 0x46 }, |
@@ -449,7 +449,7 @@ const struct b43_lcntab_tx_gain_tbl_entry | |||
449 | * SW control. | 449 | * SW control. |
450 | **************************************************/ | 450 | **************************************************/ |
451 | 451 | ||
452 | const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = { | 452 | static const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = { |
453 | 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, | 453 | 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, |
454 | 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001, | 454 | 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001, |
455 | 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, | 455 | 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, |
@@ -631,7 +631,7 @@ static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev) | |||
631 | lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18); | 631 | lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18); |
632 | } | 632 | } |
633 | 633 | ||
634 | void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev, | 634 | static void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev, |
635 | const struct b43_lcntab_tx_gain_tbl_entry *gain_table) | 635 | const struct b43_lcntab_tx_gain_tbl_entry *gain_table) |
636 | { | 636 | { |
637 | u32 i; | 637 | u32 i; |
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index 1d92d874ebb6..fc8a0fa6d3b2 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" |
@@ -36,15 +37,6 @@ config BRCMFMAC_SDIO | |||
36 | IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to | 37 | IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to |
37 | use the driver for a SDIO wireless card. | 38 | use the driver for a SDIO wireless card. |
38 | 39 | ||
39 | config BRCMFMAC_SDIO_OOB | ||
40 | bool "Out of band interrupt support for SDIO interface chipset" | ||
41 | depends on BRCMFMAC_SDIO | ||
42 | ---help--- | ||
43 | This option enables out-of-band interrupt support for Broadcom | ||
44 | SDIO Wifi chipset using fullmac in order to gain better | ||
45 | performance and deep sleep wake up capability on certain | ||
46 | platforms. Say N if you are unsure. | ||
47 | |||
48 | config BRCMFMAC_USB | 40 | config BRCMFMAC_USB |
49 | bool "USB bus interface support for FullMAC driver" | 41 | bool "USB bus interface support for FullMAC driver" |
50 | depends on USB | 42 | depends on USB |
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/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 11fd1c735589..4891e3df2058 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/mmc/sdio.h> | 25 | #include <linux/mmc/sdio.h> |
26 | #include <linux/mmc/sdio_func.h> | 26 | #include <linux/mmc/sdio_func.h> |
27 | #include <linux/mmc/card.h> | 27 | #include <linux/mmc/card.h> |
28 | #include <linux/platform_data/brcmfmac-sdio.h> | ||
28 | 29 | ||
29 | #include <defs.h> | 30 | #include <defs.h> |
30 | #include <brcm_hw_ids.h> | 31 | #include <brcm_hw_ids.h> |
@@ -37,16 +38,15 @@ | |||
37 | 38 | ||
38 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 | 39 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 |
39 | 40 | ||
40 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | 41 | |
41 | static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id) | 42 | static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id) |
42 | { | 43 | { |
43 | struct brcmf_bus *bus_if = dev_get_drvdata(dev_id); | 44 | struct brcmf_bus *bus_if = dev_get_drvdata(dev_id); |
44 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 45 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
45 | 46 | ||
46 | brcmf_dbg(INTR, "oob intr triggered\n"); | 47 | brcmf_dbg(INTR, "OOB intr triggered\n"); |
47 | 48 | ||
48 | /* | 49 | /* out-of-band interrupt is level-triggered which won't |
49 | * out-of-band interrupt is level-triggered which won't | ||
50 | * be cleared until dpc | 50 | * be cleared until dpc |
51 | */ | 51 | */ |
52 | if (sdiodev->irq_en) { | 52 | if (sdiodev->irq_en) { |
@@ -59,72 +59,12 @@ static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id) | |||
59 | return IRQ_HANDLED; | 59 | return IRQ_HANDLED; |
60 | } | 60 | } |
61 | 61 | ||
62 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | 62 | static void brcmf_sdio_ib_irqhandler(struct sdio_func *func) |
63 | { | ||
64 | int ret = 0; | ||
65 | u8 data; | ||
66 | unsigned long flags; | ||
67 | |||
68 | brcmf_dbg(TRACE, "Entering: irq %d\n", sdiodev->irq); | ||
69 | |||
70 | ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler, | ||
71 | sdiodev->irq_flags, "brcmf_oob_intr", | ||
72 | &sdiodev->func[1]->dev); | ||
73 | if (ret != 0) | ||
74 | return ret; | ||
75 | spin_lock_init(&sdiodev->irq_en_lock); | ||
76 | spin_lock_irqsave(&sdiodev->irq_en_lock, flags); | ||
77 | sdiodev->irq_en = true; | ||
78 | spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags); | ||
79 | |||
80 | ret = enable_irq_wake(sdiodev->irq); | ||
81 | if (ret != 0) | ||
82 | return ret; | ||
83 | sdiodev->irq_wake = true; | ||
84 | |||
85 | sdio_claim_host(sdiodev->func[1]); | ||
86 | |||
87 | /* must configure SDIO_CCCR_IENx to enable irq */ | ||
88 | data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret); | ||
89 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; | ||
90 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); | ||
91 | |||
92 | /* redirect, configure and enable io for interrupt signal */ | ||
93 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; | ||
94 | if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH) | ||
95 | data |= SDIO_SEPINT_ACT_HI; | ||
96 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); | ||
97 | |||
98 | sdio_release_host(sdiodev->func[1]); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | ||
104 | { | ||
105 | brcmf_dbg(TRACE, "Entering\n"); | ||
106 | |||
107 | sdio_claim_host(sdiodev->func[1]); | ||
108 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); | ||
109 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); | ||
110 | sdio_release_host(sdiodev->func[1]); | ||
111 | |||
112 | if (sdiodev->irq_wake) { | ||
113 | disable_irq_wake(sdiodev->irq); | ||
114 | sdiodev->irq_wake = false; | ||
115 | } | ||
116 | free_irq(sdiodev->irq, &sdiodev->func[1]->dev); | ||
117 | sdiodev->irq_en = false; | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | #else /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
122 | static void brcmf_sdio_irqhandler(struct sdio_func *func) | ||
123 | { | 63 | { |
124 | struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev); | 64 | struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev); |
125 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 65 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
126 | 66 | ||
127 | brcmf_dbg(INTR, "ib intr triggered\n"); | 67 | brcmf_dbg(INTR, "IB intr triggered\n"); |
128 | 68 | ||
129 | brcmf_sdbrcm_isr(sdiodev->bus); | 69 | brcmf_sdbrcm_isr(sdiodev->bus); |
130 | } | 70 | } |
@@ -136,28 +76,89 @@ static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func) | |||
136 | 76 | ||
137 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | 77 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) |
138 | { | 78 | { |
139 | brcmf_dbg(TRACE, "Entering\n"); | 79 | int ret = 0; |
80 | u8 data; | ||
81 | unsigned long flags; | ||
140 | 82 | ||
141 | sdio_claim_host(sdiodev->func[1]); | 83 | if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) { |
142 | sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler); | 84 | brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n", |
143 | sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler); | 85 | sdiodev->pdata->oob_irq_nr); |
144 | sdio_release_host(sdiodev->func[1]); | 86 | ret = request_irq(sdiodev->pdata->oob_irq_nr, |
87 | brcmf_sdio_oob_irqhandler, | ||
88 | sdiodev->pdata->oob_irq_flags, | ||
89 | "brcmf_oob_intr", | ||
90 | &sdiodev->func[1]->dev); | ||
91 | if (ret != 0) { | ||
92 | brcmf_err("request_irq failed %d\n", ret); | ||
93 | return ret; | ||
94 | } | ||
95 | sdiodev->oob_irq_requested = true; | ||
96 | spin_lock_init(&sdiodev->irq_en_lock); | ||
97 | spin_lock_irqsave(&sdiodev->irq_en_lock, flags); | ||
98 | sdiodev->irq_en = true; | ||
99 | spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags); | ||
100 | |||
101 | ret = enable_irq_wake(sdiodev->pdata->oob_irq_nr); | ||
102 | if (ret != 0) { | ||
103 | brcmf_err("enable_irq_wake failed %d\n", ret); | ||
104 | return ret; | ||
105 | } | ||
106 | sdiodev->irq_wake = true; | ||
107 | |||
108 | sdio_claim_host(sdiodev->func[1]); | ||
109 | |||
110 | /* must configure SDIO_CCCR_IENx to enable irq */ | ||
111 | data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret); | ||
112 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; | ||
113 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); | ||
114 | |||
115 | /* redirect, configure and enable io for interrupt signal */ | ||
116 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; | ||
117 | if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH) | ||
118 | data |= SDIO_SEPINT_ACT_HI; | ||
119 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); | ||
120 | |||
121 | sdio_release_host(sdiodev->func[1]); | ||
122 | } else { | ||
123 | brcmf_dbg(SDIO, "Entering\n"); | ||
124 | sdio_claim_host(sdiodev->func[1]); | ||
125 | sdio_claim_irq(sdiodev->func[1], brcmf_sdio_ib_irqhandler); | ||
126 | sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler); | ||
127 | sdio_release_host(sdiodev->func[1]); | ||
128 | } | ||
145 | 129 | ||
146 | return 0; | 130 | return 0; |
147 | } | 131 | } |
148 | 132 | ||
149 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | 133 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) |
150 | { | 134 | { |
151 | brcmf_dbg(TRACE, "Entering\n"); | 135 | brcmf_dbg(SDIO, "Entering\n"); |
152 | 136 | ||
153 | sdio_claim_host(sdiodev->func[1]); | 137 | if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) { |
154 | sdio_release_irq(sdiodev->func[2]); | 138 | sdio_claim_host(sdiodev->func[1]); |
155 | sdio_release_irq(sdiodev->func[1]); | 139 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); |
156 | sdio_release_host(sdiodev->func[1]); | 140 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); |
141 | sdio_release_host(sdiodev->func[1]); | ||
142 | |||
143 | if (sdiodev->oob_irq_requested) { | ||
144 | sdiodev->oob_irq_requested = false; | ||
145 | if (sdiodev->irq_wake) { | ||
146 | disable_irq_wake(sdiodev->pdata->oob_irq_nr); | ||
147 | sdiodev->irq_wake = false; | ||
148 | } | ||
149 | free_irq(sdiodev->pdata->oob_irq_nr, | ||
150 | &sdiodev->func[1]->dev); | ||
151 | sdiodev->irq_en = false; | ||
152 | } | ||
153 | } else { | ||
154 | sdio_claim_host(sdiodev->func[1]); | ||
155 | sdio_release_irq(sdiodev->func[2]); | ||
156 | sdio_release_irq(sdiodev->func[1]); | ||
157 | sdio_release_host(sdiodev->func[1]); | ||
158 | } | ||
157 | 159 | ||
158 | return 0; | 160 | return 0; |
159 | } | 161 | } |
160 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
161 | 162 | ||
162 | int | 163 | int |
163 | brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | 164 | brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) |
@@ -253,9 +254,9 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | |||
253 | u8 data; | 254 | u8 data; |
254 | int retval; | 255 | int retval; |
255 | 256 | ||
256 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); | 257 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); |
257 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); | 258 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); |
258 | brcmf_dbg(INFO, "data:0x%02x\n", data); | 259 | brcmf_dbg(SDIO, "data:0x%02x\n", data); |
259 | 260 | ||
260 | if (ret) | 261 | if (ret) |
261 | *ret = retval; | 262 | *ret = retval; |
@@ -268,9 +269,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | |||
268 | u32 data; | 269 | u32 data; |
269 | int retval; | 270 | int retval; |
270 | 271 | ||
271 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); | 272 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); |
272 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); | 273 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); |
273 | brcmf_dbg(INFO, "data:0x%08x\n", data); | 274 | brcmf_dbg(SDIO, "data:0x%08x\n", data); |
274 | 275 | ||
275 | if (ret) | 276 | if (ret) |
276 | *ret = retval; | 277 | *ret = retval; |
@@ -283,7 +284,7 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
283 | { | 284 | { |
284 | int retval; | 285 | int retval; |
285 | 286 | ||
286 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data); | 287 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data); |
287 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); | 288 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); |
288 | 289 | ||
289 | if (ret) | 290 | if (ret) |
@@ -295,7 +296,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
295 | { | 296 | { |
296 | int retval; | 297 | int retval; |
297 | 298 | ||
298 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data); | 299 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); |
299 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); | 300 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); |
300 | 301 | ||
301 | if (ret) | 302 | if (ret) |
@@ -358,7 +359,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
358 | uint width; | 359 | uint width; |
359 | int err = 0; | 360 | int err = 0; |
360 | 361 | ||
361 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", | 362 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", |
362 | fn, addr, pkt->len); | 363 | fn, addr, pkt->len); |
363 | 364 | ||
364 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 365 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; |
@@ -381,7 +382,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
381 | uint width; | 382 | uint width; |
382 | int err = 0; | 383 | int err = 0; |
383 | 384 | ||
384 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", | 385 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", |
385 | fn, addr, pktq->qlen); | 386 | fn, addr, pktq->qlen); |
386 | 387 | ||
387 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 388 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; |
@@ -428,7 +429,7 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
428 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | 429 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; |
429 | int err = 0; | 430 | int err = 0; |
430 | 431 | ||
431 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", | 432 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", |
432 | fn, addr, pkt->len); | 433 | fn, addr, pkt->len); |
433 | 434 | ||
434 | /* Async not implemented yet */ | 435 | /* Async not implemented yet */ |
@@ -457,48 +458,92 @@ done: | |||
457 | return err; | 458 | return err; |
458 | } | 459 | } |
459 | 460 | ||
460 | int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, | 461 | int |
461 | u8 *buf, uint nbytes) | 462 | brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, |
463 | u8 *data, uint size) | ||
462 | { | 464 | { |
463 | struct sk_buff *mypkt; | 465 | int bcmerror = 0; |
464 | bool write = rw ? SDIOH_WRITE : SDIOH_READ; | 466 | struct sk_buff *pkt; |
465 | int err; | 467 | u32 sdaddr; |
468 | uint dsize; | ||
469 | |||
470 | dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); | ||
471 | pkt = dev_alloc_skb(dsize); | ||
472 | if (!pkt) { | ||
473 | brcmf_err("dev_alloc_skb failed: len %d\n", dsize); | ||
474 | return -EIO; | ||
475 | } | ||
476 | pkt->priority = 0; | ||
466 | 477 | ||
467 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | 478 | /* Determine initial transfer parameters */ |
468 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | 479 | sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; |
480 | if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK) | ||
481 | dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr); | ||
482 | else | ||
483 | dsize = size; | ||
469 | 484 | ||
470 | mypkt = brcmu_pkt_buf_get_skb(nbytes); | 485 | sdio_claim_host(sdiodev->func[1]); |
471 | if (!mypkt) { | 486 | |
472 | brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n", | 487 | /* Do the transfer(s) */ |
473 | nbytes); | 488 | while (size) { |
474 | return -EIO; | 489 | /* Set the backplane window to include the start address */ |
490 | bcmerror = brcmf_sdcard_set_sbaddr_window(sdiodev, address); | ||
491 | if (bcmerror) | ||
492 | break; | ||
493 | |||
494 | brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n", | ||
495 | write ? "write" : "read", dsize, | ||
496 | sdaddr, address & SBSDIO_SBWINDOW_MASK); | ||
497 | |||
498 | sdaddr &= SBSDIO_SB_OFT_ADDR_MASK; | ||
499 | sdaddr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | ||
500 | |||
501 | skb_put(pkt, dsize); | ||
502 | if (write) | ||
503 | memcpy(pkt->data, data, dsize); | ||
504 | bcmerror = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, | ||
505 | write, SDIO_FUNC_1, | ||
506 | sdaddr, pkt); | ||
507 | if (bcmerror) { | ||
508 | brcmf_err("membytes transfer failed\n"); | ||
509 | break; | ||
510 | } | ||
511 | if (!write) | ||
512 | memcpy(data, pkt->data, dsize); | ||
513 | skb_trim(pkt, dsize); | ||
514 | |||
515 | /* Adjust for next transfer (if any) */ | ||
516 | size -= dsize; | ||
517 | if (size) { | ||
518 | data += dsize; | ||
519 | address += dsize; | ||
520 | sdaddr = 0; | ||
521 | dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); | ||
522 | } | ||
475 | } | 523 | } |
476 | 524 | ||
477 | /* For a write, copy the buffer data into the packet. */ | 525 | dev_kfree_skb(pkt); |
478 | if (write) | ||
479 | memcpy(mypkt->data, buf, nbytes); | ||
480 | 526 | ||
481 | err = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, write, | 527 | /* Return the window to backplane enumeration space for core access */ |
482 | SDIO_FUNC_1, addr, mypkt); | 528 | if (brcmf_sdcard_set_sbaddr_window(sdiodev, sdiodev->sbwad)) |
529 | brcmf_err("FAILED to set window back to 0x%x\n", | ||
530 | sdiodev->sbwad); | ||
483 | 531 | ||
484 | /* For a read, copy the packet data back to the buffer. */ | 532 | sdio_release_host(sdiodev->func[1]); |
485 | if (!err && !write) | ||
486 | memcpy(buf, mypkt->data, nbytes); | ||
487 | 533 | ||
488 | brcmu_pkt_buf_free_skb(mypkt); | 534 | return bcmerror; |
489 | return err; | ||
490 | } | 535 | } |
491 | 536 | ||
492 | int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) | 537 | int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) |
493 | { | 538 | { |
494 | char t_func = (char)fn; | 539 | char t_func = (char)fn; |
495 | brcmf_dbg(TRACE, "Enter\n"); | 540 | brcmf_dbg(SDIO, "Enter\n"); |
496 | 541 | ||
497 | /* issue abort cmd52 command through F0 */ | 542 | /* issue abort cmd52 command through F0 */ |
498 | brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, | 543 | brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, |
499 | SDIO_CCCR_ABORT, &t_func); | 544 | SDIO_CCCR_ABORT, &t_func); |
500 | 545 | ||
501 | brcmf_dbg(TRACE, "Exit\n"); | 546 | brcmf_dbg(SDIO, "Exit\n"); |
502 | return 0; | 547 | return 0; |
503 | } | 548 | } |
504 | 549 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index d92d373733d7..44fa0cdbf97b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/sched.h> /* request_irq() */ | 26 | #include <linux/sched.h> /* request_irq() */ |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/platform_data/brcmfmac-sdio.h> | ||
29 | #include <net/cfg80211.h> | 30 | #include <net/cfg80211.h> |
30 | 31 | ||
31 | #include <defs.h> | 32 | #include <defs.h> |
@@ -40,32 +41,30 @@ | |||
40 | 41 | ||
41 | #define DMA_ALIGN_MASK 0x03 | 42 | #define DMA_ALIGN_MASK 0x03 |
42 | 43 | ||
44 | #define SDIO_DEVICE_ID_BROADCOM_43143 43143 | ||
43 | #define SDIO_DEVICE_ID_BROADCOM_43241 0x4324 | 45 | #define SDIO_DEVICE_ID_BROADCOM_43241 0x4324 |
44 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 | 46 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 |
45 | #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 | 47 | #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 |
46 | #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 | 48 | #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 |
49 | #define SDIO_DEVICE_ID_BROADCOM_4335 0x4335 | ||
47 | 50 | ||
48 | #define SDIO_FUNC1_BLOCKSIZE 64 | 51 | #define SDIO_FUNC1_BLOCKSIZE 64 |
49 | #define SDIO_FUNC2_BLOCKSIZE 512 | 52 | #define SDIO_FUNC2_BLOCKSIZE 512 |
50 | 53 | ||
51 | /* devices we support, null terminated */ | 54 | /* devices we support, null terminated */ |
52 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { | 55 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { |
56 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)}, | ||
53 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)}, | 57 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)}, |
54 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, | 58 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, |
55 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, | 59 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, |
56 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, | 60 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, |
61 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4335)}, | ||
57 | { /* end: all zeroes */ }, | 62 | { /* end: all zeroes */ }, |
58 | }; | 63 | }; |
59 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | 64 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); |
60 | 65 | ||
61 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | 66 | static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata; |
62 | static struct list_head oobirq_lh; | 67 | |
63 | struct brcmf_sdio_oobirq { | ||
64 | unsigned int irq; | ||
65 | unsigned long flags; | ||
66 | struct list_head list; | ||
67 | }; | ||
68 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
69 | 68 | ||
70 | static bool | 69 | static bool |
71 | brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) | 70 | brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) |
@@ -139,7 +138,7 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, | |||
139 | { | 138 | { |
140 | int err_ret; | 139 | int err_ret; |
141 | 140 | ||
142 | brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); | 141 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); |
143 | 142 | ||
144 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); | 143 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); |
145 | if (brcmf_pm_resume_error(sdiodev)) | 144 | if (brcmf_pm_resume_error(sdiodev)) |
@@ -179,7 +178,7 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, | |||
179 | return -EINVAL; | 178 | return -EINVAL; |
180 | } | 179 | } |
181 | 180 | ||
182 | brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", | 181 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", |
183 | rw, func, addr, nbytes); | 182 | rw, func, addr, nbytes); |
184 | 183 | ||
185 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); | 184 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); |
@@ -252,7 +251,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, | |||
252 | 251 | ||
253 | struct sk_buff *pkt; | 252 | struct sk_buff *pkt; |
254 | 253 | ||
255 | brcmf_dbg(TRACE, "Enter\n"); | 254 | brcmf_dbg(SDIO, "Enter\n"); |
256 | 255 | ||
257 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait); | 256 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait); |
258 | if (brcmf_pm_resume_error(sdiodev)) | 257 | if (brcmf_pm_resume_error(sdiodev)) |
@@ -270,7 +269,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, | |||
270 | write ? "TX" : "RX", pkt, SGCount, addr, | 269 | write ? "TX" : "RX", pkt, SGCount, addr, |
271 | pkt_len, err_ret); | 270 | pkt_len, err_ret); |
272 | } else { | 271 | } else { |
273 | brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n", | 272 | brcmf_dbg(SDIO, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n", |
274 | write ? "TX" : "RX", pkt, SGCount, addr, | 273 | write ? "TX" : "RX", pkt, SGCount, addr, |
275 | pkt_len); | 274 | pkt_len); |
276 | } | 275 | } |
@@ -280,7 +279,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, | |||
280 | SGCount++; | 279 | SGCount++; |
281 | } | 280 | } |
282 | 281 | ||
283 | brcmf_dbg(TRACE, "Exit\n"); | 282 | brcmf_dbg(SDIO, "Exit\n"); |
284 | return err_ret; | 283 | return err_ret; |
285 | } | 284 | } |
286 | 285 | ||
@@ -295,7 +294,7 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, | |||
295 | uint pkt_len; | 294 | uint pkt_len; |
296 | bool fifo = (fix_inc == SDIOH_DATA_FIX); | 295 | bool fifo = (fix_inc == SDIOH_DATA_FIX); |
297 | 296 | ||
298 | brcmf_dbg(TRACE, "Enter\n"); | 297 | brcmf_dbg(SDIO, "Enter\n"); |
299 | 298 | ||
300 | if (pkt == NULL) | 299 | if (pkt == NULL) |
301 | return -EINVAL; | 300 | return -EINVAL; |
@@ -314,7 +313,7 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, | |||
314 | brcmf_err("%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", | 313 | brcmf_err("%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", |
315 | write ? "TX" : "RX", pkt, addr, pkt_len, status); | 314 | write ? "TX" : "RX", pkt, addr, pkt_len, status); |
316 | } else { | 315 | } else { |
317 | brcmf_dbg(TRACE, "%s xfr'd %p, addr=0x%05x, len=%d\n", | 316 | brcmf_dbg(SDIO, "%s xfr'd %p, addr=0x%05x, len=%d\n", |
318 | write ? "TX" : "RX", pkt, addr, pkt_len); | 317 | write ? "TX" : "RX", pkt, addr, pkt_len); |
319 | } | 318 | } |
320 | 319 | ||
@@ -350,12 +349,12 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) | |||
350 | u32 fbraddr; | 349 | u32 fbraddr; |
351 | u8 func; | 350 | u8 func; |
352 | 351 | ||
353 | brcmf_dbg(TRACE, "\n"); | 352 | brcmf_dbg(SDIO, "\n"); |
354 | 353 | ||
355 | /* Get the Card's common CIS address */ | 354 | /* Get the Card's common CIS address */ |
356 | sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev, | 355 | sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev, |
357 | SDIO_CCCR_CIS); | 356 | SDIO_CCCR_CIS); |
358 | brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n", | 357 | brcmf_dbg(SDIO, "Card's Common CIS Ptr = 0x%x\n", |
359 | sdiodev->func_cis_ptr[0]); | 358 | sdiodev->func_cis_ptr[0]); |
360 | 359 | ||
361 | /* Get the Card's function CIS (for each function) */ | 360 | /* Get the Card's function CIS (for each function) */ |
@@ -363,7 +362,7 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) | |||
363 | func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { | 362 | func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { |
364 | sdiodev->func_cis_ptr[func] = | 363 | sdiodev->func_cis_ptr[func] = |
365 | brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr); | 364 | brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr); |
366 | brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n", | 365 | brcmf_dbg(SDIO, "Function %d CIS Ptr = 0x%x\n", |
367 | func, sdiodev->func_cis_ptr[func]); | 366 | func, sdiodev->func_cis_ptr[func]); |
368 | } | 367 | } |
369 | 368 | ||
@@ -382,7 +381,7 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) | |||
382 | { | 381 | { |
383 | int err_ret = 0; | 382 | int err_ret = 0; |
384 | 383 | ||
385 | brcmf_dbg(TRACE, "\n"); | 384 | brcmf_dbg(SDIO, "\n"); |
386 | 385 | ||
387 | sdiodev->num_funcs = 2; | 386 | sdiodev->num_funcs = 2; |
388 | 387 | ||
@@ -404,13 +403,13 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) | |||
404 | 403 | ||
405 | out: | 404 | out: |
406 | sdio_release_host(sdiodev->func[1]); | 405 | sdio_release_host(sdiodev->func[1]); |
407 | brcmf_dbg(TRACE, "Done\n"); | 406 | brcmf_dbg(SDIO, "Done\n"); |
408 | return err_ret; | 407 | return err_ret; |
409 | } | 408 | } |
410 | 409 | ||
411 | void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) | 410 | void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) |
412 | { | 411 | { |
413 | brcmf_dbg(TRACE, "\n"); | 412 | brcmf_dbg(SDIO, "\n"); |
414 | 413 | ||
415 | /* Disable Function 2 */ | 414 | /* Disable Function 2 */ |
416 | sdio_claim_host(sdiodev->func[2]); | 415 | sdio_claim_host(sdiodev->func[2]); |
@@ -424,33 +423,6 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) | |||
424 | 423 | ||
425 | } | 424 | } |
426 | 425 | ||
427 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | ||
428 | static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev) | ||
429 | { | ||
430 | struct brcmf_sdio_oobirq *oobirq_entry; | ||
431 | |||
432 | if (list_empty(&oobirq_lh)) { | ||
433 | brcmf_err("no valid oob irq resource\n"); | ||
434 | return -ENXIO; | ||
435 | } | ||
436 | |||
437 | oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq, | ||
438 | list); | ||
439 | |||
440 | sdiodev->irq = oobirq_entry->irq; | ||
441 | sdiodev->irq_flags = oobirq_entry->flags; | ||
442 | list_del(&oobirq_entry->list); | ||
443 | kfree(oobirq_entry); | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | #else | ||
448 | static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev) | ||
449 | { | ||
450 | return 0; | ||
451 | } | ||
452 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
453 | |||
454 | static int brcmf_ops_sdio_probe(struct sdio_func *func, | 426 | static int brcmf_ops_sdio_probe(struct sdio_func *func, |
455 | const struct sdio_device_id *id) | 427 | const struct sdio_device_id *id) |
456 | { | 428 | { |
@@ -458,11 +430,11 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
458 | struct brcmf_sdio_dev *sdiodev; | 430 | struct brcmf_sdio_dev *sdiodev; |
459 | struct brcmf_bus *bus_if; | 431 | struct brcmf_bus *bus_if; |
460 | 432 | ||
461 | brcmf_dbg(TRACE, "Enter\n"); | 433 | brcmf_dbg(SDIO, "Enter\n"); |
462 | brcmf_dbg(TRACE, "Class=%x\n", func->class); | 434 | brcmf_dbg(SDIO, "Class=%x\n", func->class); |
463 | brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor); | 435 | brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor); |
464 | brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device); | 436 | brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); |
465 | brcmf_dbg(TRACE, "Function#: %d\n", func->num); | 437 | brcmf_dbg(SDIO, "Function#: %d\n", func->num); |
466 | 438 | ||
467 | /* Consume func num 1 but dont do anything with it. */ | 439 | /* Consume func num 1 but dont do anything with it. */ |
468 | if (func->num == 1) | 440 | if (func->num == 1) |
@@ -491,23 +463,21 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
491 | dev_set_drvdata(&func->dev, bus_if); | 463 | dev_set_drvdata(&func->dev, bus_if); |
492 | dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); | 464 | dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); |
493 | sdiodev->dev = &sdiodev->func[1]->dev; | 465 | sdiodev->dev = &sdiodev->func[1]->dev; |
466 | sdiodev->pdata = brcmfmac_sdio_pdata; | ||
494 | 467 | ||
495 | atomic_set(&sdiodev->suspend, false); | 468 | atomic_set(&sdiodev->suspend, false); |
496 | init_waitqueue_head(&sdiodev->request_byte_wait); | 469 | init_waitqueue_head(&sdiodev->request_byte_wait); |
497 | init_waitqueue_head(&sdiodev->request_word_wait); | 470 | init_waitqueue_head(&sdiodev->request_word_wait); |
498 | init_waitqueue_head(&sdiodev->request_chain_wait); | 471 | init_waitqueue_head(&sdiodev->request_chain_wait); |
499 | init_waitqueue_head(&sdiodev->request_buffer_wait); | 472 | init_waitqueue_head(&sdiodev->request_buffer_wait); |
500 | err = brcmf_sdio_getintrcfg(sdiodev); | ||
501 | if (err) | ||
502 | goto fail; | ||
503 | 473 | ||
504 | brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n"); | 474 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n"); |
505 | err = brcmf_sdio_probe(sdiodev); | 475 | err = brcmf_sdio_probe(sdiodev); |
506 | if (err) { | 476 | if (err) { |
507 | brcmf_err("F2 error, probe failed %d...\n", err); | 477 | brcmf_err("F2 error, probe failed %d...\n", err); |
508 | goto fail; | 478 | goto fail; |
509 | } | 479 | } |
510 | brcmf_dbg(TRACE, "F2 init completed...\n"); | 480 | brcmf_dbg(SDIO, "F2 init completed...\n"); |
511 | return 0; | 481 | return 0; |
512 | 482 | ||
513 | fail: | 483 | fail: |
@@ -523,10 +493,10 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) | |||
523 | struct brcmf_bus *bus_if; | 493 | struct brcmf_bus *bus_if; |
524 | struct brcmf_sdio_dev *sdiodev; | 494 | struct brcmf_sdio_dev *sdiodev; |
525 | 495 | ||
526 | brcmf_dbg(TRACE, "Enter\n"); | 496 | brcmf_dbg(SDIO, "Enter\n"); |
527 | brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor); | 497 | brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor); |
528 | brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device); | 498 | brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); |
529 | brcmf_dbg(TRACE, "Function: %d\n", func->num); | 499 | brcmf_dbg(SDIO, "Function: %d\n", func->num); |
530 | 500 | ||
531 | if (func->num != 1 && func->num != 2) | 501 | if (func->num != 1 && func->num != 2) |
532 | return; | 502 | return; |
@@ -543,7 +513,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) | |||
543 | kfree(sdiodev); | 513 | kfree(sdiodev); |
544 | } | 514 | } |
545 | 515 | ||
546 | brcmf_dbg(TRACE, "Exit\n"); | 516 | brcmf_dbg(SDIO, "Exit\n"); |
547 | } | 517 | } |
548 | 518 | ||
549 | #ifdef CONFIG_PM_SLEEP | 519 | #ifdef CONFIG_PM_SLEEP |
@@ -554,7 +524,7 @@ static int brcmf_sdio_suspend(struct device *dev) | |||
554 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 524 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
555 | int ret = 0; | 525 | int ret = 0; |
556 | 526 | ||
557 | brcmf_dbg(TRACE, "\n"); | 527 | brcmf_dbg(SDIO, "\n"); |
558 | 528 | ||
559 | atomic_set(&sdiodev->suspend, true); | 529 | atomic_set(&sdiodev->suspend, true); |
560 | 530 | ||
@@ -594,7 +564,7 @@ static const struct dev_pm_ops brcmf_sdio_pm_ops = { | |||
594 | static struct sdio_driver brcmf_sdmmc_driver = { | 564 | static struct sdio_driver brcmf_sdmmc_driver = { |
595 | .probe = brcmf_ops_sdio_probe, | 565 | .probe = brcmf_ops_sdio_probe, |
596 | .remove = brcmf_ops_sdio_remove, | 566 | .remove = brcmf_ops_sdio_remove, |
597 | .name = "brcmfmac", | 567 | .name = BRCMFMAC_SDIO_PDATA_NAME, |
598 | .id_table = brcmf_sdmmc_ids, | 568 | .id_table = brcmf_sdmmc_ids, |
599 | #ifdef CONFIG_PM_SLEEP | 569 | #ifdef CONFIG_PM_SLEEP |
600 | .drv = { | 570 | .drv = { |
@@ -603,83 +573,65 @@ static struct sdio_driver brcmf_sdmmc_driver = { | |||
603 | #endif /* CONFIG_PM_SLEEP */ | 573 | #endif /* CONFIG_PM_SLEEP */ |
604 | }; | 574 | }; |
605 | 575 | ||
606 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | ||
607 | static int brcmf_sdio_pd_probe(struct platform_device *pdev) | 576 | static int brcmf_sdio_pd_probe(struct platform_device *pdev) |
608 | { | 577 | { |
609 | struct resource *res; | 578 | int ret; |
610 | struct brcmf_sdio_oobirq *oobirq_entry; | ||
611 | int i, ret; | ||
612 | 579 | ||
613 | INIT_LIST_HEAD(&oobirq_lh); | 580 | brcmf_dbg(SDIO, "Enter\n"); |
614 | 581 | ||
615 | for (i = 0; ; i++) { | 582 | brcmfmac_sdio_pdata = pdev->dev.platform_data; |
616 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | ||
617 | if (!res) | ||
618 | break; | ||
619 | 583 | ||
620 | oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq), | 584 | if (brcmfmac_sdio_pdata->power_on) |
621 | GFP_KERNEL); | 585 | brcmfmac_sdio_pdata->power_on(); |
622 | if (!oobirq_entry) | ||
623 | return -ENOMEM; | ||
624 | oobirq_entry->irq = res->start; | ||
625 | oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK; | ||
626 | list_add_tail(&oobirq_entry->list, &oobirq_lh); | ||
627 | } | ||
628 | if (i == 0) | ||
629 | return -ENXIO; | ||
630 | 586 | ||
631 | ret = sdio_register_driver(&brcmf_sdmmc_driver); | 587 | ret = sdio_register_driver(&brcmf_sdmmc_driver); |
632 | |||
633 | if (ret) | 588 | if (ret) |
634 | brcmf_err("sdio_register_driver failed: %d\n", ret); | 589 | brcmf_err("sdio_register_driver failed: %d\n", ret); |
635 | 590 | ||
636 | return ret; | 591 | return ret; |
637 | } | 592 | } |
638 | 593 | ||
639 | static struct platform_driver brcmf_sdio_pd = { | 594 | static int brcmf_sdio_pd_remove(struct platform_device *pdev) |
640 | .probe = brcmf_sdio_pd_probe, | ||
641 | .driver = { | ||
642 | .name = "brcmf_sdio_pd" | ||
643 | } | ||
644 | }; | ||
645 | |||
646 | void brcmf_sdio_exit(void) | ||
647 | { | 595 | { |
648 | brcmf_dbg(TRACE, "Enter\n"); | 596 | brcmf_dbg(SDIO, "Enter\n"); |
597 | |||
598 | if (brcmfmac_sdio_pdata->power_off) | ||
599 | brcmfmac_sdio_pdata->power_off(); | ||
649 | 600 | ||
650 | sdio_unregister_driver(&brcmf_sdmmc_driver); | 601 | sdio_unregister_driver(&brcmf_sdmmc_driver); |
651 | 602 | ||
652 | platform_driver_unregister(&brcmf_sdio_pd); | 603 | return 0; |
653 | } | 604 | } |
654 | 605 | ||
655 | void brcmf_sdio_init(void) | 606 | static struct platform_driver brcmf_sdio_pd = { |
656 | { | 607 | .remove = brcmf_sdio_pd_remove, |
657 | int ret; | 608 | .driver = { |
658 | 609 | .name = BRCMFMAC_SDIO_PDATA_NAME | |
659 | brcmf_dbg(TRACE, "Enter\n"); | 610 | } |
660 | 611 | }; | |
661 | ret = platform_driver_register(&brcmf_sdio_pd); | ||
662 | 612 | ||
663 | if (ret) | ||
664 | brcmf_err("platform_driver_register failed: %d\n", ret); | ||
665 | } | ||
666 | #else | ||
667 | void brcmf_sdio_exit(void) | 613 | void brcmf_sdio_exit(void) |
668 | { | 614 | { |
669 | brcmf_dbg(TRACE, "Enter\n"); | 615 | brcmf_dbg(SDIO, "Enter\n"); |
670 | 616 | ||
671 | sdio_unregister_driver(&brcmf_sdmmc_driver); | 617 | if (brcmfmac_sdio_pdata) |
618 | platform_driver_unregister(&brcmf_sdio_pd); | ||
619 | else | ||
620 | sdio_unregister_driver(&brcmf_sdmmc_driver); | ||
672 | } | 621 | } |
673 | 622 | ||
674 | void brcmf_sdio_init(void) | 623 | void brcmf_sdio_init(void) |
675 | { | 624 | { |
676 | int ret; | 625 | int ret; |
677 | 626 | ||
678 | brcmf_dbg(TRACE, "Enter\n"); | 627 | brcmf_dbg(SDIO, "Enter\n"); |
679 | 628 | ||
680 | ret = sdio_register_driver(&brcmf_sdmmc_driver); | 629 | ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe); |
630 | if (ret == -ENODEV) { | ||
631 | brcmf_dbg(SDIO, "No platform data available, registering without.\n"); | ||
632 | ret = sdio_register_driver(&brcmf_sdmmc_driver); | ||
633 | } | ||
681 | 634 | ||
682 | if (ret) | 635 | if (ret) |
683 | brcmf_err("sdio_register_driver failed: %d\n", ret); | 636 | brcmf_err("driver registration failed: %d\n", ret); |
684 | } | 637 | } |
685 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index ef6f23be6d32..28db9cf39672 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -28,6 +28,7 @@ | |||
28 | /******************************************************************************* | 28 | /******************************************************************************* |
29 | * IO codes that are interpreted by dongle firmware | 29 | * IO codes that are interpreted by dongle firmware |
30 | ******************************************************************************/ | 30 | ******************************************************************************/ |
31 | #define BRCMF_C_GET_VERSION 1 | ||
31 | #define BRCMF_C_UP 2 | 32 | #define BRCMF_C_UP 2 |
32 | #define BRCMF_C_DOWN 3 | 33 | #define BRCMF_C_DOWN 3 |
33 | #define BRCMF_C_SET_PROMISC 10 | 34 | #define BRCMF_C_SET_PROMISC 10 |
@@ -72,6 +73,7 @@ | |||
72 | #define BRCMF_C_SET_WSEC 134 | 73 | #define BRCMF_C_SET_WSEC 134 |
73 | #define BRCMF_C_GET_PHY_NOISE 135 | 74 | #define BRCMF_C_GET_PHY_NOISE 135 |
74 | #define BRCMF_C_GET_BSS_INFO 136 | 75 | #define BRCMF_C_GET_BSS_INFO 136 |
76 | #define BRCMF_C_GET_BANDLIST 140 | ||
75 | #define BRCMF_C_SET_SCB_TIMEOUT 158 | 77 | #define BRCMF_C_SET_SCB_TIMEOUT 158 |
76 | #define BRCMF_C_GET_PHYLIST 180 | 78 | #define BRCMF_C_GET_PHYLIST 180 |
77 | #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 | 79 | #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 |
@@ -475,6 +477,11 @@ struct brcmf_sta_info_le { | |||
475 | __le32 rx_decrypt_failures; /* # of packet decrypted failed */ | 477 | __le32 rx_decrypt_failures; /* # of packet decrypted failed */ |
476 | }; | 478 | }; |
477 | 479 | ||
480 | struct brcmf_chanspec_list { | ||
481 | __le32 count; /* # of entries */ | ||
482 | __le32 element[1]; /* variable length uint32 list */ | ||
483 | }; | ||
484 | |||
478 | /* | 485 | /* |
479 | * WLC_E_PROBRESP_MSG | 486 | * WLC_E_PROBRESP_MSG |
480 | * WLC_E_P2P_PROBREQ_MSG | 487 | * WLC_E_P2P_PROBREQ_MSG |
@@ -501,6 +508,7 @@ struct brcmf_dcmd { | |||
501 | /* Forward decls for struct brcmf_pub (see below) */ | 508 | /* Forward decls for struct brcmf_pub (see below) */ |
502 | struct brcmf_proto; /* device communication protocol info */ | 509 | struct brcmf_proto; /* device communication protocol info */ |
503 | struct brcmf_cfg80211_dev; /* cfg80211 device info */ | 510 | struct brcmf_cfg80211_dev; /* cfg80211 device info */ |
511 | struct brcmf_fws_info; /* firmware signalling info */ | ||
504 | 512 | ||
505 | /* Common structure for module and instance linkage */ | 513 | /* Common structure for module and instance linkage */ |
506 | struct brcmf_pub { | 514 | struct brcmf_pub { |
@@ -527,6 +535,10 @@ struct brcmf_pub { | |||
527 | unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; | 535 | unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; |
528 | 536 | ||
529 | struct brcmf_fweh_info fweh; | 537 | struct brcmf_fweh_info fweh; |
538 | |||
539 | bool fw_signals; | ||
540 | struct brcmf_fws_info *fws; | ||
541 | spinlock_t fws_spinlock; | ||
530 | #ifdef DEBUG | 542 | #ifdef DEBUG |
531 | struct dentry *dbgfs_dir; | 543 | struct dentry *dbgfs_dir; |
532 | #endif | 544 | #endif |
@@ -537,10 +549,25 @@ struct brcmf_if_event { | |||
537 | u8 action; | 549 | u8 action; |
538 | u8 flags; | 550 | u8 flags; |
539 | u8 bssidx; | 551 | u8 bssidx; |
552 | u8 role; | ||
540 | }; | 553 | }; |
541 | 554 | ||
542 | /* forward declaration */ | 555 | /* forward declarations */ |
543 | struct brcmf_cfg80211_vif; | 556 | struct brcmf_cfg80211_vif; |
557 | struct brcmf_fws_mac_descriptor; | ||
558 | |||
559 | /** | ||
560 | * enum brcmf_netif_stop_reason - reason for stopping netif queue. | ||
561 | * | ||
562 | * @BRCMF_NETIF_STOP_REASON_FWS_FC: | ||
563 | * netif stopped due to firmware signalling flow control. | ||
564 | * @BRCMF_NETIF_STOP_REASON_BLOCK_BUS: | ||
565 | * netif stopped due to bus blocking. | ||
566 | */ | ||
567 | enum brcmf_netif_stop_reason { | ||
568 | BRCMF_NETIF_STOP_REASON_FWS_FC = 1, | ||
569 | BRCMF_NETIF_STOP_REASON_BLOCK_BUS = 2 | ||
570 | }; | ||
544 | 571 | ||
545 | /** | 572 | /** |
546 | * struct brcmf_if - interface control information. | 573 | * struct brcmf_if - interface control information. |
@@ -549,9 +576,13 @@ struct brcmf_cfg80211_vif; | |||
549 | * @vif: points to cfg80211 specific interface information. | 576 | * @vif: points to cfg80211 specific interface information. |
550 | * @ndev: associated network device. | 577 | * @ndev: associated network device. |
551 | * @stats: interface specific network statistics. | 578 | * @stats: interface specific network statistics. |
579 | * @setmacaddr_work: worker object for setting mac address. | ||
580 | * @multicast_work: worker object for multicast provisioning. | ||
581 | * @fws_desc: interface specific firmware-signalling descriptor. | ||
552 | * @ifidx: interface index in device firmware. | 582 | * @ifidx: interface index in device firmware. |
553 | * @bssidx: index of bss associated with this interface. | 583 | * @bssidx: index of bss associated with this interface. |
554 | * @mac_addr: assigned mac address. | 584 | * @mac_addr: assigned mac address. |
585 | * @netif_stop: bitmap indicates reason why netif queues are stopped. | ||
555 | * @pend_8021x_cnt: tracks outstanding number of 802.1x frames. | 586 | * @pend_8021x_cnt: tracks outstanding number of 802.1x frames. |
556 | * @pend_8021x_wait: used for signalling change in count. | 587 | * @pend_8021x_wait: used for signalling change in count. |
557 | */ | 588 | */ |
@@ -562,9 +593,11 @@ struct brcmf_if { | |||
562 | struct net_device_stats stats; | 593 | struct net_device_stats stats; |
563 | struct work_struct setmacaddr_work; | 594 | struct work_struct setmacaddr_work; |
564 | struct work_struct multicast_work; | 595 | struct work_struct multicast_work; |
596 | struct brcmf_fws_mac_descriptor *fws_desc; | ||
565 | int ifidx; | 597 | int ifidx; |
566 | s32 bssidx; | 598 | s32 bssidx; |
567 | u8 mac_addr[ETH_ALEN]; | 599 | u8 mac_addr[ETH_ALEN]; |
600 | u8 netif_stop; | ||
568 | atomic_t pend_8021x_cnt; | 601 | atomic_t pend_8021x_cnt; |
569 | wait_queue_head_t pend_8021x_wait; | 602 | wait_queue_head_t pend_8021x_wait; |
570 | }; | 603 | }; |
@@ -582,13 +615,17 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | |||
582 | void *buf, uint len); | 615 | void *buf, uint len); |
583 | 616 | ||
584 | /* Remove any protocol-specific data header. */ | 617 | /* Remove any protocol-specific data header. */ |
585 | extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, | 618 | extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, |
586 | struct sk_buff *rxp); | 619 | struct sk_buff *rxp); |
587 | 620 | ||
588 | extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); | 621 | extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); |
589 | extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, | 622 | extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, |
590 | s32 ifidx, char *name, u8 *mac_addr); | 623 | s32 ifidx, char *name, u8 *mac_addr); |
591 | extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); | 624 | extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); |
625 | void brcmf_txflowblock_if(struct brcmf_if *ifp, | ||
626 | enum brcmf_netif_stop_reason reason, bool state); | ||
592 | extern u32 brcmf_get_chip_info(struct brcmf_if *ifp); | 627 | extern u32 brcmf_get_chip_info(struct brcmf_if *ifp); |
628 | extern void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, | ||
629 | bool success); | ||
593 | 630 | ||
594 | #endif /* _BRCMF_H_ */ | 631 | #endif /* _BRCMF_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index ad25c3408b59..080395f49fa5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -39,10 +39,12 @@ struct brcmf_bus_dcmd { | |||
39 | * @txdata: send a data frame to the dongle (callee disposes skb). | 39 | * @txdata: send a data frame to the dongle (callee disposes skb). |
40 | * @txctl: transmit a control request message to dongle. | 40 | * @txctl: transmit a control request message to dongle. |
41 | * @rxctl: receive a control response message from dongle. | 41 | * @rxctl: receive a control response message from dongle. |
42 | * @gettxq: obtain a reference of bus transmit queue (optional). | ||
42 | * | 43 | * |
43 | * This structure provides an abstract interface towards the | 44 | * This structure provides an abstract interface towards the |
44 | * bus specific driver. For control messages to common driver | 45 | * bus specific driver. For control messages to common driver |
45 | * will assure there is only one active transaction. | 46 | * will assure there is only one active transaction. Unless |
47 | * indicated otherwise these callbacks are mandatory. | ||
46 | */ | 48 | */ |
47 | struct brcmf_bus_ops { | 49 | struct brcmf_bus_ops { |
48 | int (*init)(struct device *dev); | 50 | int (*init)(struct device *dev); |
@@ -50,6 +52,7 @@ struct brcmf_bus_ops { | |||
50 | int (*txdata)(struct device *dev, struct sk_buff *skb); | 52 | int (*txdata)(struct device *dev, struct sk_buff *skb); |
51 | int (*txctl)(struct device *dev, unsigned char *msg, uint len); | 53 | int (*txctl)(struct device *dev, unsigned char *msg, uint len); |
52 | int (*rxctl)(struct device *dev, unsigned char *msg, uint len); | 54 | int (*rxctl)(struct device *dev, unsigned char *msg, uint len); |
55 | struct pktq * (*gettxq)(struct device *dev); | ||
53 | }; | 56 | }; |
54 | 57 | ||
55 | /** | 58 | /** |
@@ -115,6 +118,14 @@ int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len) | |||
115 | return bus->ops->rxctl(bus->dev, msg, len); | 118 | return bus->ops->rxctl(bus->dev, msg, len); |
116 | } | 119 | } |
117 | 120 | ||
121 | static inline | ||
122 | struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus) | ||
123 | { | ||
124 | if (!bus->ops->gettxq) | ||
125 | return ERR_PTR(-ENOENT); | ||
126 | |||
127 | return bus->ops->gettxq(bus->dev); | ||
128 | } | ||
118 | /* | 129 | /* |
119 | * interface functions from common layer | 130 | * interface functions from common layer |
120 | */ | 131 | */ |
@@ -134,7 +145,7 @@ extern void brcmf_dev_reset(struct device *dev); | |||
134 | /* Indication from bus module to change flow-control state */ | 145 | /* Indication from bus module to change flow-control state */ |
135 | extern void brcmf_txflowblock(struct device *dev, bool state); | 146 | extern void brcmf_txflowblock(struct device *dev, bool state); |
136 | 147 | ||
137 | /* Notify tx completion */ | 148 | /* Notify the bus has transferred the tx packet to firmware */ |
138 | extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, | 149 | extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, |
139 | bool success); | 150 | bool success); |
140 | 151 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index a2354d951dd7..59c77aa3b959 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; |
@@ -290,8 +303,8 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, | |||
290 | 303 | ||
291 | /* Pop BDC header used to convey priority for buses that don't */ | 304 | /* Pop BDC header used to convey priority for buses that don't */ |
292 | 305 | ||
293 | if (pktbuf->len < BDC_HEADER_LEN) { | 306 | if (pktbuf->len <= BDC_HEADER_LEN) { |
294 | brcmf_err("rx data too short (%d < %d)\n", | 307 | brcmf_dbg(INFO, "rx data too short (%d <= %d)\n", |
295 | pktbuf->len, BDC_HEADER_LEN); | 308 | pktbuf->len, BDC_HEADER_LEN); |
296 | return -EBADE; | 309 | return -EBADE; |
297 | } | 310 | } |
@@ -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..202869cd0932 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,82 @@ 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[650]; | ||
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 | "mac_update_fails: %u\n" | ||
146 | "ps_update_fails: %u\n" | ||
147 | "if_update_fails: %u\n" | ||
148 | "pkt2bus: %u\n" | ||
149 | "generic_error: %u\n" | ||
150 | "rollback_success: %u\n" | ||
151 | "rollback_failed: %u\n" | ||
152 | "delayq_full: %u\n" | ||
153 | "supprq_full: %u\n" | ||
154 | "txs_indicate: %u\n" | ||
155 | "txs_discard: %u\n" | ||
156 | "txs_suppr_core: %u\n" | ||
157 | "txs_suppr_ps: %u\n" | ||
158 | "txs_tossed: %u\n" | ||
159 | "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n" | ||
160 | "fifo_credits_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n", | ||
161 | fwstats->header_pulls, | ||
162 | fwstats->header_only_pkt, | ||
163 | fwstats->tlv_parse_failed, | ||
164 | fwstats->tlv_invalid_type, | ||
165 | fwstats->mac_update_failed, | ||
166 | fwstats->mac_ps_update_failed, | ||
167 | fwstats->if_update_failed, | ||
168 | fwstats->pkt2bus, | ||
169 | fwstats->generic_error, | ||
170 | fwstats->rollback_success, | ||
171 | fwstats->rollback_failed, | ||
172 | fwstats->delayq_full_error, | ||
173 | fwstats->supprq_full_error, | ||
174 | fwstats->txs_indicate, | ||
175 | fwstats->txs_discard, | ||
176 | fwstats->txs_supp_core, | ||
177 | fwstats->txs_supp_ps, | ||
178 | fwstats->txs_tossed, | ||
179 | fwstats->send_pkts[0], fwstats->send_pkts[1], | ||
180 | fwstats->send_pkts[2], fwstats->send_pkts[3], | ||
181 | fwstats->send_pkts[4], | ||
182 | fwstats->fifo_credits_sent[0], | ||
183 | fwstats->fifo_credits_sent[1], | ||
184 | fwstats->fifo_credits_sent[2], | ||
185 | fwstats->fifo_credits_sent[3], | ||
186 | fwstats->fifo_credits_sent[4]); | ||
187 | |||
188 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
189 | } | ||
190 | |||
191 | static const struct file_operations brcmf_debugfs_fws_stats_ops = { | ||
192 | .owner = THIS_MODULE, | ||
193 | .open = simple_open, | ||
194 | .read = brcmf_debugfs_fws_stats_read | ||
195 | }; | ||
196 | |||
197 | void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
198 | struct brcmf_fws_stats *stats) | ||
199 | { | ||
200 | struct dentry *dentry = drvr->dbgfs_dir; | ||
201 | |||
202 | if (!IS_ERR_OR_NULL(dentry)) | ||
203 | debugfs_create_file("fws_stats", S_IRUGO, dentry, | ||
204 | stats, &brcmf_debugfs_fws_stats_ops); | ||
205 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index bc013cbe06f6..009c87bfd9ae 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #define BRCMF_SCAN_VAL 0x00004000 | 34 | #define BRCMF_SCAN_VAL 0x00004000 |
35 | #define BRCMF_CONN_VAL 0x00008000 | 35 | #define BRCMF_CONN_VAL 0x00008000 |
36 | #define BRCMF_CDC_VAL 0x00010000 | 36 | #define BRCMF_CDC_VAL 0x00010000 |
37 | #define BRCMF_SDIO_VAL 0x00020000 | ||
37 | 38 | ||
38 | /* set default print format */ | 39 | /* set default print format */ |
39 | #undef pr_fmt | 40 | #undef pr_fmt |
@@ -43,6 +44,7 @@ | |||
43 | * debugging is not selected. When debugging the driver error | 44 | * debugging is not selected. When debugging the driver error |
44 | * messages are as important as other tracing or even more so. | 45 | * messages are as important as other tracing or even more so. |
45 | */ | 46 | */ |
47 | #ifndef CONFIG_BRCM_TRACING | ||
46 | #ifdef CONFIG_BRCMDBG | 48 | #ifdef CONFIG_BRCMDBG |
47 | #define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__) | 49 | #define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__) |
48 | #else | 50 | #else |
@@ -52,15 +54,21 @@ | |||
52 | pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \ | 54 | pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \ |
53 | } while (0) | 55 | } while (0) |
54 | #endif | 56 | #endif |
57 | #else | ||
58 | __printf(2, 3) | ||
59 | void __brcmf_err(const char *func, const char *fmt, ...); | ||
60 | #define brcmf_err(fmt, ...) \ | ||
61 | __brcmf_err(__func__, fmt, ##__VA_ARGS__) | ||
62 | #endif | ||
55 | 63 | ||
56 | #if defined(DEBUG) | 64 | #if defined(DEBUG) || defined(CONFIG_BRCM_TRACING) |
57 | 65 | __printf(3, 4) | |
66 | void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...); | ||
58 | #define brcmf_dbg(level, fmt, ...) \ | 67 | #define brcmf_dbg(level, fmt, ...) \ |
59 | do { \ | 68 | do { \ |
60 | if (brcmf_msg_level & BRCMF_##level##_VAL) \ | 69 | __brcmf_dbg(BRCMF_##level##_VAL, __func__, \ |
61 | pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ | 70 | fmt, ##__VA_ARGS__); \ |
62 | } while (0) | 71 | } while (0) |
63 | |||
64 | #define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) | 72 | #define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) |
65 | #define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) | 73 | #define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) |
66 | #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) | 74 | #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) |
@@ -69,7 +77,7 @@ do { \ | |||
69 | #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) | 77 | #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) |
70 | #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) | 78 | #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) |
71 | 79 | ||
72 | #else /* (defined DEBUG) || (defined DEBUG) */ | 80 | #else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ |
73 | 81 | ||
74 | #define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) | 82 | #define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) |
75 | 83 | ||
@@ -81,10 +89,11 @@ do { \ | |||
81 | #define BRCMF_EVENT_ON() 0 | 89 | #define BRCMF_EVENT_ON() 0 |
82 | #define BRCMF_FIL_ON() 0 | 90 | #define BRCMF_FIL_ON() 0 |
83 | 91 | ||
84 | #endif /* defined(DEBUG) */ | 92 | #endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ |
85 | 93 | ||
86 | #define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \ | 94 | #define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \ |
87 | do { \ | 95 | do { \ |
96 | trace_brcmf_hexdump((void *)data, len); \ | ||
88 | if (test) \ | 97 | if (test) \ |
89 | brcmu_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__); \ | 98 | brcmu_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__); \ |
90 | } while (0) | 99 | } while (0) |
@@ -125,6 +134,32 @@ struct brcmf_sdio_count { | |||
125 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ | 134 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ |
126 | }; | 135 | }; |
127 | 136 | ||
137 | struct brcmf_fws_stats { | ||
138 | u32 tlv_parse_failed; | ||
139 | u32 tlv_invalid_type; | ||
140 | u32 header_only_pkt; | ||
141 | u32 header_pulls; | ||
142 | u32 pkt2bus; | ||
143 | u32 send_pkts[5]; | ||
144 | u32 fifo_credits_sent[5]; | ||
145 | u32 fifo_credits_back[6]; | ||
146 | u32 generic_error; | ||
147 | u32 mac_update_failed; | ||
148 | u32 mac_ps_update_failed; | ||
149 | u32 if_update_failed; | ||
150 | u32 packet_request_failed; | ||
151 | u32 credit_request_failed; | ||
152 | u32 rollback_success; | ||
153 | u32 rollback_failed; | ||
154 | u32 delayq_full_error; | ||
155 | u32 supprq_full_error; | ||
156 | u32 txs_indicate; | ||
157 | u32 txs_discard; | ||
158 | u32 txs_supp_core; | ||
159 | u32 txs_supp_ps; | ||
160 | u32 txs_tossed; | ||
161 | }; | ||
162 | |||
128 | struct brcmf_pub; | 163 | struct brcmf_pub; |
129 | #ifdef DEBUG | 164 | #ifdef DEBUG |
130 | void brcmf_debugfs_init(void); | 165 | void brcmf_debugfs_init(void); |
@@ -134,6 +169,8 @@ void brcmf_debugfs_detach(struct brcmf_pub *drvr); | |||
134 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); | 169 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); |
135 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | 170 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, |
136 | struct brcmf_sdio_count *sdcnt); | 171 | struct brcmf_sdio_count *sdcnt); |
172 | void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
173 | struct brcmf_fws_stats *stats); | ||
137 | #else | 174 | #else |
138 | static inline void brcmf_debugfs_init(void) | 175 | static inline void brcmf_debugfs_init(void) |
139 | { | 176 | { |
@@ -148,6 +185,10 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) | |||
148 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) | 185 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) |
149 | { | 186 | { |
150 | } | 187 | } |
188 | static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
189 | struct brcmf_fws_stats *stats) | ||
190 | { | ||
191 | } | ||
151 | #endif | 192 | #endif |
152 | 193 | ||
153 | #endif /* _BRCMF_DBG_H_ */ | 194 | #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..763a84eba216 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; |
@@ -222,18 +223,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, | |||
222 | goto done; | 223 | goto done; |
223 | } | 224 | } |
224 | 225 | ||
225 | /* handle ethernet header */ | 226 | ret = brcmf_fws_process_skb(ifp, skb); |
226 | eh = (struct ethhdr *)(skb->data); | ||
227 | if (is_multicast_ether_addr(eh->h_dest)) | ||
228 | drvr->tx_multicast++; | ||
229 | if (ntohs(eh->h_proto) == ETH_P_PAE) | ||
230 | atomic_inc(&ifp->pend_8021x_cnt); | ||
231 | |||
232 | /* If the protocol uses a data header, apply it */ | ||
233 | brcmf_proto_hdrpush(drvr, ifp->ifidx, skb); | ||
234 | |||
235 | /* Use bus module to send data frame */ | ||
236 | ret = brcmf_bus_txdata(drvr->bus_if, skb); | ||
237 | 227 | ||
238 | done: | 228 | done: |
239 | if (ret) { | 229 | if (ret) { |
@@ -247,9 +237,27 @@ done: | |||
247 | return NETDEV_TX_OK; | 237 | return NETDEV_TX_OK; |
248 | } | 238 | } |
249 | 239 | ||
240 | void brcmf_txflowblock_if(struct brcmf_if *ifp, | ||
241 | enum brcmf_netif_stop_reason reason, bool state) | ||
242 | { | ||
243 | if (!ifp) | ||
244 | return; | ||
245 | |||
246 | brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n", | ||
247 | ifp->bssidx, ifp->netif_stop, reason, state); | ||
248 | if (state) { | ||
249 | if (!ifp->netif_stop) | ||
250 | netif_stop_queue(ifp->ndev); | ||
251 | ifp->netif_stop |= reason; | ||
252 | } else { | ||
253 | ifp->netif_stop &= ~reason; | ||
254 | if (!ifp->netif_stop) | ||
255 | netif_wake_queue(ifp->ndev); | ||
256 | } | ||
257 | } | ||
258 | |||
250 | void brcmf_txflowblock(struct device *dev, bool state) | 259 | void brcmf_txflowblock(struct device *dev, bool state) |
251 | { | 260 | { |
252 | struct net_device *ndev; | ||
253 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 261 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
254 | struct brcmf_pub *drvr = bus_if->drvr; | 262 | struct brcmf_pub *drvr = bus_if->drvr; |
255 | int i; | 263 | int i; |
@@ -257,13 +265,8 @@ void brcmf_txflowblock(struct device *dev, bool state) | |||
257 | brcmf_dbg(TRACE, "Enter\n"); | 265 | brcmf_dbg(TRACE, "Enter\n"); |
258 | 266 | ||
259 | for (i = 0; i < BRCMF_MAX_IFS; i++) | 267 | for (i = 0; i < BRCMF_MAX_IFS; i++) |
260 | if (drvr->iflist[i]) { | 268 | brcmf_txflowblock_if(drvr->iflist[i], |
261 | ndev = drvr->iflist[i]->ndev; | 269 | BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state); |
262 | if (state) | ||
263 | netif_stop_queue(ndev); | ||
264 | else | ||
265 | netif_wake_queue(ndev); | ||
266 | } | ||
267 | } | 270 | } |
268 | 271 | ||
269 | void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | 272 | void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) |
@@ -283,7 +286,7 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | |||
283 | skb_unlink(skb, skb_list); | 286 | skb_unlink(skb, skb_list); |
284 | 287 | ||
285 | /* process and remove protocol-specific header */ | 288 | /* process and remove protocol-specific header */ |
286 | ret = brcmf_proto_hdrpull(drvr, &ifidx, skb); | 289 | ret = brcmf_proto_hdrpull(drvr, drvr->fw_signals, &ifidx, skb); |
287 | ifp = drvr->iflist[ifidx]; | 290 | ifp = drvr->iflist[ifidx]; |
288 | 291 | ||
289 | if (ret || !ifp || !ifp->ndev) { | 292 | if (ret || !ifp || !ifp->ndev) { |
@@ -320,13 +323,8 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | |||
320 | /* Strip header, count, deliver upward */ | 323 | /* Strip header, count, deliver upward */ |
321 | skb_pull(skb, ETH_HLEN); | 324 | skb_pull(skb, ETH_HLEN); |
322 | 325 | ||
323 | /* Process special event packets and then discard them */ | 326 | /* Process special event packets */ |
324 | brcmf_fweh_process_skb(drvr, skb, &ifidx); | 327 | brcmf_fweh_process_skb(drvr, skb); |
325 | |||
326 | if (drvr->iflist[ifidx]) { | ||
327 | ifp = drvr->iflist[ifidx]; | ||
328 | ifp->ndev->last_rx = jiffies; | ||
329 | } | ||
330 | 328 | ||
331 | if (!(ifp->ndev->flags & IFF_UP)) { | 329 | if (!(ifp->ndev->flags & IFF_UP)) { |
332 | brcmu_pkt_buf_free_skb(skb); | 330 | brcmu_pkt_buf_free_skb(skb); |
@@ -349,31 +347,49 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | |||
349 | } | 347 | } |
350 | } | 348 | } |
351 | 349 | ||
352 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) | 350 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, |
351 | bool success) | ||
353 | { | 352 | { |
354 | u8 ifidx; | 353 | struct brcmf_if *ifp; |
355 | struct ethhdr *eh; | 354 | struct ethhdr *eh; |
355 | u8 ifidx; | ||
356 | u16 type; | 356 | u16 type; |
357 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 357 | int res; |
358 | struct brcmf_pub *drvr = bus_if->drvr; | ||
359 | struct brcmf_if *ifp; | ||
360 | 358 | ||
361 | brcmf_proto_hdrpull(drvr, &ifidx, txp); | 359 | res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp); |
362 | 360 | ||
363 | ifp = drvr->iflist[ifidx]; | 361 | ifp = drvr->iflist[ifidx]; |
364 | if (!ifp) | 362 | if (!ifp) |
365 | return; | 363 | goto done; |
366 | 364 | ||
367 | eh = (struct ethhdr *)(txp->data); | 365 | if (res == 0) { |
368 | type = ntohs(eh->h_proto); | 366 | eh = (struct ethhdr *)(txp->data); |
367 | type = ntohs(eh->h_proto); | ||
369 | 368 | ||
370 | if (type == ETH_P_PAE) { | 369 | if (type == ETH_P_PAE) { |
371 | atomic_dec(&ifp->pend_8021x_cnt); | 370 | atomic_dec(&ifp->pend_8021x_cnt); |
372 | if (waitqueue_active(&ifp->pend_8021x_wait)) | 371 | if (waitqueue_active(&ifp->pend_8021x_wait)) |
373 | wake_up(&ifp->pend_8021x_wait); | 372 | wake_up(&ifp->pend_8021x_wait); |
373 | } | ||
374 | } | 374 | } |
375 | if (!success) | 375 | if (!success) |
376 | ifp->stats.tx_errors++; | 376 | ifp->stats.tx_errors++; |
377 | done: | ||
378 | brcmu_pkt_buf_free_skb(txp); | ||
379 | } | ||
380 | |||
381 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) | ||
382 | { | ||
383 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
384 | struct brcmf_pub *drvr = bus_if->drvr; | ||
385 | |||
386 | /* await txstatus signal for firmware if active */ | ||
387 | if (brcmf_fws_fc_active(drvr->fws)) { | ||
388 | if (!success) | ||
389 | brcmf_fws_bustxfail(drvr->fws, txp); | ||
390 | } else { | ||
391 | brcmf_txfinalize(drvr, txp, success); | ||
392 | } | ||
377 | } | 393 | } |
378 | 394 | ||
379 | static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) | 395 | static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) |
@@ -734,28 +750,35 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, | |||
734 | } | 750 | } |
735 | } | 751 | } |
736 | 752 | ||
737 | /* Allocate netdev, including space for private structure */ | 753 | if (!brcmf_p2p_enable && bssidx == 1) { |
738 | ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup); | 754 | /* this is P2P_DEVICE interface */ |
739 | if (!ndev) { | 755 | brcmf_dbg(INFO, "allocate non-netdev interface\n"); |
740 | brcmf_err("OOM - alloc_netdev\n"); | 756 | ifp = kzalloc(sizeof(*ifp), GFP_KERNEL); |
741 | return ERR_PTR(-ENOMEM); | 757 | } else { |
758 | brcmf_dbg(INFO, "allocate netdev interface\n"); | ||
759 | /* Allocate netdev, including space for private structure */ | ||
760 | ndev = alloc_netdev(sizeof(*ifp), name, ether_setup); | ||
761 | if (!ndev) { | ||
762 | brcmf_err("OOM - alloc_netdev\n"); | ||
763 | return ERR_PTR(-ENOMEM); | ||
764 | } | ||
765 | |||
766 | ifp = netdev_priv(ndev); | ||
767 | ifp->ndev = ndev; | ||
742 | } | 768 | } |
743 | 769 | ||
744 | ifp = netdev_priv(ndev); | ||
745 | ifp->ndev = ndev; | ||
746 | ifp->drvr = drvr; | 770 | ifp->drvr = drvr; |
747 | drvr->iflist[bssidx] = ifp; | 771 | drvr->iflist[bssidx] = ifp; |
748 | ifp->ifidx = ifidx; | 772 | ifp->ifidx = ifidx; |
749 | ifp->bssidx = bssidx; | 773 | ifp->bssidx = bssidx; |
750 | 774 | ||
751 | |||
752 | init_waitqueue_head(&ifp->pend_8021x_wait); | 775 | init_waitqueue_head(&ifp->pend_8021x_wait); |
753 | 776 | ||
754 | if (mac_addr != NULL) | 777 | if (mac_addr != NULL) |
755 | memcpy(ifp->mac_addr, mac_addr, ETH_ALEN); | 778 | memcpy(ifp->mac_addr, mac_addr, ETH_ALEN); |
756 | 779 | ||
757 | brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n", | 780 | brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n", |
758 | current->pid, ifp->ndev->name, ifp->mac_addr); | 781 | current->pid, name, ifp->mac_addr); |
759 | 782 | ||
760 | return ifp; | 783 | return ifp; |
761 | } | 784 | } |
@@ -787,11 +810,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) | |||
787 | } | 810 | } |
788 | 811 | ||
789 | unregister_netdev(ifp->ndev); | 812 | unregister_netdev(ifp->ndev); |
790 | drvr->iflist[bssidx] = NULL; | ||
791 | if (bssidx == 0) | 813 | if (bssidx == 0) |
792 | brcmf_cfg80211_detach(drvr->config); | 814 | brcmf_cfg80211_detach(drvr->config); |
793 | free_netdev(ifp->ndev); | 815 | free_netdev(ifp->ndev); |
816 | } else { | ||
817 | kfree(ifp); | ||
794 | } | 818 | } |
819 | drvr->iflist[bssidx] = NULL; | ||
795 | } | 820 | } |
796 | 821 | ||
797 | int brcmf_attach(uint bus_hdrlen, struct device *dev) | 822 | int brcmf_attach(uint bus_hdrlen, struct device *dev) |
@@ -873,6 +898,10 @@ int brcmf_bus_start(struct device *dev) | |||
873 | if (ret < 0) | 898 | if (ret < 0) |
874 | goto fail; | 899 | goto fail; |
875 | 900 | ||
901 | drvr->fw_signals = true; | ||
902 | (void)brcmf_fws_init(drvr); | ||
903 | brcmf_fws_add_interface(ifp); | ||
904 | |||
876 | drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); | 905 | drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); |
877 | if (drvr->config == NULL) { | 906 | if (drvr->config == NULL) { |
878 | ret = -ENOMEM; | 907 | ret = -ENOMEM; |
@@ -889,6 +918,10 @@ fail: | |||
889 | brcmf_err("failed: %d\n", ret); | 918 | brcmf_err("failed: %d\n", ret); |
890 | if (drvr->config) | 919 | if (drvr->config) |
891 | brcmf_cfg80211_detach(drvr->config); | 920 | brcmf_cfg80211_detach(drvr->config); |
921 | if (drvr->fws) { | ||
922 | brcmf_fws_del_interface(ifp); | ||
923 | brcmf_fws_deinit(drvr); | ||
924 | } | ||
892 | free_netdev(ifp->ndev); | 925 | free_netdev(ifp->ndev); |
893 | drvr->iflist[0] = NULL; | 926 | drvr->iflist[0] = NULL; |
894 | if (p2p_ifp) { | 927 | if (p2p_ifp) { |
@@ -944,14 +977,18 @@ void brcmf_detach(struct device *dev) | |||
944 | 977 | ||
945 | /* make sure primary interface removed last */ | 978 | /* make sure primary interface removed last */ |
946 | for (i = BRCMF_MAX_IFS-1; i > -1; i--) | 979 | for (i = BRCMF_MAX_IFS-1; i > -1; i--) |
947 | if (drvr->iflist[i]) | 980 | if (drvr->iflist[i]) { |
981 | brcmf_fws_del_interface(drvr->iflist[i]); | ||
948 | brcmf_del_if(drvr, i); | 982 | brcmf_del_if(drvr, i); |
983 | } | ||
949 | 984 | ||
950 | brcmf_bus_detach(drvr); | 985 | brcmf_bus_detach(drvr); |
951 | 986 | ||
952 | if (drvr->prot) | 987 | if (drvr->prot) |
953 | brcmf_proto_detach(drvr); | 988 | brcmf_proto_detach(drvr); |
954 | 989 | ||
990 | brcmf_fws_deinit(drvr); | ||
991 | |||
955 | brcmf_debugfs_detach(drvr); | 992 | brcmf_debugfs_detach(drvr); |
956 | bus_if->drvr = NULL; | 993 | bus_if->drvr = NULL; |
957 | kfree(drvr); | 994 | 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..d2487518bd2a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/bcma/bcma.h> | 31 | #include <linux/bcma/bcma.h> |
32 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
33 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
34 | #include <linux/platform_data/brcmfmac-sdio.h> | ||
34 | #include <asm/unaligned.h> | 35 | #include <asm/unaligned.h> |
35 | #include <defs.h> | 36 | #include <defs.h> |
36 | #include <brcmu_wifi.h> | 37 | #include <brcmu_wifi.h> |
@@ -94,6 +95,7 @@ struct rte_console { | |||
94 | 95 | ||
95 | #include "dhd_bus.h" | 96 | #include "dhd_bus.h" |
96 | #include "dhd_dbg.h" | 97 | #include "dhd_dbg.h" |
98 | #include "tracepoint.h" | ||
97 | 99 | ||
98 | #define TXQLEN 2048 /* bulk tx queue length */ | 100 | #define TXQLEN 2048 /* bulk tx queue length */ |
99 | #define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */ | 101 | #define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */ |
@@ -323,6 +325,9 @@ MODULE_FIRMWARE(BRCMF_SDIO_NV_NAME); | |||
323 | */ | 325 | */ |
324 | #define BRCMF_IDLE_INTERVAL 1 | 326 | #define BRCMF_IDLE_INTERVAL 1 |
325 | 327 | ||
328 | #define KSO_WAIT_US 50 | ||
329 | #define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US) | ||
330 | |||
326 | /* | 331 | /* |
327 | * Conversion of 802.1D priority to precedence level | 332 | * Conversion of 802.1D priority to precedence level |
328 | */ | 333 | */ |
@@ -332,95 +337,6 @@ static uint prio2prec(u32 prio) | |||
332 | (prio^2) : prio; | 337 | (prio^2) : prio; |
333 | } | 338 | } |
334 | 339 | ||
335 | /* core registers */ | ||
336 | struct sdpcmd_regs { | ||
337 | u32 corecontrol; /* 0x00, rev8 */ | ||
338 | u32 corestatus; /* rev8 */ | ||
339 | u32 PAD[1]; | ||
340 | u32 biststatus; /* rev8 */ | ||
341 | |||
342 | /* PCMCIA access */ | ||
343 | u16 pcmciamesportaladdr; /* 0x010, rev8 */ | ||
344 | u16 PAD[1]; | ||
345 | u16 pcmciamesportalmask; /* rev8 */ | ||
346 | u16 PAD[1]; | ||
347 | u16 pcmciawrframebc; /* rev8 */ | ||
348 | u16 PAD[1]; | ||
349 | u16 pcmciaunderflowtimer; /* rev8 */ | ||
350 | u16 PAD[1]; | ||
351 | |||
352 | /* interrupt */ | ||
353 | u32 intstatus; /* 0x020, rev8 */ | ||
354 | u32 hostintmask; /* rev8 */ | ||
355 | u32 intmask; /* rev8 */ | ||
356 | u32 sbintstatus; /* rev8 */ | ||
357 | u32 sbintmask; /* rev8 */ | ||
358 | u32 funcintmask; /* rev4 */ | ||
359 | u32 PAD[2]; | ||
360 | u32 tosbmailbox; /* 0x040, rev8 */ | ||
361 | u32 tohostmailbox; /* rev8 */ | ||
362 | u32 tosbmailboxdata; /* rev8 */ | ||
363 | u32 tohostmailboxdata; /* rev8 */ | ||
364 | |||
365 | /* synchronized access to registers in SDIO clock domain */ | ||
366 | u32 sdioaccess; /* 0x050, rev8 */ | ||
367 | u32 PAD[3]; | ||
368 | |||
369 | /* PCMCIA frame control */ | ||
370 | u8 pcmciaframectrl; /* 0x060, rev8 */ | ||
371 | u8 PAD[3]; | ||
372 | u8 pcmciawatermark; /* rev8 */ | ||
373 | u8 PAD[155]; | ||
374 | |||
375 | /* interrupt batching control */ | ||
376 | u32 intrcvlazy; /* 0x100, rev8 */ | ||
377 | u32 PAD[3]; | ||
378 | |||
379 | /* counters */ | ||
380 | u32 cmd52rd; /* 0x110, rev8 */ | ||
381 | u32 cmd52wr; /* rev8 */ | ||
382 | u32 cmd53rd; /* rev8 */ | ||
383 | u32 cmd53wr; /* rev8 */ | ||
384 | u32 abort; /* rev8 */ | ||
385 | u32 datacrcerror; /* rev8 */ | ||
386 | u32 rdoutofsync; /* rev8 */ | ||
387 | u32 wroutofsync; /* rev8 */ | ||
388 | u32 writebusy; /* rev8 */ | ||
389 | u32 readwait; /* rev8 */ | ||
390 | u32 readterm; /* rev8 */ | ||
391 | u32 writeterm; /* rev8 */ | ||
392 | u32 PAD[40]; | ||
393 | u32 clockctlstatus; /* rev8 */ | ||
394 | u32 PAD[7]; | ||
395 | |||
396 | u32 PAD[128]; /* DMA engines */ | ||
397 | |||
398 | /* SDIO/PCMCIA CIS region */ | ||
399 | char cis[512]; /* 0x400-0x5ff, rev6 */ | ||
400 | |||
401 | /* PCMCIA function control registers */ | ||
402 | char pcmciafcr[256]; /* 0x600-6ff, rev6 */ | ||
403 | u16 PAD[55]; | ||
404 | |||
405 | /* PCMCIA backplane access */ | ||
406 | u16 backplanecsr; /* 0x76E, rev6 */ | ||
407 | u16 backplaneaddr0; /* rev6 */ | ||
408 | u16 backplaneaddr1; /* rev6 */ | ||
409 | u16 backplaneaddr2; /* rev6 */ | ||
410 | u16 backplaneaddr3; /* rev6 */ | ||
411 | u16 backplanedata0; /* rev6 */ | ||
412 | u16 backplanedata1; /* rev6 */ | ||
413 | u16 backplanedata2; /* rev6 */ | ||
414 | u16 backplanedata3; /* rev6 */ | ||
415 | u16 PAD[31]; | ||
416 | |||
417 | /* sprom "size" & "blank" info */ | ||
418 | u16 spromstatus; /* 0x7BE, rev2 */ | ||
419 | u32 PAD[464]; | ||
420 | |||
421 | u16 PAD[0x80]; | ||
422 | }; | ||
423 | |||
424 | #ifdef DEBUG | 340 | #ifdef DEBUG |
425 | /* Device console log buffer state */ | 341 | /* Device console log buffer state */ |
426 | struct brcmf_console { | 342 | struct brcmf_console { |
@@ -587,12 +503,14 @@ struct brcmf_sdio { | |||
587 | 503 | ||
588 | bool txoff; /* Transmit flow-controlled */ | 504 | bool txoff; /* Transmit flow-controlled */ |
589 | struct brcmf_sdio_count sdcnt; | 505 | struct brcmf_sdio_count sdcnt; |
506 | bool sr_enabled; /* SaveRestore enabled */ | ||
507 | bool sleeping; /* SDIO bus sleeping */ | ||
590 | }; | 508 | }; |
591 | 509 | ||
592 | /* clkstate */ | 510 | /* clkstate */ |
593 | #define CLK_NONE 0 | 511 | #define CLK_NONE 0 |
594 | #define CLK_SDONLY 1 | 512 | #define CLK_SDONLY 1 |
595 | #define CLK_PENDING 2 /* Not used yet */ | 513 | #define CLK_PENDING 2 |
596 | #define CLK_AVAIL 3 | 514 | #define CLK_AVAIL 3 |
597 | 515 | ||
598 | #ifdef DEBUG | 516 | #ifdef DEBUG |
@@ -600,7 +518,7 @@ static int qcount[NUMPRIO]; | |||
600 | static int tx_packets[NUMPRIO]; | 518 | static int tx_packets[NUMPRIO]; |
601 | #endif /* DEBUG */ | 519 | #endif /* DEBUG */ |
602 | 520 | ||
603 | #define SDIO_DRIVE_STRENGTH 6 /* in milliamps */ | 521 | #define DEFAULT_SDIO_DRIVE_STRENGTH 6 /* in milliamps */ |
604 | 522 | ||
605 | #define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) | 523 | #define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) |
606 | 524 | ||
@@ -664,6 +582,62 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset) | |||
664 | return ret; | 582 | return ret; |
665 | } | 583 | } |
666 | 584 | ||
585 | static int | ||
586 | brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on) | ||
587 | { | ||
588 | u8 wr_val = 0, rd_val, cmp_val, bmask; | ||
589 | int err = 0; | ||
590 | int try_cnt = 0; | ||
591 | |||
592 | brcmf_dbg(TRACE, "Enter\n"); | ||
593 | |||
594 | wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); | ||
595 | /* 1st KSO write goes to AOS wake up core if device is asleep */ | ||
596 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | ||
597 | wr_val, &err); | ||
598 | if (err) { | ||
599 | brcmf_err("SDIO_AOS KSO write error: %d\n", err); | ||
600 | return err; | ||
601 | } | ||
602 | |||
603 | if (on) { | ||
604 | /* device WAKEUP through KSO: | ||
605 | * write bit 0 & read back until | ||
606 | * both bits 0 (kso bit) & 1 (dev on status) are set | ||
607 | */ | ||
608 | cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK | | ||
609 | SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK; | ||
610 | bmask = cmp_val; | ||
611 | usleep_range(2000, 3000); | ||
612 | } else { | ||
613 | /* Put device to sleep, turn off KSO */ | ||
614 | cmp_val = 0; | ||
615 | /* only check for bit0, bit1(dev on status) may not | ||
616 | * get cleared right away | ||
617 | */ | ||
618 | bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK; | ||
619 | } | ||
620 | |||
621 | do { | ||
622 | /* reliable KSO bit set/clr: | ||
623 | * the sdiod sleep write access is synced to PMU 32khz clk | ||
624 | * just one write attempt may fail, | ||
625 | * read it back until it matches written value | ||
626 | */ | ||
627 | rd_val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | ||
628 | &err); | ||
629 | if (((rd_val & bmask) == cmp_val) && !err) | ||
630 | break; | ||
631 | brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n", | ||
632 | try_cnt, MAX_KSO_ATTEMPTS, err); | ||
633 | udelay(KSO_WAIT_US); | ||
634 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | ||
635 | wr_val, &err); | ||
636 | } while (try_cnt++ < MAX_KSO_ATTEMPTS); | ||
637 | |||
638 | return err; | ||
639 | } | ||
640 | |||
667 | #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) | 641 | #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) |
668 | 642 | ||
669 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) | 643 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) |
@@ -675,10 +649,15 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
675 | u8 clkctl, clkreq, devctl; | 649 | u8 clkctl, clkreq, devctl; |
676 | unsigned long timeout; | 650 | unsigned long timeout; |
677 | 651 | ||
678 | brcmf_dbg(TRACE, "Enter\n"); | 652 | brcmf_dbg(SDIO, "Enter\n"); |
679 | 653 | ||
680 | clkctl = 0; | 654 | clkctl = 0; |
681 | 655 | ||
656 | if (bus->sr_enabled) { | ||
657 | bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY); | ||
658 | return 0; | ||
659 | } | ||
660 | |||
682 | if (on) { | 661 | if (on) { |
683 | /* Request HT Avail */ | 662 | /* Request HT Avail */ |
684 | clkreq = | 663 | clkreq = |
@@ -713,7 +692,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
713 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; | 692 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; |
714 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, | 693 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
715 | devctl, &err); | 694 | devctl, &err); |
716 | brcmf_dbg(INFO, "CLKCTL: set PENDING\n"); | 695 | brcmf_dbg(SDIO, "CLKCTL: set PENDING\n"); |
717 | bus->clkstate = CLK_PENDING; | 696 | bus->clkstate = CLK_PENDING; |
718 | 697 | ||
719 | return 0; | 698 | return 0; |
@@ -750,7 +729,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
750 | 729 | ||
751 | /* Mark clock available */ | 730 | /* Mark clock available */ |
752 | bus->clkstate = CLK_AVAIL; | 731 | bus->clkstate = CLK_AVAIL; |
753 | brcmf_dbg(INFO, "CLKCTL: turned ON\n"); | 732 | brcmf_dbg(SDIO, "CLKCTL: turned ON\n"); |
754 | 733 | ||
755 | #if defined(DEBUG) | 734 | #if defined(DEBUG) |
756 | if (!bus->alp_only) { | 735 | if (!bus->alp_only) { |
@@ -775,7 +754,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
775 | bus->clkstate = CLK_SDONLY; | 754 | bus->clkstate = CLK_SDONLY; |
776 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | 755 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
777 | clkreq, &err); | 756 | clkreq, &err); |
778 | brcmf_dbg(INFO, "CLKCTL: turned OFF\n"); | 757 | brcmf_dbg(SDIO, "CLKCTL: turned OFF\n"); |
779 | if (err) { | 758 | if (err) { |
780 | brcmf_err("Failed access turning clock off: %d\n", | 759 | brcmf_err("Failed access turning clock off: %d\n", |
781 | err); | 760 | err); |
@@ -788,7 +767,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
788 | /* Change idle/active SD state */ | 767 | /* Change idle/active SD state */ |
789 | static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on) | 768 | static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on) |
790 | { | 769 | { |
791 | brcmf_dbg(TRACE, "Enter\n"); | 770 | brcmf_dbg(SDIO, "Enter\n"); |
792 | 771 | ||
793 | if (on) | 772 | if (on) |
794 | bus->clkstate = CLK_SDONLY; | 773 | bus->clkstate = CLK_SDONLY; |
@@ -805,7 +784,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
805 | uint oldstate = bus->clkstate; | 784 | uint oldstate = bus->clkstate; |
806 | #endif /* DEBUG */ | 785 | #endif /* DEBUG */ |
807 | 786 | ||
808 | brcmf_dbg(TRACE, "Enter\n"); | 787 | brcmf_dbg(SDIO, "Enter\n"); |
809 | 788 | ||
810 | /* Early exit if we're already there */ | 789 | /* Early exit if we're already there */ |
811 | if (bus->clkstate == target) { | 790 | if (bus->clkstate == target) { |
@@ -849,12 +828,69 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
849 | break; | 828 | break; |
850 | } | 829 | } |
851 | #ifdef DEBUG | 830 | #ifdef DEBUG |
852 | brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate); | 831 | brcmf_dbg(SDIO, "%d -> %d\n", oldstate, bus->clkstate); |
853 | #endif /* DEBUG */ | 832 | #endif /* DEBUG */ |
854 | 833 | ||
855 | return 0; | 834 | return 0; |
856 | } | 835 | } |
857 | 836 | ||
837 | static int | ||
838 | brcmf_sdbrcm_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | ||
839 | { | ||
840 | int err = 0; | ||
841 | brcmf_dbg(TRACE, "Enter\n"); | ||
842 | brcmf_dbg(SDIO, "request %s currently %s\n", | ||
843 | (sleep ? "SLEEP" : "WAKE"), | ||
844 | (bus->sleeping ? "SLEEP" : "WAKE")); | ||
845 | |||
846 | /* If SR is enabled control bus state with KSO */ | ||
847 | if (bus->sr_enabled) { | ||
848 | /* Done if we're already in the requested state */ | ||
849 | if (sleep == bus->sleeping) | ||
850 | goto end; | ||
851 | |||
852 | /* Going to sleep */ | ||
853 | if (sleep) { | ||
854 | /* Don't sleep if something is pending */ | ||
855 | if (atomic_read(&bus->intstatus) || | ||
856 | atomic_read(&bus->ipend) > 0 || | ||
857 | (!atomic_read(&bus->fcstate) && | ||
858 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && | ||
859 | data_ok(bus))) | ||
860 | return -EBUSY; | ||
861 | err = brcmf_sdbrcm_kso_control(bus, false); | ||
862 | /* disable watchdog */ | ||
863 | if (!err) | ||
864 | brcmf_sdbrcm_wd_timer(bus, 0); | ||
865 | } else { | ||
866 | bus->idlecount = 0; | ||
867 | err = brcmf_sdbrcm_kso_control(bus, true); | ||
868 | } | ||
869 | if (!err) { | ||
870 | /* Change state */ | ||
871 | bus->sleeping = sleep; | ||
872 | brcmf_dbg(SDIO, "new state %s\n", | ||
873 | (sleep ? "SLEEP" : "WAKE")); | ||
874 | } else { | ||
875 | brcmf_err("error while changing bus sleep state %d\n", | ||
876 | err); | ||
877 | return err; | ||
878 | } | ||
879 | } | ||
880 | |||
881 | end: | ||
882 | /* control clocks */ | ||
883 | if (sleep) { | ||
884 | if (!bus->sr_enabled) | ||
885 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, pendok); | ||
886 | } else { | ||
887 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, pendok); | ||
888 | } | ||
889 | |||
890 | return err; | ||
891 | |||
892 | } | ||
893 | |||
858 | static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | 894 | static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) |
859 | { | 895 | { |
860 | u32 intstatus = 0; | 896 | u32 intstatus = 0; |
@@ -862,7 +898,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
862 | u8 fcbits; | 898 | u8 fcbits; |
863 | int ret; | 899 | int ret; |
864 | 900 | ||
865 | brcmf_dbg(TRACE, "Enter\n"); | 901 | brcmf_dbg(SDIO, "Enter\n"); |
866 | 902 | ||
867 | /* Read mailbox data and ack that we did so */ | 903 | /* Read mailbox data and ack that we did so */ |
868 | ret = r_sdreg32(bus, &hmb_data, | 904 | ret = r_sdreg32(bus, &hmb_data, |
@@ -875,7 +911,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
875 | 911 | ||
876 | /* Dongle recomposed rx frames, accept them again */ | 912 | /* Dongle recomposed rx frames, accept them again */ |
877 | if (hmb_data & HMB_DATA_NAKHANDLED) { | 913 | if (hmb_data & HMB_DATA_NAKHANDLED) { |
878 | brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n", | 914 | brcmf_dbg(SDIO, "Dongle reports NAK handled, expect rtx of %d\n", |
879 | bus->rx_seq); | 915 | bus->rx_seq); |
880 | if (!bus->rxskip) | 916 | if (!bus->rxskip) |
881 | brcmf_err("unexpected NAKHANDLED!\n"); | 917 | brcmf_err("unexpected NAKHANDLED!\n"); |
@@ -896,7 +932,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
896 | "expecting %d\n", | 932 | "expecting %d\n", |
897 | bus->sdpcm_ver, SDPCM_PROT_VERSION); | 933 | bus->sdpcm_ver, SDPCM_PROT_VERSION); |
898 | else | 934 | else |
899 | brcmf_dbg(INFO, "Dongle ready, protocol version %d\n", | 935 | brcmf_dbg(SDIO, "Dongle ready, protocol version %d\n", |
900 | bus->sdpcm_ver); | 936 | bus->sdpcm_ver); |
901 | } | 937 | } |
902 | 938 | ||
@@ -970,7 +1006,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
970 | if (!retries) | 1006 | if (!retries) |
971 | brcmf_err("count never zeroed: last 0x%04x\n", lastrbc); | 1007 | brcmf_err("count never zeroed: last 0x%04x\n", lastrbc); |
972 | else | 1008 | else |
973 | brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries); | 1009 | brcmf_dbg(SDIO, "flush took %d iterations\n", 0xffff - retries); |
974 | 1010 | ||
975 | if (rtx) { | 1011 | if (rtx) { |
976 | bus->sdcnt.rxrtx++; | 1012 | bus->sdcnt.rxrtx++; |
@@ -1173,7 +1209,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1173 | /* If packets, issue read(s) and send up packet chain */ | 1209 | /* If packets, issue read(s) and send up packet chain */ |
1174 | /* Return sequence numbers consumed? */ | 1210 | /* Return sequence numbers consumed? */ |
1175 | 1211 | ||
1176 | brcmf_dbg(TRACE, "start: glomd %p glom %p\n", | 1212 | brcmf_dbg(SDIO, "start: glomd %p glom %p\n", |
1177 | bus->glomd, skb_peek(&bus->glom)); | 1213 | bus->glomd, skb_peek(&bus->glom)); |
1178 | 1214 | ||
1179 | /* If there's a descriptor, generate the packet chain */ | 1215 | /* If there's a descriptor, generate the packet chain */ |
@@ -1546,7 +1582,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1546 | struct sk_buff_head pktlist; /* needed for bus interface */ | 1582 | struct sk_buff_head pktlist; /* needed for bus interface */ |
1547 | u16 pad; /* Number of pad bytes to read */ | 1583 | u16 pad; /* Number of pad bytes to read */ |
1548 | uint rxleft = 0; /* Remaining number of frames allowed */ | 1584 | uint rxleft = 0; /* Remaining number of frames allowed */ |
1549 | int sdret; /* Return code from calls */ | 1585 | int ret; /* Return code from calls */ |
1550 | uint rxcount = 0; /* Total frames read */ | 1586 | uint rxcount = 0; /* Total frames read */ |
1551 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; | 1587 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; |
1552 | u8 head_read = 0; | 1588 | u8 head_read = 0; |
@@ -1577,15 +1613,15 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1577 | /* read header first for unknow frame length */ | 1613 | /* read header first for unknow frame length */ |
1578 | sdio_claim_host(bus->sdiodev->func[1]); | 1614 | sdio_claim_host(bus->sdiodev->func[1]); |
1579 | if (!rd->len) { | 1615 | if (!rd->len) { |
1580 | sdret = brcmf_sdcard_recv_buf(bus->sdiodev, | 1616 | ret = brcmf_sdcard_recv_buf(bus->sdiodev, |
1581 | bus->sdiodev->sbwad, | 1617 | bus->sdiodev->sbwad, |
1582 | SDIO_FUNC_2, F2SYNC, | 1618 | SDIO_FUNC_2, F2SYNC, |
1583 | bus->rxhdr, | 1619 | bus->rxhdr, |
1584 | BRCMF_FIRSTREAD); | 1620 | BRCMF_FIRSTREAD); |
1585 | bus->sdcnt.f2rxhdrs++; | 1621 | bus->sdcnt.f2rxhdrs++; |
1586 | if (sdret < 0) { | 1622 | if (ret < 0) { |
1587 | brcmf_err("RXHEADER FAILED: %d\n", | 1623 | brcmf_err("RXHEADER FAILED: %d\n", |
1588 | sdret); | 1624 | ret); |
1589 | bus->sdcnt.rx_hdrfail++; | 1625 | bus->sdcnt.rx_hdrfail++; |
1590 | brcmf_sdbrcm_rxfail(bus, true, true); | 1626 | brcmf_sdbrcm_rxfail(bus, true, true); |
1591 | sdio_release_host(bus->sdiodev->func[1]); | 1627 | sdio_release_host(bus->sdiodev->func[1]); |
@@ -1637,14 +1673,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1637 | skb_pull(pkt, head_read); | 1673 | skb_pull(pkt, head_read); |
1638 | pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); | 1674 | pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); |
1639 | 1675 | ||
1640 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 1676 | ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, |
1641 | SDIO_FUNC_2, F2SYNC, pkt); | 1677 | SDIO_FUNC_2, F2SYNC, pkt); |
1642 | bus->sdcnt.f2rxdata++; | 1678 | bus->sdcnt.f2rxdata++; |
1643 | sdio_release_host(bus->sdiodev->func[1]); | 1679 | sdio_release_host(bus->sdiodev->func[1]); |
1644 | 1680 | ||
1645 | if (sdret < 0) { | 1681 | if (ret < 0) { |
1646 | brcmf_err("read %d bytes from channel %d failed: %d\n", | 1682 | brcmf_err("read %d bytes from channel %d failed: %d\n", |
1647 | rd->len, rd->channel, sdret); | 1683 | rd->len, rd->channel, ret); |
1648 | brcmu_pkt_buf_free_skb(pkt); | 1684 | brcmu_pkt_buf_free_skb(pkt); |
1649 | sdio_claim_host(bus->sdiodev->func[1]); | 1685 | sdio_claim_host(bus->sdiodev->func[1]); |
1650 | brcmf_sdbrcm_rxfail(bus, true, | 1686 | brcmf_sdbrcm_rxfail(bus, true, |
@@ -1775,13 +1811,12 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) | |||
1775 | /* Writes a HW/SW header into the packet and sends it. */ | 1811 | /* Writes a HW/SW header into the packet and sends it. */ |
1776 | /* Assumes: (a) header space already there, (b) caller holds lock */ | 1812 | /* Assumes: (a) header space already there, (b) caller holds lock */ |
1777 | static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | 1813 | static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, |
1778 | uint chan, bool free_pkt) | 1814 | uint chan) |
1779 | { | 1815 | { |
1780 | int ret; | 1816 | int ret; |
1781 | u8 *frame; | 1817 | u8 *frame; |
1782 | u16 len, pad = 0; | 1818 | u16 len, pad = 0; |
1783 | u32 swheader; | 1819 | u32 swheader; |
1784 | struct sk_buff *new; | ||
1785 | int i; | 1820 | int i; |
1786 | 1821 | ||
1787 | brcmf_dbg(TRACE, "Enter\n"); | 1822 | brcmf_dbg(TRACE, "Enter\n"); |
@@ -1795,30 +1830,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
1795 | brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n", | 1830 | brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n", |
1796 | skb_headroom(pkt), pad); | 1831 | skb_headroom(pkt), pad); |
1797 | bus->sdiodev->bus_if->tx_realloc++; | 1832 | bus->sdiodev->bus_if->tx_realloc++; |
1798 | new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN); | 1833 | ret = skb_cow(pkt, BRCMF_SDALIGN); |
1799 | if (!new) { | 1834 | if (ret) |
1800 | brcmf_err("couldn't allocate new %d-byte packet\n", | ||
1801 | pkt->len + BRCMF_SDALIGN); | ||
1802 | ret = -ENOMEM; | ||
1803 | goto done; | 1835 | goto done; |
1804 | } | 1836 | pad = ((unsigned long)frame % BRCMF_SDALIGN); |
1805 | |||
1806 | pkt_align(new, pkt->len, BRCMF_SDALIGN); | ||
1807 | memcpy(new->data, pkt->data, pkt->len); | ||
1808 | if (free_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; | ||
1813 | frame = (u8 *) (pkt->data); | ||
1814 | /* precondition: (frame % BRCMF_SDALIGN) == 0) */ | ||
1815 | pad = 0; | ||
1816 | } else { | ||
1817 | skb_push(pkt, pad); | ||
1818 | frame = (u8 *) (pkt->data); | ||
1819 | /* precondition: pad + SDPCM_HDRLEN <= pkt->len */ | ||
1820 | memset(frame, 0, pad + SDPCM_HDRLEN); | ||
1821 | } | 1837 | } |
1838 | skb_push(pkt, pad); | ||
1839 | frame = (u8 *) (pkt->data); | ||
1840 | memset(frame, 0, pad + SDPCM_HDRLEN); | ||
1822 | } | 1841 | } |
1823 | /* precondition: pad < BRCMF_SDALIGN */ | 1842 | /* precondition: pad < BRCMF_SDALIGN */ |
1824 | 1843 | ||
@@ -1833,8 +1852,8 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
1833 | (((pad + | 1852 | (((pad + |
1834 | SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); | 1853 | SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); |
1835 | 1854 | ||
1836 | put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); | 1855 | *(((__le32 *) frame) + 1) = cpu_to_le32(swheader); |
1837 | put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); | 1856 | *(((__le32 *) frame) + 2) = 0; |
1838 | 1857 | ||
1839 | #ifdef DEBUG | 1858 | #ifdef DEBUG |
1840 | tx_packets[pkt->priority]++; | 1859 | tx_packets[pkt->priority]++; |
@@ -1900,11 +1919,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
1900 | done: | 1919 | done: |
1901 | /* restore pkt buffer pointer before calling tx complete routine */ | 1920 | /* restore pkt buffer pointer before calling tx complete routine */ |
1902 | skb_pull(pkt, SDPCM_HDRLEN + pad); | 1921 | skb_pull(pkt, SDPCM_HDRLEN + pad); |
1903 | brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0); | 1922 | brcmf_txcomplete(bus->sdiodev->dev, pkt, ret == 0); |
1904 | |||
1905 | if (free_pkt) | ||
1906 | brcmu_pkt_buf_free_skb(pkt); | ||
1907 | |||
1908 | return ret; | 1923 | return ret; |
1909 | } | 1924 | } |
1910 | 1925 | ||
@@ -1932,7 +1947,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
1932 | spin_unlock_bh(&bus->txqlock); | 1947 | spin_unlock_bh(&bus->txqlock); |
1933 | datalen = pkt->len - SDPCM_HDRLEN; | 1948 | datalen = pkt->len - SDPCM_HDRLEN; |
1934 | 1949 | ||
1935 | ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); | 1950 | ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL); |
1936 | 1951 | ||
1937 | /* In poll mode, need to check for other events */ | 1952 | /* In poll mode, need to check for other events */ |
1938 | if (!bus->intr && cnt) { | 1953 | if (!bus->intr && cnt) { |
@@ -1980,7 +1995,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
1980 | sdio_claim_host(bus->sdiodev->func[1]); | 1995 | sdio_claim_host(bus->sdiodev->func[1]); |
1981 | 1996 | ||
1982 | /* Enable clock for device interrupts */ | 1997 | /* Enable clock for device interrupts */ |
1983 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 1998 | brcmf_sdbrcm_bus_sleep(bus, false, false); |
1984 | 1999 | ||
1985 | /* Disable and clear interrupts at the chip level also */ | 2000 | /* Disable and clear interrupts at the chip level also */ |
1986 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); | 2001 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); |
@@ -2032,23 +2047,19 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
2032 | bus->tx_seq = bus->rx_seq = 0; | 2047 | bus->tx_seq = bus->rx_seq = 0; |
2033 | } | 2048 | } |
2034 | 2049 | ||
2035 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | ||
2036 | static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | 2050 | static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) |
2037 | { | 2051 | { |
2038 | unsigned long flags; | 2052 | unsigned long flags; |
2039 | 2053 | ||
2040 | spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); | 2054 | if (bus->sdiodev->oob_irq_requested) { |
2041 | if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) { | 2055 | spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); |
2042 | enable_irq(bus->sdiodev->irq); | 2056 | if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) { |
2043 | bus->sdiodev->irq_en = true; | 2057 | enable_irq(bus->sdiodev->pdata->oob_irq_nr); |
2058 | bus->sdiodev->irq_en = true; | ||
2059 | } | ||
2060 | spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags); | ||
2044 | } | 2061 | } |
2045 | spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags); | ||
2046 | } | ||
2047 | #else | ||
2048 | static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | ||
2049 | { | ||
2050 | } | 2062 | } |
2051 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
2052 | 2063 | ||
2053 | static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) | 2064 | static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) |
2054 | { | 2065 | { |
@@ -2116,7 +2127,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2116 | sdio_claim_host(bus->sdiodev->func[1]); | 2127 | sdio_claim_host(bus->sdiodev->func[1]); |
2117 | 2128 | ||
2118 | /* If waiting for HTAVAIL, check status */ | 2129 | /* If waiting for HTAVAIL, check status */ |
2119 | if (bus->clkstate == CLK_PENDING) { | 2130 | if (!bus->sr_enabled && bus->clkstate == CLK_PENDING) { |
2120 | u8 clkctl, devctl = 0; | 2131 | u8 clkctl, devctl = 0; |
2121 | 2132 | ||
2122 | #ifdef DEBUG | 2133 | #ifdef DEBUG |
@@ -2138,7 +2149,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2138 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2149 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2139 | } | 2150 | } |
2140 | 2151 | ||
2141 | brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", | 2152 | brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", |
2142 | devctl, clkctl); | 2153 | devctl, clkctl); |
2143 | 2154 | ||
2144 | if (SBSDIO_HTAV(clkctl)) { | 2155 | if (SBSDIO_HTAV(clkctl)) { |
@@ -2162,7 +2173,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2162 | } | 2173 | } |
2163 | 2174 | ||
2164 | /* Make sure backplane clock is on */ | 2175 | /* Make sure backplane clock is on */ |
2165 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); | 2176 | brcmf_sdbrcm_bus_sleep(bus, false, true); |
2166 | 2177 | ||
2167 | /* Pending interrupt indicates new device status */ | 2178 | /* Pending interrupt indicates new device status */ |
2168 | if (atomic_read(&bus->ipend) > 0) { | 2179 | if (atomic_read(&bus->ipend) > 0) { |
@@ -2308,12 +2319,22 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2308 | if ((bus->clkstate != CLK_PENDING) | 2319 | if ((bus->clkstate != CLK_PENDING) |
2309 | && bus->idletime == BRCMF_IDLE_IMMEDIATE) { | 2320 | && bus->idletime == BRCMF_IDLE_IMMEDIATE) { |
2310 | bus->activity = false; | 2321 | bus->activity = false; |
2322 | brcmf_dbg(SDIO, "idle state\n"); | ||
2311 | sdio_claim_host(bus->sdiodev->func[1]); | 2323 | sdio_claim_host(bus->sdiodev->func[1]); |
2312 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); | 2324 | brcmf_sdbrcm_bus_sleep(bus, true, false); |
2313 | sdio_release_host(bus->sdiodev->func[1]); | 2325 | sdio_release_host(bus->sdiodev->func[1]); |
2314 | } | 2326 | } |
2315 | } | 2327 | } |
2316 | 2328 | ||
2329 | static struct pktq *brcmf_sdbrcm_bus_gettxq(struct device *dev) | ||
2330 | { | ||
2331 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
2332 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
2333 | struct brcmf_sdio *bus = sdiodev->bus; | ||
2334 | |||
2335 | return &bus->txq; | ||
2336 | } | ||
2337 | |||
2317 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | 2338 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) |
2318 | { | 2339 | { |
2319 | int ret = -EBADE; | 2340 | int ret = -EBADE; |
@@ -2343,7 +2364,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)) { | 2364 | if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { |
2344 | skb_pull(pkt, SDPCM_HDRLEN); | 2365 | skb_pull(pkt, SDPCM_HDRLEN); |
2345 | brcmf_txcomplete(bus->sdiodev->dev, pkt, false); | 2366 | brcmf_txcomplete(bus->sdiodev->dev, pkt, false); |
2346 | brcmu_pkt_buf_free_skb(pkt); | ||
2347 | brcmf_err("out of bus->txq !!!\n"); | 2367 | brcmf_err("out of bus->txq !!!\n"); |
2348 | ret = -ENOSR; | 2368 | ret = -ENOSR; |
2349 | } else { | 2369 | } else { |
@@ -2374,69 +2394,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2374 | return ret; | 2394 | return ret; |
2375 | } | 2395 | } |
2376 | 2396 | ||
2377 | static int | ||
2378 | brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data, | ||
2379 | uint size) | ||
2380 | { | ||
2381 | int bcmerror = 0; | ||
2382 | u32 sdaddr; | ||
2383 | uint dsize; | ||
2384 | |||
2385 | /* Determine initial transfer parameters */ | ||
2386 | sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; | ||
2387 | if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK) | ||
2388 | dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr); | ||
2389 | else | ||
2390 | dsize = size; | ||
2391 | |||
2392 | sdio_claim_host(bus->sdiodev->func[1]); | ||
2393 | |||
2394 | /* Set the backplane window to include the start address */ | ||
2395 | bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); | ||
2396 | if (bcmerror) { | ||
2397 | brcmf_err("window change failed\n"); | ||
2398 | goto xfer_done; | ||
2399 | } | ||
2400 | |||
2401 | /* Do the transfer(s) */ | ||
2402 | while (size) { | ||
2403 | brcmf_dbg(INFO, "%s %d bytes at offset 0x%08x in window 0x%08x\n", | ||
2404 | write ? "write" : "read", dsize, | ||
2405 | sdaddr, address & SBSDIO_SBWINDOW_MASK); | ||
2406 | bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write, | ||
2407 | sdaddr, data, dsize); | ||
2408 | if (bcmerror) { | ||
2409 | brcmf_err("membytes transfer failed\n"); | ||
2410 | break; | ||
2411 | } | ||
2412 | |||
2413 | /* Adjust for next transfer (if any) */ | ||
2414 | size -= dsize; | ||
2415 | if (size) { | ||
2416 | data += dsize; | ||
2417 | address += dsize; | ||
2418 | bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, | ||
2419 | address); | ||
2420 | if (bcmerror) { | ||
2421 | brcmf_err("window change failed\n"); | ||
2422 | break; | ||
2423 | } | ||
2424 | sdaddr = 0; | ||
2425 | dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); | ||
2426 | } | ||
2427 | } | ||
2428 | |||
2429 | xfer_done: | ||
2430 | /* Return the window to backplane enumeration space for core access */ | ||
2431 | if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, bus->sdiodev->sbwad)) | ||
2432 | brcmf_err("FAILED to set window back to 0x%x\n", | ||
2433 | bus->sdiodev->sbwad); | ||
2434 | |||
2435 | sdio_release_host(bus->sdiodev->func[1]); | ||
2436 | |||
2437 | return bcmerror; | ||
2438 | } | ||
2439 | |||
2440 | #ifdef DEBUG | 2397 | #ifdef DEBUG |
2441 | #define CONSOLE_LINE_MAX 192 | 2398 | #define CONSOLE_LINE_MAX 192 |
2442 | 2399 | ||
@@ -2453,8 +2410,8 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus) | |||
2453 | 2410 | ||
2454 | /* Read console log struct */ | 2411 | /* Read console log struct */ |
2455 | addr = bus->console_addr + offsetof(struct rte_console, log_le); | 2412 | addr = bus->console_addr + offsetof(struct rte_console, log_le); |
2456 | rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log_le, | 2413 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&c->log_le, |
2457 | sizeof(c->log_le)); | 2414 | sizeof(c->log_le)); |
2458 | if (rv < 0) | 2415 | if (rv < 0) |
2459 | return rv; | 2416 | return rv; |
2460 | 2417 | ||
@@ -2479,7 +2436,7 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus) | |||
2479 | 2436 | ||
2480 | /* Read the console buffer */ | 2437 | /* Read the console buffer */ |
2481 | addr = le32_to_cpu(c->log_le.buf); | 2438 | addr = le32_to_cpu(c->log_le.buf); |
2482 | rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize); | 2439 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, c->buf, c->bufsize); |
2483 | if (rv < 0) | 2440 | if (rv < 0) |
2484 | return rv; | 2441 | return rv; |
2485 | 2442 | ||
@@ -2604,7 +2561,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2604 | 2561 | ||
2605 | /* Make sure backplane clock is on */ | 2562 | /* Make sure backplane clock is on */ |
2606 | sdio_claim_host(bus->sdiodev->func[1]); | 2563 | sdio_claim_host(bus->sdiodev->func[1]); |
2607 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2564 | brcmf_sdbrcm_bus_sleep(bus, false, false); |
2608 | sdio_release_host(bus->sdiodev->func[1]); | 2565 | sdio_release_host(bus->sdiodev->func[1]); |
2609 | 2566 | ||
2610 | /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ | 2567 | /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ |
@@ -2633,10 +2590,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2633 | msecs_to_jiffies(2000)); | 2590 | msecs_to_jiffies(2000)); |
2634 | 2591 | ||
2635 | if (!bus->ctrl_frame_stat) { | 2592 | if (!bus->ctrl_frame_stat) { |
2636 | brcmf_dbg(INFO, "ctrl_frame_stat == false\n"); | 2593 | brcmf_dbg(SDIO, "ctrl_frame_stat == false\n"); |
2637 | ret = 0; | 2594 | ret = 0; |
2638 | } else { | 2595 | } else { |
2639 | brcmf_dbg(INFO, "ctrl_frame_stat == true\n"); | 2596 | brcmf_dbg(SDIO, "ctrl_frame_stat == true\n"); |
2640 | ret = -1; | 2597 | ret = -1; |
2641 | } | 2598 | } |
2642 | } | 2599 | } |
@@ -2662,6 +2619,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2662 | 2619 | ||
2663 | bus->activity = false; | 2620 | bus->activity = false; |
2664 | sdio_claim_host(bus->sdiodev->func[1]); | 2621 | sdio_claim_host(bus->sdiodev->func[1]); |
2622 | brcmf_dbg(INFO, "idle\n"); | ||
2665 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); | 2623 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); |
2666 | sdio_release_host(bus->sdiodev->func[1]); | 2624 | sdio_release_host(bus->sdiodev->func[1]); |
2667 | } else { | 2625 | } else { |
@@ -2691,23 +2649,22 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | |||
2691 | struct sdpcm_shared_le sh_le; | 2649 | struct sdpcm_shared_le sh_le; |
2692 | __le32 addr_le; | 2650 | __le32 addr_le; |
2693 | 2651 | ||
2694 | shaddr = bus->ramsize - 4; | 2652 | shaddr = bus->ci->rambase + bus->ramsize - 4; |
2695 | 2653 | ||
2696 | /* | 2654 | /* |
2697 | * Read last word in socram to determine | 2655 | * Read last word in socram to determine |
2698 | * address of sdpcm_shared structure | 2656 | * address of sdpcm_shared structure |
2699 | */ | 2657 | */ |
2700 | sdio_claim_host(bus->sdiodev->func[1]); | 2658 | sdio_claim_host(bus->sdiodev->func[1]); |
2701 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2659 | brcmf_sdbrcm_bus_sleep(bus, false, false); |
2702 | rv = brcmf_sdbrcm_membytes(bus, false, shaddr, | 2660 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4); |
2703 | (u8 *)&addr_le, 4); | ||
2704 | sdio_release_host(bus->sdiodev->func[1]); | 2661 | sdio_release_host(bus->sdiodev->func[1]); |
2705 | if (rv < 0) | 2662 | if (rv < 0) |
2706 | return rv; | 2663 | return rv; |
2707 | 2664 | ||
2708 | addr = le32_to_cpu(addr_le); | 2665 | addr = le32_to_cpu(addr_le); |
2709 | 2666 | ||
2710 | brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr); | 2667 | brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr); |
2711 | 2668 | ||
2712 | /* | 2669 | /* |
2713 | * Check if addr is valid. | 2670 | * Check if addr is valid. |
@@ -2720,8 +2677,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | |||
2720 | } | 2677 | } |
2721 | 2678 | ||
2722 | /* Read hndrte_shared structure */ | 2679 | /* Read hndrte_shared structure */ |
2723 | rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le, | 2680 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le, |
2724 | sizeof(struct sdpcm_shared_le)); | 2681 | sizeof(struct sdpcm_shared_le)); |
2725 | if (rv < 0) | 2682 | if (rv < 0) |
2726 | return rv; | 2683 | return rv; |
2727 | 2684 | ||
@@ -2734,8 +2691,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | |||
2734 | sh->console_addr = le32_to_cpu(sh_le.console_addr); | 2691 | sh->console_addr = le32_to_cpu(sh_le.console_addr); |
2735 | sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr); | 2692 | sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr); |
2736 | 2693 | ||
2737 | if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) { | 2694 | if ((sh->flags & SDPCM_SHARED_VERSION_MASK) > SDPCM_SHARED_VERSION) { |
2738 | brcmf_err("sdpcm_shared version mismatch: dhd %d dongle %d\n", | 2695 | brcmf_err("sdpcm shared version unsupported: dhd %d dongle %d\n", |
2739 | SDPCM_SHARED_VERSION, | 2696 | SDPCM_SHARED_VERSION, |
2740 | sh->flags & SDPCM_SHARED_VERSION_MASK); | 2697 | sh->flags & SDPCM_SHARED_VERSION_MASK); |
2741 | return -EPROTO; | 2698 | return -EPROTO; |
@@ -2757,22 +2714,22 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, | |||
2757 | 2714 | ||
2758 | /* obtain console information from device memory */ | 2715 | /* obtain console information from device memory */ |
2759 | addr = sh->console_addr + offsetof(struct rte_console, log_le); | 2716 | addr = sh->console_addr + offsetof(struct rte_console, log_le); |
2760 | rv = brcmf_sdbrcm_membytes(bus, false, addr, | 2717 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, |
2761 | (u8 *)&sh_val, sizeof(u32)); | 2718 | (u8 *)&sh_val, sizeof(u32)); |
2762 | if (rv < 0) | 2719 | if (rv < 0) |
2763 | return rv; | 2720 | return rv; |
2764 | console_ptr = le32_to_cpu(sh_val); | 2721 | console_ptr = le32_to_cpu(sh_val); |
2765 | 2722 | ||
2766 | addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size); | 2723 | addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size); |
2767 | rv = brcmf_sdbrcm_membytes(bus, false, addr, | 2724 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, |
2768 | (u8 *)&sh_val, sizeof(u32)); | 2725 | (u8 *)&sh_val, sizeof(u32)); |
2769 | if (rv < 0) | 2726 | if (rv < 0) |
2770 | return rv; | 2727 | return rv; |
2771 | console_size = le32_to_cpu(sh_val); | 2728 | console_size = le32_to_cpu(sh_val); |
2772 | 2729 | ||
2773 | addr = sh->console_addr + offsetof(struct rte_console, log_le.idx); | 2730 | addr = sh->console_addr + offsetof(struct rte_console, log_le.idx); |
2774 | rv = brcmf_sdbrcm_membytes(bus, false, addr, | 2731 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, |
2775 | (u8 *)&sh_val, sizeof(u32)); | 2732 | (u8 *)&sh_val, sizeof(u32)); |
2776 | if (rv < 0) | 2733 | if (rv < 0) |
2777 | return rv; | 2734 | return rv; |
2778 | console_index = le32_to_cpu(sh_val); | 2735 | console_index = le32_to_cpu(sh_val); |
@@ -2786,8 +2743,8 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, | |||
2786 | 2743 | ||
2787 | /* obtain the console data from device */ | 2744 | /* obtain the console data from device */ |
2788 | conbuf[console_size] = '\0'; | 2745 | conbuf[console_size] = '\0'; |
2789 | rv = brcmf_sdbrcm_membytes(bus, false, console_ptr, (u8 *)conbuf, | 2746 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, console_ptr, (u8 *)conbuf, |
2790 | console_size); | 2747 | console_size); |
2791 | if (rv < 0) | 2748 | if (rv < 0) |
2792 | goto done; | 2749 | goto done; |
2793 | 2750 | ||
@@ -2817,21 +2774,18 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, | |||
2817 | int error, res; | 2774 | int error, res; |
2818 | char buf[350]; | 2775 | char buf[350]; |
2819 | struct brcmf_trap_info tr; | 2776 | struct brcmf_trap_info tr; |
2820 | int nbytes; | ||
2821 | loff_t pos = 0; | 2777 | loff_t pos = 0; |
2822 | 2778 | ||
2823 | if ((sh->flags & SDPCM_SHARED_TRAP) == 0) | 2779 | if ((sh->flags & SDPCM_SHARED_TRAP) == 0) { |
2780 | brcmf_dbg(INFO, "no trap in firmware\n"); | ||
2824 | return 0; | 2781 | return 0; |
2782 | } | ||
2825 | 2783 | ||
2826 | error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr, | 2784 | error = brcmf_sdio_ramrw(bus->sdiodev, false, sh->trap_addr, (u8 *)&tr, |
2827 | sizeof(struct brcmf_trap_info)); | 2785 | sizeof(struct brcmf_trap_info)); |
2828 | if (error < 0) | 2786 | if (error < 0) |
2829 | return error; | 2787 | return error; |
2830 | 2788 | ||
2831 | nbytes = brcmf_sdio_dump_console(bus, sh, data, count); | ||
2832 | if (nbytes < 0) | ||
2833 | return nbytes; | ||
2834 | |||
2835 | res = scnprintf(buf, sizeof(buf), | 2789 | res = scnprintf(buf, sizeof(buf), |
2836 | "dongle trap info: type 0x%x @ epc 0x%08x\n" | 2790 | "dongle trap info: type 0x%x @ epc 0x%08x\n" |
2837 | " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" | 2791 | " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" |
@@ -2847,12 +2801,7 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, | |||
2847 | le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), | 2801 | le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), |
2848 | le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); | 2802 | le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); |
2849 | 2803 | ||
2850 | error = simple_read_from_buffer(data+nbytes, count, &pos, buf, res); | 2804 | return simple_read_from_buffer(data, count, &pos, buf, res); |
2851 | if (error < 0) | ||
2852 | return error; | ||
2853 | |||
2854 | nbytes += error; | ||
2855 | return nbytes; | ||
2856 | } | 2805 | } |
2857 | 2806 | ||
2858 | static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, | 2807 | static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, |
@@ -2876,14 +2825,14 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, | |||
2876 | 2825 | ||
2877 | sdio_claim_host(bus->sdiodev->func[1]); | 2826 | sdio_claim_host(bus->sdiodev->func[1]); |
2878 | if (sh->assert_file_addr != 0) { | 2827 | if (sh->assert_file_addr != 0) { |
2879 | error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr, | 2828 | error = brcmf_sdio_ramrw(bus->sdiodev, false, |
2880 | (u8 *)file, 80); | 2829 | sh->assert_file_addr, (u8 *)file, 80); |
2881 | if (error < 0) | 2830 | if (error < 0) |
2882 | return error; | 2831 | return error; |
2883 | } | 2832 | } |
2884 | if (sh->assert_exp_addr != 0) { | 2833 | if (sh->assert_exp_addr != 0) { |
2885 | error = brcmf_sdbrcm_membytes(bus, false, sh->assert_exp_addr, | 2834 | error = brcmf_sdio_ramrw(bus->sdiodev, false, |
2886 | (u8 *)expr, 80); | 2835 | sh->assert_exp_addr, (u8 *)expr, 80); |
2887 | if (error < 0) | 2836 | if (error < 0) |
2888 | return error; | 2837 | return error; |
2889 | } | 2838 | } |
@@ -2934,14 +2883,20 @@ static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data, | |||
2934 | error = brcmf_sdio_assert_info(bus, &sh, data, count); | 2883 | error = brcmf_sdio_assert_info(bus, &sh, data, count); |
2935 | if (error < 0) | 2884 | if (error < 0) |
2936 | goto done; | 2885 | goto done; |
2937 | |||
2938 | nbytes = error; | 2886 | nbytes = error; |
2939 | error = brcmf_sdio_trap_info(bus, &sh, data, count); | 2887 | |
2888 | error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count); | ||
2940 | if (error < 0) | 2889 | if (error < 0) |
2941 | goto done; | 2890 | goto done; |
2891 | nbytes += error; | ||
2892 | |||
2893 | error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count); | ||
2894 | if (error < 0) | ||
2895 | goto done; | ||
2896 | nbytes += error; | ||
2942 | 2897 | ||
2943 | error += nbytes; | 2898 | error = nbytes; |
2944 | *ppos += error; | 2899 | *ppos += nbytes; |
2945 | done: | 2900 | done: |
2946 | return error; | 2901 | return error; |
2947 | } | 2902 | } |
@@ -3035,84 +2990,8 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) | |||
3035 | return rxlen ? (int)rxlen : -ETIMEDOUT; | 2990 | return rxlen ? (int)rxlen : -ETIMEDOUT; |
3036 | } | 2991 | } |
3037 | 2992 | ||
3038 | static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) | 2993 | static bool brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) |
3039 | { | 2994 | { |
3040 | int bcmerror = 0; | ||
3041 | u32 varaddr; | ||
3042 | u32 varsizew; | ||
3043 | __le32 varsizew_le; | ||
3044 | #ifdef DEBUG | ||
3045 | char *nvram_ularray; | ||
3046 | #endif /* DEBUG */ | ||
3047 | |||
3048 | /* Even if there are no vars are to be written, we still | ||
3049 | need to set the ramsize. */ | ||
3050 | varaddr = (bus->ramsize - 4) - bus->varsz; | ||
3051 | |||
3052 | if (bus->vars) { | ||
3053 | /* Write the vars list */ | ||
3054 | bcmerror = brcmf_sdbrcm_membytes(bus, true, varaddr, | ||
3055 | bus->vars, bus->varsz); | ||
3056 | #ifdef DEBUG | ||
3057 | /* Verify NVRAM bytes */ | ||
3058 | brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", | ||
3059 | bus->varsz); | ||
3060 | nvram_ularray = kmalloc(bus->varsz, GFP_ATOMIC); | ||
3061 | if (!nvram_ularray) | ||
3062 | return -ENOMEM; | ||
3063 | |||
3064 | /* Upload image to verify downloaded contents. */ | ||
3065 | memset(nvram_ularray, 0xaa, bus->varsz); | ||
3066 | |||
3067 | /* Read the vars list to temp buffer for comparison */ | ||
3068 | bcmerror = brcmf_sdbrcm_membytes(bus, false, varaddr, | ||
3069 | nvram_ularray, bus->varsz); | ||
3070 | if (bcmerror) { | ||
3071 | brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n", | ||
3072 | bcmerror, bus->varsz, varaddr); | ||
3073 | } | ||
3074 | /* Compare the org NVRAM with the one read from RAM */ | ||
3075 | if (memcmp(bus->vars, nvram_ularray, bus->varsz)) | ||
3076 | brcmf_err("Downloaded NVRAM image is corrupted\n"); | ||
3077 | else | ||
3078 | brcmf_err("Download/Upload/Compare of NVRAM ok\n"); | ||
3079 | |||
3080 | kfree(nvram_ularray); | ||
3081 | #endif /* DEBUG */ | ||
3082 | } | ||
3083 | |||
3084 | /* adjust to the user specified RAM */ | ||
3085 | brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize); | ||
3086 | brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n", | ||
3087 | varaddr, bus->varsz); | ||
3088 | |||
3089 | /* | ||
3090 | * Determine the length token: | ||
3091 | * Varsize, converted to words, in lower 16-bits, checksum | ||
3092 | * in upper 16-bits. | ||
3093 | */ | ||
3094 | if (bcmerror) { | ||
3095 | varsizew = 0; | ||
3096 | varsizew_le = cpu_to_le32(0); | ||
3097 | } else { | ||
3098 | varsizew = bus->varsz / 4; | ||
3099 | varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); | ||
3100 | varsizew_le = cpu_to_le32(varsizew); | ||
3101 | } | ||
3102 | |||
3103 | brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n", | ||
3104 | bus->varsz, varsizew); | ||
3105 | |||
3106 | /* Write the length token to the last word */ | ||
3107 | bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4), | ||
3108 | (u8 *)&varsizew_le, 4); | ||
3109 | |||
3110 | return bcmerror; | ||
3111 | } | ||
3112 | |||
3113 | static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) | ||
3114 | { | ||
3115 | int bcmerror = 0; | ||
3116 | struct chip_info *ci = bus->ci; | 2995 | struct chip_info *ci = bus->ci; |
3117 | 2996 | ||
3118 | /* To enter download state, disable ARM and reset SOCRAM. | 2997 | /* To enter download state, disable ARM and reset SOCRAM. |
@@ -3121,41 +3000,19 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) | |||
3121 | if (enter) { | 3000 | if (enter) { |
3122 | bus->alp_only = true; | 3001 | bus->alp_only = true; |
3123 | 3002 | ||
3124 | ci->coredisable(bus->sdiodev, ci, BCMA_CORE_ARM_CM3); | 3003 | brcmf_sdio_chip_enter_download(bus->sdiodev, ci); |
3125 | |||
3126 | ci->resetcore(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM); | ||
3127 | |||
3128 | /* Clear the top bit of memory */ | ||
3129 | if (bus->ramsize) { | ||
3130 | u32 zeros = 0; | ||
3131 | brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4, | ||
3132 | (u8 *)&zeros, 4); | ||
3133 | } | ||
3134 | } else { | 3004 | } else { |
3135 | if (!ci->iscoreup(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) { | 3005 | if (!brcmf_sdio_chip_exit_download(bus->sdiodev, ci, bus->vars, |
3136 | brcmf_err("SOCRAM core is down after reset?\n"); | 3006 | bus->varsz)) |
3137 | bcmerror = -EBADE; | 3007 | return false; |
3138 | goto fail; | ||
3139 | } | ||
3140 | |||
3141 | bcmerror = brcmf_sdbrcm_write_vars(bus); | ||
3142 | if (bcmerror) { | ||
3143 | brcmf_err("no vars written to RAM\n"); | ||
3144 | bcmerror = 0; | ||
3145 | } | ||
3146 | |||
3147 | w_sdreg32(bus, 0xFFFFFFFF, | ||
3148 | offsetof(struct sdpcmd_regs, intstatus)); | ||
3149 | |||
3150 | ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3); | ||
3151 | 3008 | ||
3152 | /* Allow HT Clock now that the ARM is running. */ | 3009 | /* Allow HT Clock now that the ARM is running. */ |
3153 | bus->alp_only = false; | 3010 | bus->alp_only = false; |
3154 | 3011 | ||
3155 | bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD; | 3012 | bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD; |
3156 | } | 3013 | } |
3157 | fail: | 3014 | |
3158 | return bcmerror; | 3015 | return true; |
3159 | } | 3016 | } |
3160 | 3017 | ||
3161 | static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus) | 3018 | static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus) |
@@ -3170,10 +3027,11 @@ static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus) | |||
3170 | 3027 | ||
3171 | static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) | 3028 | static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) |
3172 | { | 3029 | { |
3173 | int offset = 0; | 3030 | int offset; |
3174 | uint len; | 3031 | uint len; |
3175 | u8 *memblock = NULL, *memptr; | 3032 | u8 *memblock = NULL, *memptr; |
3176 | int ret; | 3033 | int ret; |
3034 | u8 idx; | ||
3177 | 3035 | ||
3178 | brcmf_dbg(INFO, "Enter\n"); | 3036 | brcmf_dbg(INFO, "Enter\n"); |
3179 | 3037 | ||
@@ -3194,10 +3052,15 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) | |||
3194 | memptr += (BRCMF_SDALIGN - | 3052 | memptr += (BRCMF_SDALIGN - |
3195 | ((u32)(unsigned long)memblock % BRCMF_SDALIGN)); | 3053 | ((u32)(unsigned long)memblock % BRCMF_SDALIGN)); |
3196 | 3054 | ||
3055 | offset = bus->ci->rambase; | ||
3056 | |||
3197 | /* Download image */ | 3057 | /* Download image */ |
3198 | while ((len = | 3058 | len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus); |
3199 | brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) { | 3059 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4); |
3200 | ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len); | 3060 | if (BRCMF_MAX_CORENUM != idx) |
3061 | memcpy(&bus->ci->rst_vec, memptr, sizeof(bus->ci->rst_vec)); | ||
3062 | while (len) { | ||
3063 | ret = brcmf_sdio_ramrw(bus->sdiodev, true, offset, memptr, len); | ||
3201 | if (ret) { | 3064 | if (ret) { |
3202 | brcmf_err("error %d on writing %d membytes at 0x%08x\n", | 3065 | brcmf_err("error %d on writing %d membytes at 0x%08x\n", |
3203 | ret, MEMBLOCK, offset); | 3066 | ret, MEMBLOCK, offset); |
@@ -3205,6 +3068,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) | |||
3205 | } | 3068 | } |
3206 | 3069 | ||
3207 | offset += MEMBLOCK; | 3070 | offset += MEMBLOCK; |
3071 | len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus); | ||
3208 | } | 3072 | } |
3209 | 3073 | ||
3210 | err: | 3074 | err: |
@@ -3312,23 +3176,23 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) | |||
3312 | int bcmerror = -1; | 3176 | int bcmerror = -1; |
3313 | 3177 | ||
3314 | /* Keep arm in reset */ | 3178 | /* Keep arm in reset */ |
3315 | if (brcmf_sdbrcm_download_state(bus, true)) { | 3179 | if (!brcmf_sdbrcm_download_state(bus, true)) { |
3316 | brcmf_err("error placing ARM core in reset\n"); | 3180 | brcmf_err("error placing ARM core in reset\n"); |
3317 | goto err; | 3181 | goto err; |
3318 | } | 3182 | } |
3319 | 3183 | ||
3320 | /* External image takes precedence if specified */ | ||
3321 | if (brcmf_sdbrcm_download_code_file(bus)) { | 3184 | if (brcmf_sdbrcm_download_code_file(bus)) { |
3322 | brcmf_err("dongle image file download failed\n"); | 3185 | brcmf_err("dongle image file download failed\n"); |
3323 | goto err; | 3186 | goto err; |
3324 | } | 3187 | } |
3325 | 3188 | ||
3326 | /* External nvram takes precedence if specified */ | 3189 | if (brcmf_sdbrcm_download_nvram(bus)) { |
3327 | if (brcmf_sdbrcm_download_nvram(bus)) | ||
3328 | brcmf_err("dongle nvram file download failed\n"); | 3190 | brcmf_err("dongle nvram file download failed\n"); |
3191 | goto err; | ||
3192 | } | ||
3329 | 3193 | ||
3330 | /* Take arm out of reset */ | 3194 | /* Take arm out of reset */ |
3331 | if (brcmf_sdbrcm_download_state(bus, false)) { | 3195 | if (!brcmf_sdbrcm_download_state(bus, false)) { |
3332 | brcmf_err("error getting out of ARM core reset\n"); | 3196 | brcmf_err("error getting out of ARM core reset\n"); |
3333 | goto err; | 3197 | goto err; |
3334 | } | 3198 | } |
@@ -3339,6 +3203,103 @@ err: | |||
3339 | return bcmerror; | 3203 | return bcmerror; |
3340 | } | 3204 | } |
3341 | 3205 | ||
3206 | static bool brcmf_sdbrcm_sr_capable(struct brcmf_sdio *bus) | ||
3207 | { | ||
3208 | u32 addr, reg; | ||
3209 | |||
3210 | brcmf_dbg(TRACE, "Enter\n"); | ||
3211 | |||
3212 | /* old chips with PMU version less than 17 don't support save restore */ | ||
3213 | if (bus->ci->pmurev < 17) | ||
3214 | return false; | ||
3215 | |||
3216 | /* read PMU chipcontrol register 3*/ | ||
3217 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr); | ||
3218 | brcmf_sdio_regwl(bus->sdiodev, addr, 3, NULL); | ||
3219 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data); | ||
3220 | reg = brcmf_sdio_regrl(bus->sdiodev, addr, NULL); | ||
3221 | |||
3222 | return (bool)reg; | ||
3223 | } | ||
3224 | |||
3225 | static void brcmf_sdbrcm_sr_init(struct brcmf_sdio *bus) | ||
3226 | { | ||
3227 | int err = 0; | ||
3228 | u8 val; | ||
3229 | |||
3230 | brcmf_dbg(TRACE, "Enter\n"); | ||
3231 | |||
3232 | val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, | ||
3233 | &err); | ||
3234 | if (err) { | ||
3235 | brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n"); | ||
3236 | return; | ||
3237 | } | ||
3238 | |||
3239 | val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT; | ||
3240 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, | ||
3241 | val, &err); | ||
3242 | if (err) { | ||
3243 | brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n"); | ||
3244 | return; | ||
3245 | } | ||
3246 | |||
3247 | /* Add CMD14 Support */ | ||
3248 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP, | ||
3249 | (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | | ||
3250 | SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT), | ||
3251 | &err); | ||
3252 | if (err) { | ||
3253 | brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n"); | ||
3254 | return; | ||
3255 | } | ||
3256 | |||
3257 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
3258 | SBSDIO_FORCE_HT, &err); | ||
3259 | if (err) { | ||
3260 | brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n"); | ||
3261 | return; | ||
3262 | } | ||
3263 | |||
3264 | /* set flag */ | ||
3265 | bus->sr_enabled = true; | ||
3266 | brcmf_dbg(INFO, "SR enabled\n"); | ||
3267 | } | ||
3268 | |||
3269 | /* enable KSO bit */ | ||
3270 | static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus) | ||
3271 | { | ||
3272 | u8 val; | ||
3273 | int err = 0; | ||
3274 | |||
3275 | brcmf_dbg(TRACE, "Enter\n"); | ||
3276 | |||
3277 | /* KSO bit added in SDIO core rev 12 */ | ||
3278 | if (bus->ci->c_inf[1].rev < 12) | ||
3279 | return 0; | ||
3280 | |||
3281 | val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | ||
3282 | &err); | ||
3283 | if (err) { | ||
3284 | brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n"); | ||
3285 | return err; | ||
3286 | } | ||
3287 | |||
3288 | if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) { | ||
3289 | val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << | ||
3290 | SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); | ||
3291 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | ||
3292 | val, &err); | ||
3293 | if (err) { | ||
3294 | brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n"); | ||
3295 | return err; | ||
3296 | } | ||
3297 | } | ||
3298 | |||
3299 | return 0; | ||
3300 | } | ||
3301 | |||
3302 | |||
3342 | static bool | 3303 | static bool |
3343 | brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) | 3304 | brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) |
3344 | { | 3305 | { |
@@ -3437,8 +3398,13 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
3437 | ret = -ENODEV; | 3398 | ret = -ENODEV; |
3438 | } | 3399 | } |
3439 | 3400 | ||
3440 | /* Restore previous clock setting */ | 3401 | if (brcmf_sdbrcm_sr_capable(bus)) { |
3441 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); | 3402 | brcmf_sdbrcm_sr_init(bus); |
3403 | } else { | ||
3404 | /* Restore previous clock setting */ | ||
3405 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
3406 | saveclk, &err); | ||
3407 | } | ||
3442 | 3408 | ||
3443 | if (ret == 0) { | 3409 | if (ret == 0) { |
3444 | ret = brcmf_sdio_intr_register(bus->sdiodev); | 3410 | ret = brcmf_sdio_intr_register(bus->sdiodev); |
@@ -3499,7 +3465,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3499 | brcmf_dbg(TIMER, "Enter\n"); | 3465 | brcmf_dbg(TIMER, "Enter\n"); |
3500 | 3466 | ||
3501 | /* Poll period: check device if appropriate. */ | 3467 | /* Poll period: check device if appropriate. */ |
3502 | if (bus->poll && (++bus->polltick >= bus->pollrate)) { | 3468 | if (!bus->sr_enabled && |
3469 | bus->poll && (++bus->polltick >= bus->pollrate)) { | ||
3503 | u32 intstatus = 0; | 3470 | u32 intstatus = 0; |
3504 | 3471 | ||
3505 | /* Reset poll tick */ | 3472 | /* Reset poll tick */ |
@@ -3550,7 +3517,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3550 | bus->console.count -= bus->console_interval; | 3517 | bus->console.count -= bus->console_interval; |
3551 | sdio_claim_host(bus->sdiodev->func[1]); | 3518 | sdio_claim_host(bus->sdiodev->func[1]); |
3552 | /* Make sure backplane clock is on */ | 3519 | /* Make sure backplane clock is on */ |
3553 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 3520 | brcmf_sdbrcm_bus_sleep(bus, false, false); |
3554 | if (brcmf_sdbrcm_readconsole(bus) < 0) | 3521 | if (brcmf_sdbrcm_readconsole(bus) < 0) |
3555 | /* stop on error */ | 3522 | /* stop on error */ |
3556 | bus->console_interval = 0; | 3523 | bus->console_interval = 0; |
@@ -3567,8 +3534,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3567 | bus->activity = false; | 3534 | bus->activity = false; |
3568 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); | 3535 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); |
3569 | } else { | 3536 | } else { |
3537 | brcmf_dbg(SDIO, "idle\n"); | ||
3570 | sdio_claim_host(bus->sdiodev->func[1]); | 3538 | sdio_claim_host(bus->sdiodev->func[1]); |
3571 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); | 3539 | brcmf_sdbrcm_bus_sleep(bus, true, false); |
3572 | sdio_release_host(bus->sdiodev->func[1]); | 3540 | sdio_release_host(bus->sdiodev->func[1]); |
3573 | } | 3541 | } |
3574 | } | 3542 | } |
@@ -3579,6 +3547,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3579 | 3547 | ||
3580 | static bool brcmf_sdbrcm_chipmatch(u16 chipid) | 3548 | static bool brcmf_sdbrcm_chipmatch(u16 chipid) |
3581 | { | 3549 | { |
3550 | if (chipid == BCM43143_CHIP_ID) | ||
3551 | return true; | ||
3582 | if (chipid == BCM43241_CHIP_ID) | 3552 | if (chipid == BCM43241_CHIP_ID) |
3583 | return true; | 3553 | return true; |
3584 | if (chipid == BCM4329_CHIP_ID) | 3554 | if (chipid == BCM4329_CHIP_ID) |
@@ -3587,6 +3557,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid) | |||
3587 | return true; | 3557 | return true; |
3588 | if (chipid == BCM4334_CHIP_ID) | 3558 | if (chipid == BCM4334_CHIP_ID) |
3589 | return true; | 3559 | return true; |
3560 | if (chipid == BCM4335_CHIP_ID) | ||
3561 | return true; | ||
3590 | return false; | 3562 | return false; |
3591 | } | 3563 | } |
3592 | 3564 | ||
@@ -3664,7 +3636,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3664 | int err = 0; | 3636 | int err = 0; |
3665 | int reg_addr; | 3637 | int reg_addr; |
3666 | u32 reg_val; | 3638 | u32 reg_val; |
3667 | u8 idx; | 3639 | u32 drivestrength; |
3668 | 3640 | ||
3669 | bus->alp_only = true; | 3641 | bus->alp_only = true; |
3670 | 3642 | ||
@@ -3700,8 +3672,16 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3700 | goto fail; | 3672 | goto fail; |
3701 | } | 3673 | } |
3702 | 3674 | ||
3703 | brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, | 3675 | if (brcmf_sdbrcm_kso_init(bus)) { |
3704 | SDIO_DRIVE_STRENGTH); | 3676 | brcmf_err("error enabling KSO\n"); |
3677 | goto fail; | ||
3678 | } | ||
3679 | |||
3680 | if ((bus->sdiodev->pdata) && (bus->sdiodev->pdata->drive_strength)) | ||
3681 | drivestrength = bus->sdiodev->pdata->drive_strength; | ||
3682 | else | ||
3683 | drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH; | ||
3684 | brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength); | ||
3705 | 3685 | ||
3706 | /* Get info on the SOCRAM cores... */ | 3686 | /* Get info on the SOCRAM cores... */ |
3707 | bus->ramsize = bus->ci->ramsize; | 3687 | bus->ramsize = bus->ci->ramsize; |
@@ -3710,12 +3690,37 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3710 | goto fail; | 3690 | goto fail; |
3711 | } | 3691 | } |
3712 | 3692 | ||
3713 | /* Set core control so an SDIO reset does a backplane reset */ | 3693 | /* Set card control so an SDIO card reset does a WLAN backplane reset */ |
3714 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | 3694 | reg_val = brcmf_sdio_regrb(bus->sdiodev, |
3715 | reg_addr = bus->ci->c_inf[idx].base + | 3695 | SDIO_CCCR_BRCM_CARDCTRL, &err); |
3716 | offsetof(struct sdpcmd_regs, corecontrol); | 3696 | if (err) |
3717 | reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL); | 3697 | goto fail; |
3718 | brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL); | 3698 | |
3699 | reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET; | ||
3700 | |||
3701 | brcmf_sdio_regwb(bus->sdiodev, | ||
3702 | SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err); | ||
3703 | if (err) | ||
3704 | goto fail; | ||
3705 | |||
3706 | /* set PMUControl so a backplane reset does PMU state reload */ | ||
3707 | reg_addr = CORE_CC_REG(bus->ci->c_inf[0].base, | ||
3708 | pmucontrol); | ||
3709 | reg_val = brcmf_sdio_regrl(bus->sdiodev, | ||
3710 | reg_addr, | ||
3711 | &err); | ||
3712 | if (err) | ||
3713 | goto fail; | ||
3714 | |||
3715 | reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT); | ||
3716 | |||
3717 | brcmf_sdio_regwl(bus->sdiodev, | ||
3718 | reg_addr, | ||
3719 | reg_val, | ||
3720 | &err); | ||
3721 | if (err) | ||
3722 | goto fail; | ||
3723 | |||
3719 | 3724 | ||
3720 | sdio_release_host(bus->sdiodev->func[1]); | 3725 | sdio_release_host(bus->sdiodev->func[1]); |
3721 | 3726 | ||
@@ -3769,6 +3774,10 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) | |||
3769 | bus->use_rxchain = false; | 3774 | bus->use_rxchain = false; |
3770 | bus->sd_rxchain = false; | 3775 | bus->sd_rxchain = false; |
3771 | 3776 | ||
3777 | /* SR state */ | ||
3778 | bus->sleeping = false; | ||
3779 | bus->sr_enabled = false; | ||
3780 | |||
3772 | return true; | 3781 | return true; |
3773 | } | 3782 | } |
3774 | 3783 | ||
@@ -3856,6 +3865,7 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = { | |||
3856 | .txdata = brcmf_sdbrcm_bus_txdata, | 3865 | .txdata = brcmf_sdbrcm_bus_txdata, |
3857 | .txctl = brcmf_sdbrcm_bus_txctl, | 3866 | .txctl = brcmf_sdbrcm_bus_txctl, |
3858 | .rxctl = brcmf_sdbrcm_bus_rxctl, | 3867 | .rxctl = brcmf_sdbrcm_bus_rxctl, |
3868 | .gettxq = brcmf_sdbrcm_bus_gettxq, | ||
3859 | }; | 3869 | }; |
3860 | 3870 | ||
3861 | void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | 3871 | void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index e9d6f91a1f2b..5a64280e6485 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c | |||
@@ -20,6 +20,8 @@ | |||
20 | 20 | ||
21 | #include "dhd.h" | 21 | #include "dhd.h" |
22 | #include "dhd_dbg.h" | 22 | #include "dhd_dbg.h" |
23 | #include "tracepoint.h" | ||
24 | #include "fwsignal.h" | ||
23 | #include "fweh.h" | 25 | #include "fweh.h" |
24 | #include "fwil.h" | 26 | #include "fwil.h" |
25 | 27 | ||
@@ -154,7 +156,7 @@ static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp, | |||
154 | fweh = &ifp->drvr->fweh; | 156 | fweh = &ifp->drvr->fweh; |
155 | 157 | ||
156 | /* handle the event if valid interface and handler */ | 158 | /* handle the event if valid interface and handler */ |
157 | if (ifp->ndev && fweh->evt_handler[code]) | 159 | if (fweh->evt_handler[code]) |
158 | err = fweh->evt_handler[code](ifp, emsg, data); | 160 | err = fweh->evt_handler[code](ifp, emsg, data); |
159 | else | 161 | else |
160 | brcmf_err("unhandled event %d ignored\n", code); | 162 | brcmf_err("unhandled event %d ignored\n", code); |
@@ -179,9 +181,9 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, | |||
179 | struct brcmf_if *ifp; | 181 | struct brcmf_if *ifp; |
180 | int err = 0; | 182 | int err = 0; |
181 | 183 | ||
182 | brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u\n", | 184 | brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n", |
183 | ifevent->action, ifevent->ifidx, | 185 | ifevent->action, ifevent->ifidx, ifevent->bssidx, |
184 | ifevent->bssidx, ifevent->flags); | 186 | ifevent->flags, ifevent->role); |
185 | 187 | ||
186 | if (ifevent->ifidx >= BRCMF_MAX_IFS) { | 188 | if (ifevent->ifidx >= BRCMF_MAX_IFS) { |
187 | brcmf_err("invalid interface index: %u\n", | 189 | brcmf_err("invalid interface index: %u\n", |
@@ -198,15 +200,20 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, | |||
198 | emsg->ifname, emsg->addr); | 200 | emsg->ifname, emsg->addr); |
199 | if (IS_ERR(ifp)) | 201 | if (IS_ERR(ifp)) |
200 | return; | 202 | return; |
201 | 203 | brcmf_fws_add_interface(ifp); | |
202 | if (!drvr->fweh.evt_handler[BRCMF_E_IF]) | 204 | if (!drvr->fweh.evt_handler[BRCMF_E_IF]) |
203 | err = brcmf_net_attach(ifp, false); | 205 | err = brcmf_net_attach(ifp, false); |
204 | } | 206 | } |
205 | 207 | ||
208 | if (ifevent->action == BRCMF_E_IF_CHANGE) | ||
209 | brcmf_fws_reset_interface(ifp); | ||
210 | |||
206 | err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); | 211 | err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); |
207 | 212 | ||
208 | if (ifevent->action == BRCMF_E_IF_DEL) | 213 | if (ifevent->action == BRCMF_E_IF_DEL) { |
214 | brcmf_fws_del_interface(ifp); | ||
209 | brcmf_del_if(drvr, ifevent->bssidx); | 215 | brcmf_del_if(drvr, ifevent->bssidx); |
216 | } | ||
210 | } | 217 | } |
211 | 218 | ||
212 | /** | 219 | /** |
@@ -400,13 +407,12 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp) | |||
400 | * | 407 | * |
401 | * @drvr: driver information object. | 408 | * @drvr: driver information object. |
402 | * @event_packet: event packet to process. | 409 | * @event_packet: event packet to process. |
403 | * @ifidx: index of the firmware interface (may change). | ||
404 | * | 410 | * |
405 | * If the packet buffer contains a firmware event message it will | 411 | * If the packet buffer contains a firmware event message it will |
406 | * dispatch the event to a registered handler (using worker). | 412 | * dispatch the event to a registered handler (using worker). |
407 | */ | 413 | */ |
408 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, | 414 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, |
409 | struct brcmf_event *event_packet, u8 *ifidx) | 415 | struct brcmf_event *event_packet) |
410 | { | 416 | { |
411 | enum brcmf_fweh_event_code code; | 417 | enum brcmf_fweh_event_code code; |
412 | struct brcmf_fweh_info *fweh = &drvr->fweh; | 418 | struct brcmf_fweh_info *fweh = &drvr->fweh; |
@@ -418,7 +424,6 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, | |||
418 | /* get event info */ | 424 | /* get event info */ |
419 | code = get_unaligned_be32(&event_packet->msg.event_type); | 425 | code = get_unaligned_be32(&event_packet->msg.event_type); |
420 | datalen = get_unaligned_be32(&event_packet->msg.datalen); | 426 | datalen = get_unaligned_be32(&event_packet->msg.datalen); |
421 | *ifidx = event_packet->msg.ifidx; | ||
422 | data = &event_packet[1]; | 427 | data = &event_packet[1]; |
423 | 428 | ||
424 | if (code >= BRCMF_E_LAST) | 429 | if (code >= BRCMF_E_LAST) |
@@ -435,7 +440,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, | |||
435 | return; | 440 | return; |
436 | 441 | ||
437 | event->code = code; | 442 | event->code = code; |
438 | event->ifidx = *ifidx; | 443 | event->ifidx = event_packet->msg.ifidx; |
439 | 444 | ||
440 | /* use memcpy to get aligned event message */ | 445 | /* use memcpy to get aligned event message */ |
441 | memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg)); | 446 | memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg)); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index 8c39b51dcccf..6ec5db9c60a5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h | |||
@@ -187,10 +187,10 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr, | |||
187 | enum brcmf_fweh_event_code code); | 187 | enum brcmf_fweh_event_code code); |
188 | int brcmf_fweh_activate_events(struct brcmf_if *ifp); | 188 | int brcmf_fweh_activate_events(struct brcmf_if *ifp); |
189 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, | 189 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, |
190 | struct brcmf_event *event_packet, u8 *ifidx); | 190 | struct brcmf_event *event_packet); |
191 | 191 | ||
192 | static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, | 192 | static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, |
193 | struct sk_buff *skb, u8 *ifidx) | 193 | struct sk_buff *skb) |
194 | { | 194 | { |
195 | struct brcmf_event *event_packet; | 195 | struct brcmf_event *event_packet; |
196 | u8 *data; | 196 | u8 *data; |
@@ -213,7 +213,7 @@ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, | |||
213 | if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT) | 213 | if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT) |
214 | return; | 214 | return; |
215 | 215 | ||
216 | brcmf_fweh_process_event(drvr, event_packet, ifidx); | 216 | brcmf_fweh_process_event(drvr, event_packet); |
217 | } | 217 | } |
218 | 218 | ||
219 | #endif /* FWEH_H_ */ | 219 | #endif /* FWEH_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index 8d1def935b8d..04f395930d86 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "dhd.h" | 25 | #include "dhd.h" |
26 | #include "dhd_bus.h" | 26 | #include "dhd_bus.h" |
27 | #include "dhd_dbg.h" | 27 | #include "dhd_dbg.h" |
28 | #include "tracepoint.h" | ||
28 | #include "fwil.h" | 29 | #include "fwil.h" |
29 | 30 | ||
30 | 31 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c new file mode 100644 index 000000000000..1bcd58ce4a2f --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -0,0 +1,1948 @@ | |||
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/module.h> | ||
18 | #include <linux/if_ether.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/skbuff.h> | ||
21 | #include <linux/netdevice.h> | ||
22 | #include <linux/etherdevice.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <uapi/linux/nl80211.h> | ||
25 | #include <net/cfg80211.h> | ||
26 | |||
27 | #include <brcmu_utils.h> | ||
28 | #include <brcmu_wifi.h> | ||
29 | #include "dhd.h" | ||
30 | #include "dhd_proto.h" | ||
31 | #include "dhd_dbg.h" | ||
32 | #include "dhd_bus.h" | ||
33 | #include "fwil.h" | ||
34 | #include "fwil_types.h" | ||
35 | #include "fweh.h" | ||
36 | #include "fwsignal.h" | ||
37 | #include "p2p.h" | ||
38 | #include "wl_cfg80211.h" | ||
39 | |||
40 | /** | ||
41 | * DOC: Firmware Signalling | ||
42 | * | ||
43 | * Firmware can send signals to host and vice versa, which are passed in the | ||
44 | * data packets using TLV based header. This signalling layer is on top of the | ||
45 | * BDC bus protocol layer. | ||
46 | */ | ||
47 | |||
48 | /* | ||
49 | * single definition for firmware-driver flow control tlv's. | ||
50 | * | ||
51 | * each tlv is specified by BRCMF_FWS_TLV_DEF(name, ID, length). | ||
52 | * A length value 0 indicates variable length tlv. | ||
53 | */ | ||
54 | #define BRCMF_FWS_TLV_DEFLIST \ | ||
55 | BRCMF_FWS_TLV_DEF(MAC_OPEN, 1, 1) \ | ||
56 | BRCMF_FWS_TLV_DEF(MAC_CLOSE, 2, 1) \ | ||
57 | BRCMF_FWS_TLV_DEF(MAC_REQUEST_CREDIT, 3, 2) \ | ||
58 | BRCMF_FWS_TLV_DEF(TXSTATUS, 4, 4) \ | ||
59 | BRCMF_FWS_TLV_DEF(PKTTAG, 5, 4) \ | ||
60 | BRCMF_FWS_TLV_DEF(MACDESC_ADD, 6, 8) \ | ||
61 | BRCMF_FWS_TLV_DEF(MACDESC_DEL, 7, 8) \ | ||
62 | BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \ | ||
63 | BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \ | ||
64 | BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \ | ||
65 | BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 6) \ | ||
66 | BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \ | ||
67 | BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \ | ||
68 | BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \ | ||
69 | BRCMF_FWS_TLV_DEF(TRANS_ID, 18, 6) \ | ||
70 | BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \ | ||
71 | BRCMF_FWS_TLV_DEF(FILLER, 255, 0) | ||
72 | |||
73 | /* | ||
74 | * enum brcmf_fws_tlv_type - definition of tlv identifiers. | ||
75 | */ | ||
76 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
77 | BRCMF_FWS_TYPE_ ## name = id, | ||
78 | enum brcmf_fws_tlv_type { | ||
79 | BRCMF_FWS_TLV_DEFLIST | ||
80 | BRCMF_FWS_TYPE_INVALID | ||
81 | }; | ||
82 | #undef BRCMF_FWS_TLV_DEF | ||
83 | |||
84 | /* | ||
85 | * enum brcmf_fws_tlv_len - definition of tlv lengths. | ||
86 | */ | ||
87 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
88 | BRCMF_FWS_TYPE_ ## name ## _LEN = (len), | ||
89 | enum brcmf_fws_tlv_len { | ||
90 | BRCMF_FWS_TLV_DEFLIST | ||
91 | }; | ||
92 | #undef BRCMF_FWS_TLV_DEF | ||
93 | |||
94 | #ifdef DEBUG | ||
95 | /* | ||
96 | * brcmf_fws_tlv_names - array of tlv names. | ||
97 | */ | ||
98 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
99 | { id, #name }, | ||
100 | static struct { | ||
101 | enum brcmf_fws_tlv_type id; | ||
102 | const char *name; | ||
103 | } brcmf_fws_tlv_names[] = { | ||
104 | BRCMF_FWS_TLV_DEFLIST | ||
105 | }; | ||
106 | #undef BRCMF_FWS_TLV_DEF | ||
107 | |||
108 | static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | ||
109 | { | ||
110 | int i; | ||
111 | |||
112 | for (i = 0; i < ARRAY_SIZE(brcmf_fws_tlv_names); i++) | ||
113 | if (brcmf_fws_tlv_names[i].id == id) | ||
114 | return brcmf_fws_tlv_names[i].name; | ||
115 | |||
116 | return "INVALID"; | ||
117 | } | ||
118 | #else | ||
119 | static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | ||
120 | { | ||
121 | return "NODEBUG"; | ||
122 | } | ||
123 | #endif /* DEBUG */ | ||
124 | |||
125 | /* | ||
126 | * flags used to enable tlv signalling from firmware. | ||
127 | */ | ||
128 | #define BRCMF_FWS_FLAGS_RSSI_SIGNALS 0x0001 | ||
129 | #define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS 0x0002 | ||
130 | #define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS 0x0004 | ||
131 | #define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE 0x0008 | ||
132 | #define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE 0x0010 | ||
133 | #define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE 0x0020 | ||
134 | #define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE 0x0040 | ||
135 | |||
136 | #define BRCMF_FWS_MAC_DESC_TABLE_SIZE 32 | ||
137 | #define BRCMF_FWS_MAC_DESC_ID_INVALID 0xff | ||
138 | |||
139 | #define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF 0 | ||
140 | #define BRCMF_FWS_HOSTIF_FLOWSTATE_ON 1 | ||
141 | #define BRCMF_FWS_FLOWCONTROL_HIWATER 128 | ||
142 | #define BRCMF_FWS_FLOWCONTROL_LOWATER 64 | ||
143 | |||
144 | #define BRCMF_FWS_PSQ_PREC_COUNT ((NL80211_NUM_ACS + 1) * 2) | ||
145 | #define BRCMF_FWS_PSQ_LEN 256 | ||
146 | |||
147 | #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01 | ||
148 | #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED 0x02 | ||
149 | |||
150 | /** | ||
151 | * enum brcmf_fws_skb_state - indicates processing state of skb. | ||
152 | * | ||
153 | * @BRCMF_FWS_SKBSTATE_NEW: sk_buff is newly arrived in the driver. | ||
154 | * @BRCMF_FWS_SKBSTATE_DELAYED: sk_buff had to wait on queue. | ||
155 | * @BRCMF_FWS_SKBSTATE_SUPPRESSED: sk_buff has been suppressed by firmware. | ||
156 | */ | ||
157 | enum brcmf_fws_skb_state { | ||
158 | BRCMF_FWS_SKBSTATE_NEW, | ||
159 | BRCMF_FWS_SKBSTATE_DELAYED, | ||
160 | BRCMF_FWS_SKBSTATE_SUPPRESSED | ||
161 | }; | ||
162 | |||
163 | /** | ||
164 | * struct brcmf_skbuff_cb - control buffer associated with skbuff. | ||
165 | * | ||
166 | * @if_flags: holds interface index and packet related flags. | ||
167 | * @htod: host to device packet identifier (used in PKTTAG tlv). | ||
168 | * @state: transmit state of the packet. | ||
169 | * @mac: descriptor related to destination for this packet. | ||
170 | * | ||
171 | * This information is stored in control buffer struct sk_buff::cb, which | ||
172 | * provides 48 bytes of storage so this structure should not exceed that. | ||
173 | */ | ||
174 | struct brcmf_skbuff_cb { | ||
175 | u16 if_flags; | ||
176 | u32 htod; | ||
177 | enum brcmf_fws_skb_state state; | ||
178 | struct brcmf_fws_mac_descriptor *mac; | ||
179 | }; | ||
180 | |||
181 | /* | ||
182 | * macro casting skbuff control buffer to struct brcmf_skbuff_cb. | ||
183 | */ | ||
184 | #define brcmf_skbcb(skb) ((struct brcmf_skbuff_cb *)((skb)->cb)) | ||
185 | |||
186 | /* | ||
187 | * sk_buff control if flags | ||
188 | * | ||
189 | * b[11] - packet sent upon firmware request. | ||
190 | * b[10] - packet only contains signalling data. | ||
191 | * b[9] - packet is a tx packet. | ||
192 | * b[8] - packet uses FIFO credit (non-pspoll). | ||
193 | * b[7] - interface in AP mode. | ||
194 | * b[6:4] - AC FIFO number. | ||
195 | * b[3:0] - interface index. | ||
196 | */ | ||
197 | #define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK 0x0800 | ||
198 | #define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT 11 | ||
199 | #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK 0x0400 | ||
200 | #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_SHIFT 10 | ||
201 | #define BRCMF_SKB_IF_FLAGS_TRANSMIT_MASK 0x0200 | ||
202 | #define BRCMF_SKB_IF_FLAGS_TRANSMIT_SHIFT 9 | ||
203 | #define BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK 0x0100 | ||
204 | #define BRCMF_SKB_IF_FLAGS_CREDITCHECK_SHIFT 8 | ||
205 | #define BRCMF_SKB_IF_FLAGS_IF_AP_MASK 0x0080 | ||
206 | #define BRCMF_SKB_IF_FLAGS_IF_AP_SHIFT 7 | ||
207 | #define BRCMF_SKB_IF_FLAGS_FIFO_MASK 0x0070 | ||
208 | #define BRCMF_SKB_IF_FLAGS_FIFO_SHIFT 4 | ||
209 | #define BRCMF_SKB_IF_FLAGS_INDEX_MASK 0x000f | ||
210 | #define BRCMF_SKB_IF_FLAGS_INDEX_SHIFT 0 | ||
211 | |||
212 | #define brcmf_skb_if_flags_set_field(skb, field, value) \ | ||
213 | brcmu_maskset16(&(brcmf_skbcb(skb)->if_flags), \ | ||
214 | BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \ | ||
215 | BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT, (value)) | ||
216 | #define brcmf_skb_if_flags_get_field(skb, field) \ | ||
217 | brcmu_maskget16(brcmf_skbcb(skb)->if_flags, \ | ||
218 | BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \ | ||
219 | BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT) | ||
220 | |||
221 | /* | ||
222 | * sk_buff control packet identifier | ||
223 | * | ||
224 | * 32-bit packet identifier used in PKTTAG tlv from host to dongle. | ||
225 | * | ||
226 | * - Generated at the host (e.g. dhd) | ||
227 | * - Seen as a generic sequence number by firmware except for the flags field. | ||
228 | * | ||
229 | * Generation : b[31] => generation number for this packet [host->fw] | ||
230 | * OR, current generation number [fw->host] | ||
231 | * Flags : b[30:27] => command, status flags | ||
232 | * FIFO-AC : b[26:24] => AC-FIFO id | ||
233 | * h-slot : b[23:8] => hanger-slot | ||
234 | * freerun : b[7:0] => A free running counter | ||
235 | */ | ||
236 | #define BRCMF_SKB_HTOD_TAG_GENERATION_MASK 0x80000000 | ||
237 | #define BRCMF_SKB_HTOD_TAG_GENERATION_SHIFT 31 | ||
238 | #define BRCMF_SKB_HTOD_TAG_FLAGS_MASK 0x78000000 | ||
239 | #define BRCMF_SKB_HTOD_TAG_FLAGS_SHIFT 27 | ||
240 | #define BRCMF_SKB_HTOD_TAG_FIFO_MASK 0x07000000 | ||
241 | #define BRCMF_SKB_HTOD_TAG_FIFO_SHIFT 24 | ||
242 | #define BRCMF_SKB_HTOD_TAG_HSLOT_MASK 0x00ffff00 | ||
243 | #define BRCMF_SKB_HTOD_TAG_HSLOT_SHIFT 8 | ||
244 | #define BRCMF_SKB_HTOD_TAG_FREERUN_MASK 0x000000ff | ||
245 | #define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT 0 | ||
246 | |||
247 | #define brcmf_skb_htod_tag_set_field(skb, field, value) \ | ||
248 | brcmu_maskset32(&(brcmf_skbcb(skb)->htod), \ | ||
249 | BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ | ||
250 | BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT, (value)) | ||
251 | #define brcmf_skb_htod_tag_get_field(skb, field) \ | ||
252 | brcmu_maskget32(brcmf_skbcb(skb)->htod, \ | ||
253 | BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ | ||
254 | BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT) | ||
255 | |||
256 | #define BRCMF_FWS_TXSTAT_GENERATION_MASK 0x80000000 | ||
257 | #define BRCMF_FWS_TXSTAT_GENERATION_SHIFT 31 | ||
258 | #define BRCMF_FWS_TXSTAT_FLAGS_MASK 0x78000000 | ||
259 | #define BRCMF_FWS_TXSTAT_FLAGS_SHIFT 27 | ||
260 | #define BRCMF_FWS_TXSTAT_FIFO_MASK 0x07000000 | ||
261 | #define BRCMF_FWS_TXSTAT_FIFO_SHIFT 24 | ||
262 | #define BRCMF_FWS_TXSTAT_HSLOT_MASK 0x00FFFF00 | ||
263 | #define BRCMF_FWS_TXSTAT_HSLOT_SHIFT 8 | ||
264 | #define BRCMF_FWS_TXSTAT_PKTID_MASK 0x00FFFFFF | ||
265 | #define BRCMF_FWS_TXSTAT_PKTID_SHIFT 0 | ||
266 | |||
267 | #define brcmf_txstatus_get_field(txs, field) \ | ||
268 | brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \ | ||
269 | BRCMF_FWS_TXSTAT_ ## field ## _SHIFT) | ||
270 | |||
271 | /** | ||
272 | * enum brcmf_fws_fifo - fifo indices used by dongle firmware. | ||
273 | * | ||
274 | * @BRCMF_FWS_FIFO_AC_BK: fifo for background traffic. | ||
275 | * @BRCMF_FWS_FIFO_AC_BE: fifo for best-effort traffic. | ||
276 | * @BRCMF_FWS_FIFO_AC_VI: fifo for video traffic. | ||
277 | * @BRCMF_FWS_FIFO_AC_VO: fifo for voice traffic. | ||
278 | * @BRCMF_FWS_FIFO_BCMC: fifo for broadcast/multicast (AP only). | ||
279 | * @BRCMF_FWS_FIFO_ATIM: fifo for ATIM (AP only). | ||
280 | * @BRCMF_FWS_FIFO_COUNT: number of fifos. | ||
281 | */ | ||
282 | enum brcmf_fws_fifo { | ||
283 | BRCMF_FWS_FIFO_AC_BK, | ||
284 | BRCMF_FWS_FIFO_AC_BE, | ||
285 | BRCMF_FWS_FIFO_AC_VI, | ||
286 | BRCMF_FWS_FIFO_AC_VO, | ||
287 | BRCMF_FWS_FIFO_BCMC, | ||
288 | BRCMF_FWS_FIFO_ATIM, | ||
289 | BRCMF_FWS_FIFO_COUNT | ||
290 | }; | ||
291 | |||
292 | /** | ||
293 | * enum brcmf_fws_txstatus - txstatus flag values. | ||
294 | * | ||
295 | * @BRCMF_FWS_TXSTATUS_DISCARD: | ||
296 | * host is free to discard the packet. | ||
297 | * @BRCMF_FWS_TXSTATUS_CORE_SUPPRESS: | ||
298 | * 802.11 core suppressed the packet. | ||
299 | * @BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS: | ||
300 | * firmware suppress the packet as device is already in PS mode. | ||
301 | * @BRCMF_FWS_TXSTATUS_FW_TOSSED: | ||
302 | * firmware tossed the packet. | ||
303 | */ | ||
304 | enum brcmf_fws_txstatus { | ||
305 | BRCMF_FWS_TXSTATUS_DISCARD, | ||
306 | BRCMF_FWS_TXSTATUS_CORE_SUPPRESS, | ||
307 | BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS, | ||
308 | BRCMF_FWS_TXSTATUS_FW_TOSSED | ||
309 | }; | ||
310 | |||
311 | enum brcmf_fws_fcmode { | ||
312 | BRCMF_FWS_FCMODE_NONE, | ||
313 | BRCMF_FWS_FCMODE_IMPLIED_CREDIT, | ||
314 | BRCMF_FWS_FCMODE_EXPLICIT_CREDIT | ||
315 | }; | ||
316 | |||
317 | enum brcmf_fws_mac_desc_state { | ||
318 | BRCMF_FWS_STATE_OPEN = 1, | ||
319 | BRCMF_FWS_STATE_CLOSE | ||
320 | }; | ||
321 | |||
322 | /** | ||
323 | * struct brcmf_fws_mac_descriptor - firmware signalling data per node/interface | ||
324 | * | ||
325 | * @occupied: slot is in use. | ||
326 | * @mac_handle: handle for mac entry determined by firmware. | ||
327 | * @interface_id: interface index. | ||
328 | * @state: current state. | ||
329 | * @suppressed: mac entry is suppressed. | ||
330 | * @generation: generation bit. | ||
331 | * @ac_bitmap: ac queue bitmap. | ||
332 | * @requested_credit: credits requested by firmware. | ||
333 | * @ea: ethernet address. | ||
334 | * @seq: per-node free-running sequence. | ||
335 | * @psq: power-save queue. | ||
336 | * @transit_count: packet in transit to firmware. | ||
337 | */ | ||
338 | struct brcmf_fws_mac_descriptor { | ||
339 | u8 occupied; | ||
340 | u8 mac_handle; | ||
341 | u8 interface_id; | ||
342 | u8 state; | ||
343 | bool suppressed; | ||
344 | u8 generation; | ||
345 | u8 ac_bitmap; | ||
346 | u8 requested_credit; | ||
347 | u8 requested_packet; | ||
348 | u8 ea[ETH_ALEN]; | ||
349 | u8 seq[BRCMF_FWS_FIFO_COUNT]; | ||
350 | struct pktq psq; | ||
351 | int transit_count; | ||
352 | int suppress_count; | ||
353 | int suppr_transit_count; | ||
354 | bool send_tim_signal; | ||
355 | u8 traffic_pending_bmp; | ||
356 | u8 traffic_lastreported_bmp; | ||
357 | }; | ||
358 | |||
359 | #define BRCMF_FWS_HANGER_MAXITEMS 1024 | ||
360 | |||
361 | /** | ||
362 | * enum brcmf_fws_hanger_item_state - state of hanger item. | ||
363 | * | ||
364 | * @BRCMF_FWS_HANGER_ITEM_STATE_FREE: item is free for use. | ||
365 | * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE: item is in use. | ||
366 | * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED: item was suppressed. | ||
367 | */ | ||
368 | enum brcmf_fws_hanger_item_state { | ||
369 | BRCMF_FWS_HANGER_ITEM_STATE_FREE = 1, | ||
370 | BRCMF_FWS_HANGER_ITEM_STATE_INUSE, | ||
371 | BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED | ||
372 | }; | ||
373 | |||
374 | |||
375 | /** | ||
376 | * struct brcmf_fws_hanger_item - single entry for tx pending packet. | ||
377 | * | ||
378 | * @state: entry is either free or occupied. | ||
379 | * @gen: generation. | ||
380 | * @pkt: packet itself. | ||
381 | */ | ||
382 | struct brcmf_fws_hanger_item { | ||
383 | enum brcmf_fws_hanger_item_state state; | ||
384 | u8 gen; | ||
385 | struct sk_buff *pkt; | ||
386 | }; | ||
387 | |||
388 | /** | ||
389 | * struct brcmf_fws_hanger - holds packets awaiting firmware txstatus. | ||
390 | * | ||
391 | * @pushed: packets pushed to await txstatus. | ||
392 | * @popped: packets popped upon handling txstatus. | ||
393 | * @failed_to_push: packets that could not be pushed. | ||
394 | * @failed_to_pop: packets that could not be popped. | ||
395 | * @failed_slotfind: packets for which failed to find an entry. | ||
396 | * @slot_pos: last returned item index for a free entry. | ||
397 | * @items: array of hanger items. | ||
398 | */ | ||
399 | struct brcmf_fws_hanger { | ||
400 | u32 pushed; | ||
401 | u32 popped; | ||
402 | u32 failed_to_push; | ||
403 | u32 failed_to_pop; | ||
404 | u32 failed_slotfind; | ||
405 | u32 slot_pos; | ||
406 | struct brcmf_fws_hanger_item items[BRCMF_FWS_HANGER_MAXITEMS]; | ||
407 | }; | ||
408 | |||
409 | struct brcmf_fws_macdesc_table { | ||
410 | struct brcmf_fws_mac_descriptor nodes[BRCMF_FWS_MAC_DESC_TABLE_SIZE]; | ||
411 | struct brcmf_fws_mac_descriptor iface[BRCMF_MAX_IFS]; | ||
412 | struct brcmf_fws_mac_descriptor other; | ||
413 | }; | ||
414 | |||
415 | struct brcmf_fws_info { | ||
416 | struct brcmf_pub *drvr; | ||
417 | struct brcmf_fws_stats stats; | ||
418 | struct brcmf_fws_hanger hanger; | ||
419 | enum brcmf_fws_fcmode fcmode; | ||
420 | struct brcmf_fws_macdesc_table desc; | ||
421 | struct workqueue_struct *fws_wq; | ||
422 | struct work_struct fws_dequeue_work; | ||
423 | u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT]; | ||
424 | int fifo_credit[BRCMF_FWS_FIFO_COUNT]; | ||
425 | int deq_node_pos[BRCMF_FWS_FIFO_COUNT]; | ||
426 | u32 fifo_credit_map; | ||
427 | u32 fifo_delay_map; | ||
428 | }; | ||
429 | |||
430 | /* | ||
431 | * brcmf_fws_prio2fifo - mapping from 802.1d priority to firmware fifo index. | ||
432 | */ | ||
433 | static const int brcmf_fws_prio2fifo[] = { | ||
434 | BRCMF_FWS_FIFO_AC_BE, | ||
435 | BRCMF_FWS_FIFO_AC_BK, | ||
436 | BRCMF_FWS_FIFO_AC_BK, | ||
437 | BRCMF_FWS_FIFO_AC_BE, | ||
438 | BRCMF_FWS_FIFO_AC_VI, | ||
439 | BRCMF_FWS_FIFO_AC_VI, | ||
440 | BRCMF_FWS_FIFO_AC_VO, | ||
441 | BRCMF_FWS_FIFO_AC_VO | ||
442 | }; | ||
443 | |||
444 | static int fcmode; | ||
445 | module_param(fcmode, int, S_IRUSR); | ||
446 | MODULE_PARM_DESC(fcmode, "mode of firmware signalled flow control"); | ||
447 | |||
448 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
449 | case BRCMF_FWS_TYPE_ ## name: \ | ||
450 | return len; | ||
451 | |||
452 | /** | ||
453 | * brcmf_fws_get_tlv_len() - returns defined length for given tlv id. | ||
454 | * | ||
455 | * @fws: firmware-signalling information. | ||
456 | * @id: identifier of the TLV. | ||
457 | * | ||
458 | * Return: the specified length for the given TLV; Otherwise -EINVAL. | ||
459 | */ | ||
460 | static int brcmf_fws_get_tlv_len(struct brcmf_fws_info *fws, | ||
461 | enum brcmf_fws_tlv_type id) | ||
462 | { | ||
463 | switch (id) { | ||
464 | BRCMF_FWS_TLV_DEFLIST | ||
465 | default: | ||
466 | fws->stats.tlv_invalid_type++; | ||
467 | break; | ||
468 | } | ||
469 | return -EINVAL; | ||
470 | } | ||
471 | #undef BRCMF_FWS_TLV_DEF | ||
472 | |||
473 | static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg) | ||
474 | { | ||
475 | u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX); | ||
476 | return ifidx == *(int *)arg; | ||
477 | } | ||
478 | |||
479 | static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q, | ||
480 | int ifidx) | ||
481 | { | ||
482 | bool (*matchfn)(struct sk_buff *, void *) = NULL; | ||
483 | struct sk_buff *skb; | ||
484 | int prec; | ||
485 | |||
486 | if (ifidx != -1) | ||
487 | matchfn = brcmf_fws_ifidx_match; | ||
488 | for (prec = 0; prec < q->num_prec; prec++) { | ||
489 | skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); | ||
490 | while (skb) { | ||
491 | brcmu_pkt_buf_free_skb(skb); | ||
492 | skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); | ||
493 | } | ||
494 | } | ||
495 | } | ||
496 | |||
497 | static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger) | ||
498 | { | ||
499 | int i; | ||
500 | |||
501 | brcmf_dbg(TRACE, "enter\n"); | ||
502 | memset(hanger, 0, sizeof(*hanger)); | ||
503 | for (i = 0; i < ARRAY_SIZE(hanger->items); i++) | ||
504 | hanger->items[i].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE; | ||
505 | } | ||
506 | |||
507 | static u32 brcmf_fws_hanger_get_free_slot(struct brcmf_fws_hanger *h) | ||
508 | { | ||
509 | u32 i; | ||
510 | |||
511 | brcmf_dbg(TRACE, "enter\n"); | ||
512 | i = (h->slot_pos + 1) % BRCMF_FWS_HANGER_MAXITEMS; | ||
513 | |||
514 | while (i != h->slot_pos) { | ||
515 | if (h->items[i].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) { | ||
516 | h->slot_pos = i; | ||
517 | goto done; | ||
518 | } | ||
519 | i++; | ||
520 | if (i == BRCMF_FWS_HANGER_MAXITEMS) | ||
521 | i = 0; | ||
522 | } | ||
523 | brcmf_err("all slots occupied\n"); | ||
524 | h->failed_slotfind++; | ||
525 | i = BRCMF_FWS_HANGER_MAXITEMS; | ||
526 | done: | ||
527 | brcmf_dbg(TRACE, "exit: %d\n", i); | ||
528 | return i; | ||
529 | } | ||
530 | |||
531 | static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h, | ||
532 | struct sk_buff *pkt, u32 slot_id) | ||
533 | { | ||
534 | brcmf_dbg(TRACE, "enter\n"); | ||
535 | if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) | ||
536 | return -ENOENT; | ||
537 | |||
538 | if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_FREE) { | ||
539 | brcmf_err("slot is not free\n"); | ||
540 | h->failed_to_push++; | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | |||
544 | h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE; | ||
545 | h->items[slot_id].pkt = pkt; | ||
546 | h->pushed++; | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h, | ||
551 | u32 slot_id, struct sk_buff **pktout, | ||
552 | bool remove_item) | ||
553 | { | ||
554 | brcmf_dbg(TRACE, "enter\n"); | ||
555 | if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) | ||
556 | return -ENOENT; | ||
557 | |||
558 | if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) { | ||
559 | brcmf_err("entry not in use\n"); | ||
560 | h->failed_to_pop++; | ||
561 | return -EINVAL; | ||
562 | } | ||
563 | |||
564 | *pktout = h->items[slot_id].pkt; | ||
565 | if (remove_item) { | ||
566 | h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE; | ||
567 | h->items[slot_id].pkt = NULL; | ||
568 | h->items[slot_id].gen = 0xff; | ||
569 | h->popped++; | ||
570 | } | ||
571 | return 0; | ||
572 | } | ||
573 | |||
574 | static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h, | ||
575 | u32 slot_id, u8 gen) | ||
576 | { | ||
577 | brcmf_dbg(TRACE, "enter\n"); | ||
578 | |||
579 | if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) | ||
580 | return -ENOENT; | ||
581 | |||
582 | h->items[slot_id].gen = gen; | ||
583 | |||
584 | if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_INUSE) { | ||
585 | brcmf_err("entry not in use\n"); | ||
586 | return -EINVAL; | ||
587 | } | ||
588 | |||
589 | h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED; | ||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | static int brcmf_fws_hanger_get_genbit(struct brcmf_fws_hanger *hanger, | ||
594 | struct sk_buff *pkt, u32 slot_id, | ||
595 | int *gen) | ||
596 | { | ||
597 | brcmf_dbg(TRACE, "enter\n"); | ||
598 | *gen = 0xff; | ||
599 | |||
600 | if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) | ||
601 | return -ENOENT; | ||
602 | |||
603 | if (hanger->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) { | ||
604 | brcmf_err("slot not in use\n"); | ||
605 | return -EINVAL; | ||
606 | } | ||
607 | |||
608 | *gen = hanger->items[slot_id].gen; | ||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws, | ||
613 | bool (*fn)(struct sk_buff *, void *), | ||
614 | int ifidx) | ||
615 | { | ||
616 | struct brcmf_fws_hanger *h = &fws->hanger; | ||
617 | struct sk_buff *skb; | ||
618 | int i; | ||
619 | enum brcmf_fws_hanger_item_state s; | ||
620 | |||
621 | brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); | ||
622 | for (i = 0; i < ARRAY_SIZE(h->items); i++) { | ||
623 | s = h->items[i].state; | ||
624 | if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE || | ||
625 | s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { | ||
626 | skb = h->items[i].pkt; | ||
627 | if (fn == NULL || fn(skb, &ifidx)) { | ||
628 | /* suppress packets freed from psq */ | ||
629 | if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE) | ||
630 | brcmu_pkt_buf_free_skb(skb); | ||
631 | h->items[i].state = | ||
632 | BRCMF_FWS_HANGER_ITEM_STATE_FREE; | ||
633 | } | ||
634 | } | ||
635 | } | ||
636 | } | ||
637 | |||
638 | static void brcmf_fws_init_mac_descriptor(struct brcmf_fws_mac_descriptor *desc, | ||
639 | u8 *addr, u8 ifidx) | ||
640 | { | ||
641 | brcmf_dbg(TRACE, | ||
642 | "enter: desc %p ea=%pM, ifidx=%u\n", desc, addr, ifidx); | ||
643 | desc->occupied = 1; | ||
644 | desc->state = BRCMF_FWS_STATE_OPEN; | ||
645 | desc->requested_credit = 0; | ||
646 | /* depending on use may need ifp->bssidx instead */ | ||
647 | desc->interface_id = ifidx; | ||
648 | desc->ac_bitmap = 0xff; /* update this when handling APSD */ | ||
649 | if (addr) | ||
650 | memcpy(&desc->ea[0], addr, ETH_ALEN); | ||
651 | } | ||
652 | |||
653 | static | ||
654 | void brcmf_fws_clear_mac_descriptor(struct brcmf_fws_mac_descriptor *desc) | ||
655 | { | ||
656 | brcmf_dbg(TRACE, | ||
657 | "enter: ea=%pM, ifidx=%u\n", desc->ea, desc->interface_id); | ||
658 | desc->occupied = 0; | ||
659 | desc->state = BRCMF_FWS_STATE_CLOSE; | ||
660 | desc->requested_credit = 0; | ||
661 | } | ||
662 | |||
663 | static struct brcmf_fws_mac_descriptor * | ||
664 | brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea) | ||
665 | { | ||
666 | struct brcmf_fws_mac_descriptor *entry; | ||
667 | int i; | ||
668 | |||
669 | brcmf_dbg(TRACE, "enter: ea=%pM\n", ea); | ||
670 | if (ea == NULL) | ||
671 | return ERR_PTR(-EINVAL); | ||
672 | |||
673 | entry = &fws->desc.nodes[0]; | ||
674 | for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++) { | ||
675 | if (entry->occupied && !memcmp(entry->ea, ea, ETH_ALEN)) | ||
676 | return entry; | ||
677 | entry++; | ||
678 | } | ||
679 | |||
680 | return ERR_PTR(-ENOENT); | ||
681 | } | ||
682 | |||
683 | static struct brcmf_fws_mac_descriptor* | ||
684 | brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp, | ||
685 | u8 *da) | ||
686 | { | ||
687 | struct brcmf_fws_mac_descriptor *entry = &fws->desc.other; | ||
688 | bool multicast; | ||
689 | enum nl80211_iftype iftype; | ||
690 | |||
691 | brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); | ||
692 | |||
693 | multicast = is_multicast_ether_addr(da); | ||
694 | iftype = brcmf_cfg80211_get_iftype(ifp); | ||
695 | |||
696 | /* Multicast destination and P2P clients get the interface entry. | ||
697 | * STA gets the interface entry if there is no exact match. For | ||
698 | * example, TDLS destinations have their own entry. | ||
699 | */ | ||
700 | entry = NULL; | ||
701 | if ((multicast || iftype == NL80211_IFTYPE_STATION || | ||
702 | iftype == NL80211_IFTYPE_P2P_CLIENT) && ifp->fws_desc) | ||
703 | entry = ifp->fws_desc; | ||
704 | |||
705 | if (entry != NULL && iftype != NL80211_IFTYPE_STATION) | ||
706 | goto done; | ||
707 | |||
708 | entry = brcmf_fws_mac_descriptor_lookup(fws, da); | ||
709 | if (IS_ERR(entry)) | ||
710 | entry = &fws->desc.other; | ||
711 | |||
712 | done: | ||
713 | brcmf_dbg(TRACE, "exit: entry=%p\n", entry); | ||
714 | return entry; | ||
715 | } | ||
716 | |||
717 | static bool brcmf_fws_mac_desc_closed(struct brcmf_fws_mac_descriptor *entry, | ||
718 | int fifo) | ||
719 | { | ||
720 | bool closed; | ||
721 | |||
722 | /* an entry is closed when the state is closed and | ||
723 | * the firmware did not request anything. | ||
724 | */ | ||
725 | closed = entry->state == BRCMF_FWS_STATE_CLOSE && | ||
726 | !entry->requested_credit && !entry->requested_packet; | ||
727 | |||
728 | /* Or firmware does not allow traffic for given fifo */ | ||
729 | return closed || !(entry->ac_bitmap & BIT(fifo)); | ||
730 | } | ||
731 | |||
732 | static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_info *fws, | ||
733 | struct brcmf_fws_mac_descriptor *entry, | ||
734 | int ifidx) | ||
735 | { | ||
736 | brcmf_dbg(TRACE, "enter: entry=(ea=%pM, ifid=%d), ifidx=%d\n", | ||
737 | entry->ea, entry->interface_id, ifidx); | ||
738 | if (entry->occupied && (ifidx == -1 || ifidx == entry->interface_id)) { | ||
739 | brcmf_dbg(TRACE, "flush psq: ifidx=%d, qlen=%d\n", | ||
740 | ifidx, entry->psq.len); | ||
741 | brcmf_fws_psq_flush(fws, &entry->psq, ifidx); | ||
742 | entry->occupied = !!(entry->psq.len); | ||
743 | } | ||
744 | } | ||
745 | |||
746 | static void brcmf_fws_bus_txq_cleanup(struct brcmf_fws_info *fws, | ||
747 | bool (*fn)(struct sk_buff *, void *), | ||
748 | int ifidx) | ||
749 | { | ||
750 | struct brcmf_fws_hanger_item *hi; | ||
751 | struct pktq *txq; | ||
752 | struct sk_buff *skb; | ||
753 | int prec; | ||
754 | u32 hslot; | ||
755 | |||
756 | brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); | ||
757 | txq = brcmf_bus_gettxq(fws->drvr->bus_if); | ||
758 | if (IS_ERR(txq)) { | ||
759 | brcmf_dbg(TRACE, "no txq to clean up\n"); | ||
760 | return; | ||
761 | } | ||
762 | |||
763 | for (prec = 0; prec < txq->num_prec; prec++) { | ||
764 | skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx); | ||
765 | while (skb) { | ||
766 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | ||
767 | hi = &fws->hanger.items[hslot]; | ||
768 | WARN_ON(skb != hi->pkt); | ||
769 | hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE; | ||
770 | brcmu_pkt_buf_free_skb(skb); | ||
771 | skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx); | ||
772 | } | ||
773 | } | ||
774 | } | ||
775 | |||
776 | static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx) | ||
777 | { | ||
778 | int i; | ||
779 | struct brcmf_fws_mac_descriptor *table; | ||
780 | bool (*matchfn)(struct sk_buff *, void *) = NULL; | ||
781 | |||
782 | brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); | ||
783 | if (fws == NULL) | ||
784 | return; | ||
785 | |||
786 | if (ifidx != -1) | ||
787 | matchfn = brcmf_fws_ifidx_match; | ||
788 | |||
789 | /* cleanup individual nodes */ | ||
790 | table = &fws->desc.nodes[0]; | ||
791 | for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++) | ||
792 | brcmf_fws_mac_desc_cleanup(fws, &table[i], ifidx); | ||
793 | |||
794 | brcmf_fws_mac_desc_cleanup(fws, &fws->desc.other, ifidx); | ||
795 | brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx); | ||
796 | brcmf_fws_hanger_cleanup(fws, matchfn, ifidx); | ||
797 | } | ||
798 | |||
799 | static void brcmf_fws_tim_update(struct brcmf_fws_info *ctx, | ||
800 | struct brcmf_fws_mac_descriptor *entry, | ||
801 | int prec) | ||
802 | { | ||
803 | brcmf_dbg(TRACE, "enter: ea=%pM\n", entry->ea); | ||
804 | if (entry->state == BRCMF_FWS_STATE_CLOSE) { | ||
805 | /* check delayedQ and suppressQ in one call using bitmap */ | ||
806 | if (brcmu_pktq_mlen(&entry->psq, 3 << (prec * 2)) == 0) | ||
807 | entry->traffic_pending_bmp = | ||
808 | entry->traffic_pending_bmp & ~NBITVAL(prec); | ||
809 | else | ||
810 | entry->traffic_pending_bmp = | ||
811 | entry->traffic_pending_bmp | NBITVAL(prec); | ||
812 | } | ||
813 | /* request a TIM update to firmware at the next piggyback opportunity */ | ||
814 | if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp) | ||
815 | entry->send_tim_signal = true; | ||
816 | } | ||
817 | |||
818 | static void | ||
819 | brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq, | ||
820 | u8 if_id) | ||
821 | { | ||
822 | struct brcmf_if *ifp = fws->drvr->iflist[if_id]; | ||
823 | |||
824 | brcmf_dbg(TRACE, | ||
825 | "enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx); | ||
826 | if (WARN_ON(!ifp)) | ||
827 | return; | ||
828 | |||
829 | if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) && | ||
830 | pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER) | ||
831 | brcmf_txflowblock_if(ifp, | ||
832 | BRCMF_NETIF_STOP_REASON_FWS_FC, false); | ||
833 | if (!(ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) && | ||
834 | pq->len >= BRCMF_FWS_FLOWCONTROL_HIWATER) | ||
835 | brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FWS_FC, true); | ||
836 | return; | ||
837 | } | ||
838 | |||
839 | static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi) | ||
840 | { | ||
841 | brcmf_dbg(CTL, "rssi %d\n", rssi); | ||
842 | return 0; | ||
843 | } | ||
844 | |||
845 | static | ||
846 | int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) | ||
847 | { | ||
848 | struct brcmf_fws_mac_descriptor *entry, *existing; | ||
849 | u8 mac_handle; | ||
850 | u8 ifidx; | ||
851 | u8 *addr; | ||
852 | |||
853 | mac_handle = *data++; | ||
854 | ifidx = *data++; | ||
855 | addr = data; | ||
856 | |||
857 | entry = &fws->desc.nodes[mac_handle & 0x1F]; | ||
858 | if (type == BRCMF_FWS_TYPE_MACDESC_DEL) { | ||
859 | brcmf_dbg(TRACE, "deleting mac %pM idx %d\n", addr, ifidx); | ||
860 | if (entry->occupied) | ||
861 | brcmf_fws_clear_mac_descriptor(entry); | ||
862 | else | ||
863 | fws->stats.mac_update_failed++; | ||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | brcmf_dbg(TRACE, | ||
868 | "add mac %pM handle %u idx %d\n", addr, mac_handle, ifidx); | ||
869 | existing = brcmf_fws_mac_descriptor_lookup(fws, addr); | ||
870 | if (IS_ERR(existing)) { | ||
871 | if (!entry->occupied) { | ||
872 | entry->mac_handle = mac_handle; | ||
873 | brcmf_fws_init_mac_descriptor(entry, addr, ifidx); | ||
874 | brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, | ||
875 | BRCMF_FWS_PSQ_LEN); | ||
876 | } else { | ||
877 | fws->stats.mac_update_failed++; | ||
878 | } | ||
879 | } else { | ||
880 | if (entry != existing) { | ||
881 | brcmf_dbg(TRACE, "relocate mac\n"); | ||
882 | memcpy(entry, existing, | ||
883 | offsetof(struct brcmf_fws_mac_descriptor, psq)); | ||
884 | entry->mac_handle = mac_handle; | ||
885 | brcmf_fws_clear_mac_descriptor(existing); | ||
886 | } else { | ||
887 | brcmf_dbg(TRACE, "use existing\n"); | ||
888 | WARN_ON(entry->mac_handle != mac_handle); | ||
889 | /* TODO: what should we do here: continue, reinit, .. */ | ||
890 | } | ||
891 | } | ||
892 | return 0; | ||
893 | } | ||
894 | |||
895 | static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws, | ||
896 | u8 type, u8 *data) | ||
897 | { | ||
898 | struct brcmf_fws_mac_descriptor *entry; | ||
899 | u8 mac_handle; | ||
900 | int i; | ||
901 | |||
902 | mac_handle = data[0]; | ||
903 | entry = &fws->desc.nodes[mac_handle & 0x1F]; | ||
904 | if (!entry->occupied) { | ||
905 | fws->stats.mac_ps_update_failed++; | ||
906 | return -ESRCH; | ||
907 | } | ||
908 | |||
909 | /* a state update should wipe old credits? */ | ||
910 | entry->requested_credit = 0; | ||
911 | if (type == BRCMF_FWS_TYPE_MAC_OPEN) { | ||
912 | entry->state = BRCMF_FWS_STATE_OPEN; | ||
913 | } else { | ||
914 | entry->state = BRCMF_FWS_STATE_CLOSE; | ||
915 | for (i = BRCMF_FWS_FIFO_AC_BE; i < NL80211_NUM_ACS; i++) | ||
916 | brcmf_fws_tim_update(fws, entry, i); | ||
917 | } | ||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws, | ||
922 | u8 type, u8 *data) | ||
923 | { | ||
924 | struct brcmf_fws_mac_descriptor *entry; | ||
925 | u8 ifidx; | ||
926 | int ret; | ||
927 | |||
928 | ifidx = data[0]; | ||
929 | |||
930 | brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); | ||
931 | if (ifidx >= BRCMF_MAX_IFS) { | ||
932 | ret = -ERANGE; | ||
933 | goto fail; | ||
934 | } | ||
935 | |||
936 | entry = &fws->desc.iface[ifidx]; | ||
937 | if (!entry->occupied) { | ||
938 | ret = -ESRCH; | ||
939 | goto fail; | ||
940 | } | ||
941 | |||
942 | switch (type) { | ||
943 | case BRCMF_FWS_TYPE_INTERFACE_OPEN: | ||
944 | entry->state = BRCMF_FWS_STATE_OPEN; | ||
945 | return 0; | ||
946 | case BRCMF_FWS_TYPE_INTERFACE_CLOSE: | ||
947 | entry->state = BRCMF_FWS_STATE_CLOSE; | ||
948 | return 0; | ||
949 | default: | ||
950 | ret = -EINVAL; | ||
951 | break; | ||
952 | } | ||
953 | fail: | ||
954 | fws->stats.if_update_failed++; | ||
955 | return ret; | ||
956 | } | ||
957 | |||
958 | static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type, | ||
959 | u8 *data) | ||
960 | { | ||
961 | struct brcmf_fws_mac_descriptor *entry; | ||
962 | |||
963 | entry = &fws->desc.nodes[data[1] & 0x1F]; | ||
964 | if (!entry->occupied) { | ||
965 | if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT) | ||
966 | fws->stats.credit_request_failed++; | ||
967 | else | ||
968 | fws->stats.packet_request_failed++; | ||
969 | return -ESRCH; | ||
970 | } | ||
971 | |||
972 | if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT) | ||
973 | entry->requested_credit = data[0]; | ||
974 | else | ||
975 | entry->requested_packet = data[0]; | ||
976 | |||
977 | entry->ac_bitmap = data[2]; | ||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | static void brcmf_fws_return_credits(struct brcmf_fws_info *fws, | ||
982 | u8 fifo, u8 credits) | ||
983 | { | ||
984 | if (!credits) | ||
985 | return; | ||
986 | |||
987 | fws->fifo_credit_map |= 1 << fifo; | ||
988 | fws->fifo_credit[fifo] += credits; | ||
989 | } | ||
990 | |||
991 | static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws) | ||
992 | { | ||
993 | /* only schedule dequeue when there are credits for delayed traffic */ | ||
994 | if (fws->fifo_credit_map & fws->fifo_delay_map) | ||
995 | queue_work(fws->fws_wq, &fws->fws_dequeue_work); | ||
996 | } | ||
997 | |||
998 | static void brcmf_skb_pick_up_credit(struct brcmf_fws_info *fws, int fifo, | ||
999 | struct sk_buff *p) | ||
1000 | { | ||
1001 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(p)->mac; | ||
1002 | |||
1003 | if (brcmf_skbcb(p)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) { | ||
1004 | if (fws->fcmode != BRCMF_FWS_FCMODE_IMPLIED_CREDIT) | ||
1005 | return; | ||
1006 | brcmf_fws_return_credits(fws, fifo, 1); | ||
1007 | } else { | ||
1008 | /* | ||
1009 | * if this packet did not count against FIFO credit, it | ||
1010 | * must have taken a requested_credit from the destination | ||
1011 | * entry (for pspoll etc.) | ||
1012 | */ | ||
1013 | if (!brcmf_skb_if_flags_get_field(p, REQUESTED)) | ||
1014 | entry->requested_credit++; | ||
1015 | } | ||
1016 | brcmf_fws_schedule_deq(fws); | ||
1017 | } | ||
1018 | |||
1019 | static int brcmf_fws_enq(struct brcmf_fws_info *fws, | ||
1020 | enum brcmf_fws_skb_state state, int fifo, | ||
1021 | struct sk_buff *p) | ||
1022 | { | ||
1023 | int prec = 2 * fifo; | ||
1024 | u32 *qfull_stat = &fws->stats.delayq_full_error; | ||
1025 | |||
1026 | struct brcmf_fws_mac_descriptor *entry; | ||
1027 | |||
1028 | entry = brcmf_skbcb(p)->mac; | ||
1029 | if (entry == NULL) { | ||
1030 | brcmf_err("no mac descriptor found for skb %p\n", p); | ||
1031 | return -ENOENT; | ||
1032 | } | ||
1033 | |||
1034 | brcmf_dbg(TRACE, "enter: ea=%pM, qlen=%d\n", entry->ea, entry->psq.len); | ||
1035 | if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { | ||
1036 | prec += 1; | ||
1037 | qfull_stat = &fws->stats.supprq_full_error; | ||
1038 | } | ||
1039 | |||
1040 | if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) { | ||
1041 | *qfull_stat += 1; | ||
1042 | return -ENFILE; | ||
1043 | } | ||
1044 | |||
1045 | /* increment total enqueued packet count */ | ||
1046 | fws->fifo_delay_map |= 1 << fifo; | ||
1047 | fws->fifo_enqpkt[fifo]++; | ||
1048 | |||
1049 | /* update the sk_buff state */ | ||
1050 | brcmf_skbcb(p)->state = state; | ||
1051 | if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) | ||
1052 | entry->suppress_count++; | ||
1053 | |||
1054 | /* | ||
1055 | * A packet has been pushed so update traffic | ||
1056 | * availability bitmap, if applicable | ||
1057 | */ | ||
1058 | brcmf_fws_tim_update(fws, entry, fifo); | ||
1059 | brcmf_fws_flow_control_check(fws, &entry->psq, | ||
1060 | brcmf_skb_if_flags_get_field(p, INDEX)); | ||
1061 | return 0; | ||
1062 | } | ||
1063 | |||
1064 | static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) | ||
1065 | { | ||
1066 | struct brcmf_fws_mac_descriptor *table; | ||
1067 | struct brcmf_fws_mac_descriptor *entry; | ||
1068 | struct sk_buff *p; | ||
1069 | int use_credit = 1; | ||
1070 | int num_nodes; | ||
1071 | int node_pos; | ||
1072 | int prec_out; | ||
1073 | int pmsk = 3; | ||
1074 | int i; | ||
1075 | |||
1076 | table = (struct brcmf_fws_mac_descriptor *)&fws->desc; | ||
1077 | num_nodes = sizeof(fws->desc) / sizeof(struct brcmf_fws_mac_descriptor); | ||
1078 | node_pos = fws->deq_node_pos[fifo]; | ||
1079 | |||
1080 | for (i = 0; i < num_nodes; i++) { | ||
1081 | entry = &table[(node_pos + i) % num_nodes]; | ||
1082 | if (!entry->occupied || brcmf_fws_mac_desc_closed(entry, fifo)) | ||
1083 | continue; | ||
1084 | |||
1085 | if (entry->suppressed) | ||
1086 | pmsk = 2; | ||
1087 | p = brcmu_pktq_mdeq(&entry->psq, pmsk << (fifo * 2), &prec_out); | ||
1088 | if (p == NULL) { | ||
1089 | if (entry->suppressed) { | ||
1090 | if (entry->suppr_transit_count > | ||
1091 | entry->suppress_count) | ||
1092 | return NULL; | ||
1093 | entry->suppressed = false; | ||
1094 | p = brcmu_pktq_mdeq(&entry->psq, | ||
1095 | 1 << (fifo * 2), &prec_out); | ||
1096 | } | ||
1097 | } | ||
1098 | if (p == NULL) | ||
1099 | continue; | ||
1100 | |||
1101 | /* did the packet come from suppress sub-queue? */ | ||
1102 | if (entry->requested_credit > 0) { | ||
1103 | entry->requested_credit--; | ||
1104 | /* | ||
1105 | * if the packet was pulled out while destination is in | ||
1106 | * closed state but had a non-zero packets requested, | ||
1107 | * then this should not count against the FIFO credit. | ||
1108 | * That is due to the fact that the firmware will | ||
1109 | * most likely hold onto this packet until a suitable | ||
1110 | * time later to push it to the appropriate AC FIFO. | ||
1111 | */ | ||
1112 | if (entry->state == BRCMF_FWS_STATE_CLOSE) | ||
1113 | use_credit = 0; | ||
1114 | } else if (entry->requested_packet > 0) { | ||
1115 | entry->requested_packet--; | ||
1116 | brcmf_skb_if_flags_set_field(p, REQUESTED, 1); | ||
1117 | if (entry->state == BRCMF_FWS_STATE_CLOSE) | ||
1118 | use_credit = 0; | ||
1119 | } | ||
1120 | brcmf_skb_if_flags_set_field(p, CREDITCHECK, use_credit); | ||
1121 | |||
1122 | /* move dequeue position to ensure fair round-robin */ | ||
1123 | fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes; | ||
1124 | brcmf_fws_flow_control_check(fws, &entry->psq, | ||
1125 | brcmf_skb_if_flags_get_field(p, | ||
1126 | INDEX) | ||
1127 | ); | ||
1128 | /* | ||
1129 | * A packet has been picked up, update traffic | ||
1130 | * availability bitmap, if applicable | ||
1131 | */ | ||
1132 | brcmf_fws_tim_update(fws, entry, fifo); | ||
1133 | |||
1134 | /* | ||
1135 | * decrement total enqueued fifo packets and | ||
1136 | * clear delay bitmap if done. | ||
1137 | */ | ||
1138 | fws->fifo_enqpkt[fifo]--; | ||
1139 | if (fws->fifo_enqpkt[fifo] == 0) | ||
1140 | fws->fifo_delay_map &= ~(1 << fifo); | ||
1141 | goto done; | ||
1142 | } | ||
1143 | p = NULL; | ||
1144 | done: | ||
1145 | brcmf_dbg(TRACE, "exit: fifo %d skb %p\n", fifo, p); | ||
1146 | return p; | ||
1147 | } | ||
1148 | |||
1149 | static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | ||
1150 | struct sk_buff *skb, u32 genbit) | ||
1151 | { | ||
1152 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; | ||
1153 | u32 hslot; | ||
1154 | int ret; | ||
1155 | |||
1156 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | ||
1157 | |||
1158 | /* this packet was suppressed */ | ||
1159 | if (!entry->suppressed || entry->generation != genbit) { | ||
1160 | entry->suppressed = true; | ||
1161 | entry->suppress_count = brcmu_pktq_mlen(&entry->psq, | ||
1162 | 1 << (fifo * 2 + 1)); | ||
1163 | entry->suppr_transit_count = entry->transit_count; | ||
1164 | } | ||
1165 | |||
1166 | entry->generation = genbit; | ||
1167 | |||
1168 | ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb); | ||
1169 | if (ret != 0) { | ||
1170 | /* suppress q is full, drop this packet */ | ||
1171 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, | ||
1172 | true); | ||
1173 | } else { | ||
1174 | /* | ||
1175 | * Mark suppressed to avoid a double free during | ||
1176 | * wlfc cleanup | ||
1177 | */ | ||
1178 | brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot, | ||
1179 | genbit); | ||
1180 | entry->suppress_count++; | ||
1181 | } | ||
1182 | |||
1183 | return ret; | ||
1184 | } | ||
1185 | |||
1186 | static int | ||
1187 | brcmf_fws_txstatus_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, | ||
1188 | u32 genbit) | ||
1189 | { | ||
1190 | u32 fifo; | ||
1191 | int ret; | ||
1192 | bool remove_from_hanger = true; | ||
1193 | struct sk_buff *skb; | ||
1194 | struct brcmf_fws_mac_descriptor *entry = NULL; | ||
1195 | |||
1196 | brcmf_dbg(TRACE, "status: flags=0x%X, hslot=%d\n", | ||
1197 | flags, hslot); | ||
1198 | |||
1199 | if (flags == BRCMF_FWS_TXSTATUS_DISCARD) | ||
1200 | fws->stats.txs_discard++; | ||
1201 | else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) { | ||
1202 | fws->stats.txs_supp_core++; | ||
1203 | remove_from_hanger = false; | ||
1204 | } else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) { | ||
1205 | fws->stats.txs_supp_ps++; | ||
1206 | remove_from_hanger = false; | ||
1207 | } else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED) | ||
1208 | fws->stats.txs_tossed++; | ||
1209 | else | ||
1210 | brcmf_err("unexpected txstatus\n"); | ||
1211 | |||
1212 | ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, | ||
1213 | remove_from_hanger); | ||
1214 | if (ret != 0) { | ||
1215 | brcmf_err("no packet in hanger slot: hslot=%d\n", hslot); | ||
1216 | return ret; | ||
1217 | } | ||
1218 | |||
1219 | entry = brcmf_skbcb(skb)->mac; | ||
1220 | if (WARN_ON(!entry)) { | ||
1221 | brcmu_pkt_buf_free_skb(skb); | ||
1222 | return -EINVAL; | ||
1223 | } | ||
1224 | |||
1225 | /* pick up the implicit credit from this packet */ | ||
1226 | fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); | ||
1227 | brcmf_skb_pick_up_credit(fws, fifo, skb); | ||
1228 | |||
1229 | if (!remove_from_hanger) | ||
1230 | ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit); | ||
1231 | |||
1232 | if (remove_from_hanger || ret) { | ||
1233 | entry->transit_count--; | ||
1234 | if (entry->suppressed) | ||
1235 | entry->suppr_transit_count--; | ||
1236 | |||
1237 | brcmf_txfinalize(fws->drvr, skb, true); | ||
1238 | } | ||
1239 | return 0; | ||
1240 | } | ||
1241 | |||
1242 | static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, | ||
1243 | u8 *data) | ||
1244 | { | ||
1245 | int i; | ||
1246 | |||
1247 | if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) { | ||
1248 | brcmf_dbg(INFO, "ignored\n"); | ||
1249 | return 0; | ||
1250 | } | ||
1251 | |||
1252 | brcmf_dbg(TRACE, "enter: data %pM\n", data); | ||
1253 | for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++) | ||
1254 | brcmf_fws_return_credits(fws, i, data[i]); | ||
1255 | |||
1256 | brcmf_dbg(INFO, "map: credit %x delay %x\n", fws->fifo_credit_map, | ||
1257 | fws->fifo_delay_map); | ||
1258 | brcmf_fws_schedule_deq(fws); | ||
1259 | return 0; | ||
1260 | } | ||
1261 | |||
1262 | static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) | ||
1263 | { | ||
1264 | __le32 status_le; | ||
1265 | u32 status; | ||
1266 | u32 hslot; | ||
1267 | u32 genbit; | ||
1268 | u8 flags; | ||
1269 | |||
1270 | fws->stats.txs_indicate++; | ||
1271 | memcpy(&status_le, data, sizeof(status_le)); | ||
1272 | status = le32_to_cpu(status_le); | ||
1273 | flags = brcmf_txstatus_get_field(status, FLAGS); | ||
1274 | hslot = brcmf_txstatus_get_field(status, HSLOT); | ||
1275 | genbit = brcmf_txstatus_get_field(status, GENERATION); | ||
1276 | |||
1277 | return brcmf_fws_txstatus_process(fws, flags, hslot, genbit); | ||
1278 | } | ||
1279 | |||
1280 | static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) | ||
1281 | { | ||
1282 | __le32 timestamp; | ||
1283 | |||
1284 | memcpy(×tamp, &data[2], sizeof(timestamp)); | ||
1285 | brcmf_dbg(INFO, "received: seq %d, timestamp %d\n", data[1], | ||
1286 | le32_to_cpu(timestamp)); | ||
1287 | return 0; | ||
1288 | } | ||
1289 | |||
1290 | /* using macro so sparse checking does not complain | ||
1291 | * about locking imbalance. | ||
1292 | */ | ||
1293 | #define brcmf_fws_lock(drvr, flags) \ | ||
1294 | do { \ | ||
1295 | flags = 0; \ | ||
1296 | spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \ | ||
1297 | } while (0) | ||
1298 | |||
1299 | /* using macro so sparse checking does not complain | ||
1300 | * about locking imbalance. | ||
1301 | */ | ||
1302 | #define brcmf_fws_unlock(drvr, flags) \ | ||
1303 | spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags)) | ||
1304 | |||
1305 | static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, | ||
1306 | const struct brcmf_event_msg *e, | ||
1307 | void *data) | ||
1308 | { | ||
1309 | struct brcmf_fws_info *fws = ifp->drvr->fws; | ||
1310 | int i; | ||
1311 | ulong flags; | ||
1312 | u8 *credits = data; | ||
1313 | |||
1314 | if (e->datalen < BRCMF_FWS_FIFO_COUNT) { | ||
1315 | brcmf_err("event payload too small (%d)\n", e->datalen); | ||
1316 | return -EINVAL; | ||
1317 | } | ||
1318 | |||
1319 | brcmf_dbg(TRACE, "enter: credits %pM\n", credits); | ||
1320 | brcmf_fws_lock(ifp->drvr, flags); | ||
1321 | for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) { | ||
1322 | if (*credits) | ||
1323 | fws->fifo_credit_map |= 1 << i; | ||
1324 | else | ||
1325 | fws->fifo_credit_map &= ~(1 << i); | ||
1326 | fws->fifo_credit[i] = *credits++; | ||
1327 | } | ||
1328 | brcmf_fws_schedule_deq(fws); | ||
1329 | brcmf_fws_unlock(ifp->drvr, flags); | ||
1330 | return 0; | ||
1331 | } | ||
1332 | |||
1333 | int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | ||
1334 | struct sk_buff *skb) | ||
1335 | { | ||
1336 | struct brcmf_fws_info *fws = drvr->fws; | ||
1337 | ulong flags; | ||
1338 | u8 *signal_data; | ||
1339 | s16 data_len; | ||
1340 | u8 type; | ||
1341 | u8 len; | ||
1342 | u8 *data; | ||
1343 | |||
1344 | brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n", | ||
1345 | ifidx, skb->len, signal_len); | ||
1346 | |||
1347 | WARN_ON(signal_len > skb->len); | ||
1348 | |||
1349 | /* if flow control disabled, skip to packet data and leave */ | ||
1350 | if (!signal_len || !drvr->fw_signals) { | ||
1351 | skb_pull(skb, signal_len); | ||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1355 | /* lock during tlv parsing */ | ||
1356 | brcmf_fws_lock(drvr, flags); | ||
1357 | |||
1358 | fws->stats.header_pulls++; | ||
1359 | data_len = signal_len; | ||
1360 | signal_data = skb->data; | ||
1361 | |||
1362 | while (data_len > 0) { | ||
1363 | /* extract tlv info */ | ||
1364 | type = signal_data[0]; | ||
1365 | |||
1366 | /* FILLER type is actually not a TLV, but | ||
1367 | * a single byte that can be skipped. | ||
1368 | */ | ||
1369 | if (type == BRCMF_FWS_TYPE_FILLER) { | ||
1370 | signal_data += 1; | ||
1371 | data_len -= 1; | ||
1372 | continue; | ||
1373 | } | ||
1374 | len = signal_data[1]; | ||
1375 | data = signal_data + 2; | ||
1376 | |||
1377 | brcmf_dbg(INFO, "tlv type=%d (%s), len=%d, data[0]=%d\n", type, | ||
1378 | brcmf_fws_get_tlv_name(type), len, *data); | ||
1379 | |||
1380 | /* abort parsing when length invalid */ | ||
1381 | if (data_len < len + 2) | ||
1382 | break; | ||
1383 | |||
1384 | if (len != brcmf_fws_get_tlv_len(fws, type)) | ||
1385 | break; | ||
1386 | |||
1387 | switch (type) { | ||
1388 | case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS: | ||
1389 | case BRCMF_FWS_TYPE_COMP_TXSTATUS: | ||
1390 | break; | ||
1391 | case BRCMF_FWS_TYPE_MACDESC_ADD: | ||
1392 | case BRCMF_FWS_TYPE_MACDESC_DEL: | ||
1393 | brcmf_fws_macdesc_indicate(fws, type, data); | ||
1394 | break; | ||
1395 | case BRCMF_FWS_TYPE_MAC_OPEN: | ||
1396 | case BRCMF_FWS_TYPE_MAC_CLOSE: | ||
1397 | brcmf_fws_macdesc_state_indicate(fws, type, data); | ||
1398 | break; | ||
1399 | case BRCMF_FWS_TYPE_INTERFACE_OPEN: | ||
1400 | case BRCMF_FWS_TYPE_INTERFACE_CLOSE: | ||
1401 | brcmf_fws_interface_state_indicate(fws, type, data); | ||
1402 | break; | ||
1403 | case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT: | ||
1404 | case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET: | ||
1405 | brcmf_fws_request_indicate(fws, type, data); | ||
1406 | break; | ||
1407 | case BRCMF_FWS_TYPE_TXSTATUS: | ||
1408 | brcmf_fws_txstatus_indicate(fws, data); | ||
1409 | break; | ||
1410 | case BRCMF_FWS_TYPE_FIFO_CREDITBACK: | ||
1411 | brcmf_fws_fifocreditback_indicate(fws, data); | ||
1412 | break; | ||
1413 | case BRCMF_FWS_TYPE_RSSI: | ||
1414 | brcmf_fws_rssi_indicate(fws, *data); | ||
1415 | break; | ||
1416 | case BRCMF_FWS_TYPE_TRANS_ID: | ||
1417 | brcmf_fws_dbg_seqnum_check(fws, data); | ||
1418 | break; | ||
1419 | case BRCMF_FWS_TYPE_PKTTAG: | ||
1420 | case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP: | ||
1421 | default: | ||
1422 | fws->stats.tlv_invalid_type++; | ||
1423 | break; | ||
1424 | } | ||
1425 | |||
1426 | signal_data += len + 2; | ||
1427 | data_len -= len + 2; | ||
1428 | } | ||
1429 | |||
1430 | if (data_len != 0) | ||
1431 | fws->stats.tlv_parse_failed++; | ||
1432 | |||
1433 | /* signalling processing result does | ||
1434 | * not affect the actual ethernet packet. | ||
1435 | */ | ||
1436 | skb_pull(skb, signal_len); | ||
1437 | |||
1438 | /* this may be a signal-only packet | ||
1439 | */ | ||
1440 | if (skb->len == 0) | ||
1441 | fws->stats.header_only_pkt++; | ||
1442 | |||
1443 | brcmf_fws_unlock(drvr, flags); | ||
1444 | return 0; | ||
1445 | } | ||
1446 | |||
1447 | static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) | ||
1448 | { | ||
1449 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; | ||
1450 | u8 *wlh; | ||
1451 | u16 data_offset = 0; | ||
1452 | u8 fillers; | ||
1453 | __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod); | ||
1454 | |||
1455 | brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u, pkttag=0x%08X\n", | ||
1456 | entry->ea, entry->interface_id, le32_to_cpu(pkttag)); | ||
1457 | if (entry->send_tim_signal) | ||
1458 | data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; | ||
1459 | |||
1460 | /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ | ||
1461 | data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN; | ||
1462 | fillers = round_up(data_offset, 4) - data_offset; | ||
1463 | data_offset += fillers; | ||
1464 | |||
1465 | skb_push(skb, data_offset); | ||
1466 | wlh = skb->data; | ||
1467 | |||
1468 | wlh[0] = BRCMF_FWS_TYPE_PKTTAG; | ||
1469 | wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN; | ||
1470 | memcpy(&wlh[2], &pkttag, sizeof(pkttag)); | ||
1471 | wlh += BRCMF_FWS_TYPE_PKTTAG_LEN + 2; | ||
1472 | |||
1473 | if (entry->send_tim_signal) { | ||
1474 | entry->send_tim_signal = 0; | ||
1475 | wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP; | ||
1476 | wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; | ||
1477 | wlh[2] = entry->mac_handle; | ||
1478 | wlh[3] = entry->traffic_pending_bmp; | ||
1479 | wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2; | ||
1480 | entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; | ||
1481 | } | ||
1482 | if (fillers) | ||
1483 | memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers); | ||
1484 | |||
1485 | brcmf_proto_hdrpush(fws->drvr, brcmf_skb_if_flags_get_field(skb, INDEX), | ||
1486 | data_offset >> 2, skb); | ||
1487 | return 0; | ||
1488 | } | ||
1489 | |||
1490 | static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, | ||
1491 | struct sk_buff *p) | ||
1492 | { | ||
1493 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); | ||
1494 | struct brcmf_fws_mac_descriptor *entry = skcb->mac; | ||
1495 | int rc = 0; | ||
1496 | bool header_needed; | ||
1497 | int hslot = BRCMF_FWS_HANGER_MAXITEMS; | ||
1498 | u8 free_ctr; | ||
1499 | u8 ifidx; | ||
1500 | u8 flags; | ||
1501 | |||
1502 | header_needed = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED; | ||
1503 | |||
1504 | if (header_needed) { | ||
1505 | /* obtaining free slot may fail, but that will be caught | ||
1506 | * by the hanger push. This assures the packet has a BDC | ||
1507 | * header upon return. | ||
1508 | */ | ||
1509 | hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger); | ||
1510 | free_ctr = entry->seq[fifo]; | ||
1511 | brcmf_skb_htod_tag_set_field(p, HSLOT, hslot); | ||
1512 | brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr); | ||
1513 | brcmf_skb_htod_tag_set_field(p, GENERATION, 1); | ||
1514 | entry->transit_count++; | ||
1515 | } | ||
1516 | brcmf_skb_if_flags_set_field(p, TRANSMIT, 1); | ||
1517 | brcmf_skb_htod_tag_set_field(p, FIFO, fifo); | ||
1518 | |||
1519 | flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST; | ||
1520 | if (!(skcb->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) { | ||
1521 | /* | ||
1522 | Indicate that this packet is being sent in response to an | ||
1523 | explicit request from the firmware side. | ||
1524 | */ | ||
1525 | flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED; | ||
1526 | } | ||
1527 | brcmf_skb_htod_tag_set_field(p, FLAGS, flags); | ||
1528 | if (header_needed) { | ||
1529 | brcmf_fws_hdrpush(fws, p); | ||
1530 | rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot); | ||
1531 | if (rc) | ||
1532 | brcmf_err("hanger push failed: rc=%d\n", rc); | ||
1533 | } else { | ||
1534 | int gen; | ||
1535 | |||
1536 | /* remove old header */ | ||
1537 | rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, p); | ||
1538 | if (rc == 0) { | ||
1539 | hslot = brcmf_skb_htod_tag_get_field(p, HSLOT); | ||
1540 | brcmf_fws_hanger_get_genbit(&fws->hanger, p, | ||
1541 | hslot, &gen); | ||
1542 | brcmf_skb_htod_tag_set_field(p, GENERATION, gen); | ||
1543 | |||
1544 | /* push new header */ | ||
1545 | brcmf_fws_hdrpush(fws, p); | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | return rc; | ||
1550 | } | ||
1551 | |||
1552 | static int | ||
1553 | brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb) | ||
1554 | { | ||
1555 | /* | ||
1556 | put the packet back to the head of queue | ||
1557 | |||
1558 | - suppressed packet goes back to suppress sub-queue | ||
1559 | - pull out the header, if new or delayed packet | ||
1560 | |||
1561 | Note: hslot is used only when header removal is done. | ||
1562 | */ | ||
1563 | struct brcmf_fws_mac_descriptor *entry; | ||
1564 | enum brcmf_fws_skb_state state; | ||
1565 | struct sk_buff *pktout; | ||
1566 | int rc = 0; | ||
1567 | int fifo; | ||
1568 | int hslot; | ||
1569 | u8 ifidx; | ||
1570 | |||
1571 | fifo = brcmf_skb_if_flags_get_field(skb, FIFO); | ||
1572 | state = brcmf_skbcb(skb)->state; | ||
1573 | entry = brcmf_skbcb(skb)->mac; | ||
1574 | |||
1575 | if (entry != NULL) { | ||
1576 | if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { | ||
1577 | /* wl-header is saved for suppressed packets */ | ||
1578 | pktout = brcmu_pktq_penq_head(&entry->psq, 2 * fifo + 1, | ||
1579 | skb); | ||
1580 | if (pktout == NULL) { | ||
1581 | brcmf_err("suppress queue full\n"); | ||
1582 | rc = -ENOSPC; | ||
1583 | } | ||
1584 | } else { | ||
1585 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | ||
1586 | |||
1587 | /* remove header first */ | ||
1588 | rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); | ||
1589 | if (rc) { | ||
1590 | brcmf_err("header removal failed\n"); | ||
1591 | /* free the hanger slot */ | ||
1592 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, | ||
1593 | &pktout, true); | ||
1594 | brcmf_txfinalize(fws->drvr, skb, false); | ||
1595 | rc = -EINVAL; | ||
1596 | goto fail; | ||
1597 | } | ||
1598 | |||
1599 | /* delay-q packets are going to delay-q */ | ||
1600 | pktout = brcmu_pktq_penq_head(&entry->psq, | ||
1601 | 2 * fifo, skb); | ||
1602 | if (pktout == NULL) { | ||
1603 | brcmf_err("delay queue full\n"); | ||
1604 | rc = -ENOSPC; | ||
1605 | } | ||
1606 | |||
1607 | /* free the hanger slot */ | ||
1608 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &pktout, | ||
1609 | true); | ||
1610 | |||
1611 | /* decrement sequence count */ | ||
1612 | entry->seq[fifo]--; | ||
1613 | } | ||
1614 | /* | ||
1615 | if this packet did not count against FIFO credit, it must have | ||
1616 | taken a requested_credit from the firmware (for pspoll etc.) | ||
1617 | */ | ||
1618 | if (!(brcmf_skbcb(skb)->if_flags & | ||
1619 | BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) | ||
1620 | entry->requested_credit++; | ||
1621 | } else { | ||
1622 | brcmf_err("no mac entry linked\n"); | ||
1623 | rc = -ENOENT; | ||
1624 | } | ||
1625 | |||
1626 | |||
1627 | fail: | ||
1628 | if (rc) | ||
1629 | fws->stats.rollback_failed++; | ||
1630 | else | ||
1631 | fws->stats.rollback_success++; | ||
1632 | return rc; | ||
1633 | } | ||
1634 | |||
1635 | static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo, | ||
1636 | struct sk_buff *skb) | ||
1637 | { | ||
1638 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; | ||
1639 | int *credit = &fws->fifo_credit[fifo]; | ||
1640 | int use_credit = 1; | ||
1641 | |||
1642 | brcmf_dbg(TRACE, "enter: ac=%d, credits=%d\n", fifo, *credit); | ||
1643 | |||
1644 | if (entry->requested_credit > 0) { | ||
1645 | /* | ||
1646 | * if the packet was pulled out while destination is in | ||
1647 | * closed state but had a non-zero packets requested, | ||
1648 | * then this should not count against the FIFO credit. | ||
1649 | * That is due to the fact that the firmware will | ||
1650 | * most likely hold onto this packet until a suitable | ||
1651 | * time later to push it to the appropriate AC FIFO. | ||
1652 | */ | ||
1653 | entry->requested_credit--; | ||
1654 | if (entry->state == BRCMF_FWS_STATE_CLOSE) | ||
1655 | use_credit = 0; | ||
1656 | } else if (entry->requested_packet > 0) { | ||
1657 | entry->requested_packet--; | ||
1658 | brcmf_skb_if_flags_set_field(skb, REQUESTED, 1); | ||
1659 | if (entry->state == BRCMF_FWS_STATE_CLOSE) | ||
1660 | use_credit = 0; | ||
1661 | } | ||
1662 | brcmf_skb_if_flags_set_field(skb, CREDITCHECK, use_credit); | ||
1663 | if (!use_credit) { | ||
1664 | brcmf_dbg(TRACE, "exit: no creditcheck set\n"); | ||
1665 | return 0; | ||
1666 | } | ||
1667 | |||
1668 | if (!(*credit)) { | ||
1669 | brcmf_dbg(TRACE, "exit: credits depleted\n"); | ||
1670 | return -ENAVAIL; | ||
1671 | } | ||
1672 | (*credit)--; | ||
1673 | if (!(*credit)) | ||
1674 | fws->fifo_credit_map &= ~(1 << fifo); | ||
1675 | brcmf_dbg(TRACE, "exit: ac=%d, credits=%d\n", fifo, *credit); | ||
1676 | return 0; | ||
1677 | } | ||
1678 | |||
1679 | static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, | ||
1680 | struct sk_buff *skb) | ||
1681 | { | ||
1682 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb); | ||
1683 | struct brcmf_fws_mac_descriptor *entry; | ||
1684 | struct brcmf_bus *bus = fws->drvr->bus_if; | ||
1685 | int rc; | ||
1686 | |||
1687 | entry = skcb->mac; | ||
1688 | if (IS_ERR(entry)) | ||
1689 | return PTR_ERR(entry); | ||
1690 | |||
1691 | rc = brcmf_fws_precommit_skb(fws, fifo, skb); | ||
1692 | if (rc < 0) { | ||
1693 | fws->stats.generic_error++; | ||
1694 | goto rollback; | ||
1695 | } | ||
1696 | |||
1697 | rc = brcmf_bus_txdata(bus, skb); | ||
1698 | if (rc < 0) | ||
1699 | goto rollback; | ||
1700 | |||
1701 | entry->seq[fifo]++; | ||
1702 | fws->stats.pkt2bus++; | ||
1703 | if (brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) { | ||
1704 | fws->stats.send_pkts[fifo]++; | ||
1705 | fws->stats.fifo_credits_sent[fifo]++; | ||
1706 | } | ||
1707 | |||
1708 | return rc; | ||
1709 | |||
1710 | rollback: | ||
1711 | rc = brcmf_fws_rollback_toq(fws, skb); | ||
1712 | return rc; | ||
1713 | } | ||
1714 | |||
1715 | int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) | ||
1716 | { | ||
1717 | struct brcmf_pub *drvr = ifp->drvr; | ||
1718 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb); | ||
1719 | struct ethhdr *eh = (struct ethhdr *)(skb->data); | ||
1720 | ulong flags; | ||
1721 | int fifo = BRCMF_FWS_FIFO_BCMC; | ||
1722 | bool multicast = is_multicast_ether_addr(eh->h_dest); | ||
1723 | |||
1724 | /* determine the priority */ | ||
1725 | if (!skb->priority) | ||
1726 | skb->priority = cfg80211_classify8021d(skb); | ||
1727 | |||
1728 | drvr->tx_multicast += !!multicast; | ||
1729 | if (ntohs(eh->h_proto) == ETH_P_PAE) | ||
1730 | atomic_inc(&ifp->pend_8021x_cnt); | ||
1731 | |||
1732 | if (!brcmf_fws_fc_active(drvr->fws)) { | ||
1733 | /* If the protocol uses a data header, apply it */ | ||
1734 | brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb); | ||
1735 | |||
1736 | /* Use bus module to send data frame */ | ||
1737 | return brcmf_bus_txdata(drvr->bus_if, skb); | ||
1738 | } | ||
1739 | |||
1740 | /* set control buffer information */ | ||
1741 | skcb->if_flags = 0; | ||
1742 | skcb->mac = brcmf_fws_find_mac_desc(drvr->fws, ifp, eh->h_dest); | ||
1743 | skcb->state = BRCMF_FWS_SKBSTATE_NEW; | ||
1744 | brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx); | ||
1745 | if (!multicast) | ||
1746 | fifo = brcmf_fws_prio2fifo[skb->priority]; | ||
1747 | brcmf_skb_if_flags_set_field(skb, FIFO, fifo); | ||
1748 | |||
1749 | brcmf_dbg(TRACE, "ea=%pM, multi=%d, fifo=%d\n", eh->h_dest, | ||
1750 | multicast, fifo); | ||
1751 | |||
1752 | brcmf_fws_lock(drvr, flags); | ||
1753 | if (skcb->mac->suppressed || | ||
1754 | brcmf_fws_mac_desc_closed(skcb->mac, fifo) || | ||
1755 | brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) || | ||
1756 | (!multicast && | ||
1757 | brcmf_fws_consume_credit(drvr->fws, fifo, skb) < 0)) { | ||
1758 | /* enqueue the packet in delayQ */ | ||
1759 | drvr->fws->fifo_delay_map |= 1 << fifo; | ||
1760 | brcmf_fws_enq(drvr->fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); | ||
1761 | } else { | ||
1762 | brcmf_fws_commit_skb(drvr->fws, fifo, skb); | ||
1763 | } | ||
1764 | brcmf_fws_unlock(drvr, flags); | ||
1765 | return 0; | ||
1766 | } | ||
1767 | |||
1768 | void brcmf_fws_reset_interface(struct brcmf_if *ifp) | ||
1769 | { | ||
1770 | struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc; | ||
1771 | |||
1772 | brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); | ||
1773 | if (!entry) | ||
1774 | return; | ||
1775 | |||
1776 | brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx); | ||
1777 | } | ||
1778 | |||
1779 | void brcmf_fws_add_interface(struct brcmf_if *ifp) | ||
1780 | { | ||
1781 | struct brcmf_fws_info *fws = ifp->drvr->fws; | ||
1782 | struct brcmf_fws_mac_descriptor *entry; | ||
1783 | |||
1784 | brcmf_dbg(TRACE, "enter: idx=%d, mac=%pM\n", | ||
1785 | ifp->bssidx, ifp->mac_addr); | ||
1786 | if (!ifp->ndev || !ifp->drvr->fw_signals) | ||
1787 | return; | ||
1788 | |||
1789 | entry = &fws->desc.iface[ifp->ifidx]; | ||
1790 | ifp->fws_desc = entry; | ||
1791 | brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx); | ||
1792 | brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, | ||
1793 | BRCMF_FWS_PSQ_LEN); | ||
1794 | } | ||
1795 | |||
1796 | void brcmf_fws_del_interface(struct brcmf_if *ifp) | ||
1797 | { | ||
1798 | struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc; | ||
1799 | |||
1800 | brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); | ||
1801 | if (!entry) | ||
1802 | return; | ||
1803 | |||
1804 | ifp->fws_desc = NULL; | ||
1805 | brcmf_fws_clear_mac_descriptor(entry); | ||
1806 | brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx); | ||
1807 | } | ||
1808 | |||
1809 | static void brcmf_fws_dequeue_worker(struct work_struct *worker) | ||
1810 | { | ||
1811 | struct brcmf_fws_info *fws; | ||
1812 | struct sk_buff *skb; | ||
1813 | ulong flags; | ||
1814 | int fifo; | ||
1815 | int credit; | ||
1816 | |||
1817 | fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work); | ||
1818 | |||
1819 | brcmf_dbg(TRACE, "enter: fws=%p\n", fws); | ||
1820 | brcmf_fws_lock(fws->drvr, flags); | ||
1821 | for (fifo = NL80211_NUM_ACS; fifo >= 0; fifo--) { | ||
1822 | brcmf_dbg(TRACE, "fifo %d credit %d\n", fifo, | ||
1823 | fws->fifo_credit[fifo]); | ||
1824 | for (credit = 0; credit < fws->fifo_credit[fifo]; /* nop */) { | ||
1825 | skb = brcmf_fws_deq(fws, fifo); | ||
1826 | if (!skb) | ||
1827 | break; | ||
1828 | if (!brcmf_fws_commit_skb(fws, fifo, skb) && | ||
1829 | brcmf_skbcb(skb)->if_flags & | ||
1830 | BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) | ||
1831 | credit++; | ||
1832 | } | ||
1833 | fws->fifo_credit[fifo] -= credit; | ||
1834 | } | ||
1835 | brcmf_fws_unlock(fws->drvr, flags); | ||
1836 | } | ||
1837 | |||
1838 | int brcmf_fws_init(struct brcmf_pub *drvr) | ||
1839 | { | ||
1840 | u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; | ||
1841 | int rc; | ||
1842 | |||
1843 | if (!drvr->fw_signals) | ||
1844 | return 0; | ||
1845 | |||
1846 | spin_lock_init(&drvr->fws_spinlock); | ||
1847 | |||
1848 | drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL); | ||
1849 | if (!drvr->fws) { | ||
1850 | rc = -ENOMEM; | ||
1851 | goto fail; | ||
1852 | } | ||
1853 | |||
1854 | /* set linkage back */ | ||
1855 | drvr->fws->drvr = drvr; | ||
1856 | drvr->fws->fcmode = fcmode; | ||
1857 | |||
1858 | drvr->fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq"); | ||
1859 | if (drvr->fws->fws_wq == NULL) { | ||
1860 | brcmf_err("workqueue creation failed\n"); | ||
1861 | rc = -EBADF; | ||
1862 | goto fail; | ||
1863 | } | ||
1864 | INIT_WORK(&drvr->fws->fws_dequeue_work, brcmf_fws_dequeue_worker); | ||
1865 | |||
1866 | /* enable firmware signalling if fcmode active */ | ||
1867 | if (drvr->fws->fcmode != BRCMF_FWS_FCMODE_NONE) | ||
1868 | tlv |= BRCMF_FWS_FLAGS_XONXOFF_SIGNALS | | ||
1869 | BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS | | ||
1870 | BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE; | ||
1871 | |||
1872 | rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv); | ||
1873 | if (rc < 0) { | ||
1874 | brcmf_err("failed to set bdcv2 tlv signaling\n"); | ||
1875 | goto fail; | ||
1876 | } | ||
1877 | |||
1878 | if (brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP, | ||
1879 | brcmf_fws_notify_credit_map)) { | ||
1880 | brcmf_err("register credit map handler failed\n"); | ||
1881 | goto fail; | ||
1882 | } | ||
1883 | |||
1884 | brcmf_fws_hanger_init(&drvr->fws->hanger); | ||
1885 | brcmf_fws_init_mac_descriptor(&drvr->fws->desc.other, NULL, 0); | ||
1886 | brcmu_pktq_init(&drvr->fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT, | ||
1887 | BRCMF_FWS_PSQ_LEN); | ||
1888 | |||
1889 | /* create debugfs file for statistics */ | ||
1890 | brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats); | ||
1891 | |||
1892 | /* TODO: remove upon feature delivery */ | ||
1893 | brcmf_err("%s bdcv2 tlv signaling [%x]\n", | ||
1894 | drvr->fw_signals ? "enabled" : "disabled", tlv); | ||
1895 | return 0; | ||
1896 | |||
1897 | fail: | ||
1898 | /* disable flow control entirely */ | ||
1899 | drvr->fw_signals = false; | ||
1900 | brcmf_fws_deinit(drvr); | ||
1901 | return rc; | ||
1902 | } | ||
1903 | |||
1904 | void brcmf_fws_deinit(struct brcmf_pub *drvr) | ||
1905 | { | ||
1906 | struct brcmf_fws_info *fws = drvr->fws; | ||
1907 | ulong flags; | ||
1908 | |||
1909 | if (!fws) | ||
1910 | return; | ||
1911 | |||
1912 | /* cleanup */ | ||
1913 | brcmf_fws_lock(drvr, flags); | ||
1914 | brcmf_fws_cleanup(fws, -1); | ||
1915 | drvr->fws = NULL; | ||
1916 | brcmf_fws_unlock(drvr, flags); | ||
1917 | |||
1918 | /* free top structure */ | ||
1919 | kfree(fws); | ||
1920 | } | ||
1921 | |||
1922 | bool brcmf_fws_fc_active(struct brcmf_fws_info *fws) | ||
1923 | { | ||
1924 | if (!fws) | ||
1925 | return false; | ||
1926 | |||
1927 | brcmf_dbg(TRACE, "enter: mode=%d\n", fws->fcmode); | ||
1928 | return fws->fcmode != BRCMF_FWS_FCMODE_NONE; | ||
1929 | } | ||
1930 | |||
1931 | void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb) | ||
1932 | { | ||
1933 | ulong flags; | ||
1934 | |||
1935 | brcmf_fws_lock(fws->drvr, flags); | ||
1936 | brcmf_fws_txstatus_process(fws, BRCMF_FWS_TXSTATUS_FW_TOSSED, | ||
1937 | brcmf_skb_htod_tag_get_field(skb, HSLOT), 0); | ||
1938 | /* the packet never reached firmware so reclaim credit */ | ||
1939 | if (fws->fcmode == BRCMF_FWS_FCMODE_EXPLICIT_CREDIT && | ||
1940 | brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) { | ||
1941 | brcmf_fws_return_credits(fws, | ||
1942 | brcmf_skb_htod_tag_get_field(skb, | ||
1943 | FIFO), | ||
1944 | 1); | ||
1945 | brcmf_fws_schedule_deq(fws); | ||
1946 | } | ||
1947 | brcmf_fws_unlock(fws->drvr, flags); | ||
1948 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h new file mode 100644 index 000000000000..fbe483d23752 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h | |||
@@ -0,0 +1,33 @@ | |||
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 | bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); | ||
24 | int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | ||
25 | struct sk_buff *skb); | ||
26 | int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb); | ||
27 | |||
28 | void brcmf_fws_reset_interface(struct brcmf_if *ifp); | ||
29 | void brcmf_fws_add_interface(struct brcmf_if *ifp); | ||
30 | void brcmf_fws_del_interface(struct brcmf_if *ifp); | ||
31 | void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb); | ||
32 | |||
33 | #endif /* FWSIGNAL_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 4166e642068b..2b90da0d85f3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | #include <linux/etherdevice.h> | ||
18 | #include <net/cfg80211.h> | 19 | #include <net/cfg80211.h> |
19 | 20 | ||
20 | #include <brcmu_wifi.h> | 21 | #include <brcmu_wifi.h> |
@@ -423,29 +424,6 @@ static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len) | |||
423 | 424 | ||
424 | 425 | ||
425 | /** | 426 | /** |
426 | * brcmf_p2p_chnr_to_chspec() - convert channel number to chanspec. | ||
427 | * | ||
428 | * @channel: channel number | ||
429 | */ | ||
430 | static u16 brcmf_p2p_chnr_to_chspec(u16 channel) | ||
431 | { | ||
432 | u16 chanspec; | ||
433 | |||
434 | chanspec = channel & WL_CHANSPEC_CHAN_MASK; | ||
435 | |||
436 | if (channel <= CH_MAX_2G_CHANNEL) | ||
437 | chanspec |= WL_CHANSPEC_BAND_2G; | ||
438 | else | ||
439 | chanspec |= WL_CHANSPEC_BAND_5G; | ||
440 | |||
441 | chanspec |= WL_CHANSPEC_BW_20; | ||
442 | chanspec |= WL_CHANSPEC_CTL_SB_NONE; | ||
443 | |||
444 | return chanspec; | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
449 | * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation. | 427 | * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation. |
450 | * | 428 | * |
451 | * @ifp: ifp to use for iovars (primary). | 429 | * @ifp: ifp to use for iovars (primary). |
@@ -455,7 +433,9 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) | |||
455 | { | 433 | { |
456 | s32 ret = 0; | 434 | s32 ret = 0; |
457 | 435 | ||
436 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); | ||
458 | brcmf_fil_iovar_int_set(ifp, "apsta", 1); | 437 | brcmf_fil_iovar_int_set(ifp, "apsta", 1); |
438 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); | ||
459 | 439 | ||
460 | /* In case of COB type, firmware has default mac address | 440 | /* In case of COB type, firmware has default mac address |
461 | * After Initializing firmware, we have to set current mac address to | 441 | * After Initializing firmware, we have to set current mac address to |
@@ -473,28 +453,35 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) | |||
473 | * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P. | 453 | * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P. |
474 | * | 454 | * |
475 | * @p2p: P2P specific data. | 455 | * @p2p: P2P specific data. |
456 | * @dev_addr: optional device address. | ||
476 | * | 457 | * |
477 | * P2P needs mac addresses for P2P device and interface. These are | 458 | * P2P needs mac addresses for P2P device and interface. If no device |
478 | * derived from the primary net device, ie. the permanent ethernet | 459 | * address it specified, these are derived from the primary net device, ie. |
479 | * address of the device. | 460 | * the permanent ethernet address of the device. |
480 | */ | 461 | */ |
481 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p) | 462 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) |
482 | { | 463 | { |
483 | struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 464 | struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; |
484 | struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp; | 465 | bool local_admin = false; |
466 | |||
467 | if (!dev_addr || is_zero_ether_addr(dev_addr)) { | ||
468 | dev_addr = pri_ifp->mac_addr; | ||
469 | local_admin = true; | ||
470 | } | ||
485 | 471 | ||
486 | /* Generate the P2P Device Address. This consists of the device's | 472 | /* Generate the P2P Device Address. This consists of the device's |
487 | * primary MAC address with the locally administered bit set. | 473 | * primary MAC address with the locally administered bit set. |
488 | */ | 474 | */ |
489 | memcpy(p2p->dev_addr, pri_ifp->mac_addr, ETH_ALEN); | 475 | memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); |
490 | p2p->dev_addr[0] |= 0x02; | 476 | if (local_admin) |
491 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | 477 | p2p->dev_addr[0] |= 0x02; |
492 | 478 | ||
493 | /* Generate the P2P Interface Address. If the discovery and connection | 479 | /* Generate the P2P Interface Address. If the discovery and connection |
494 | * BSSCFGs need to simultaneously co-exist, then this address must be | 480 | * BSSCFGs need to simultaneously co-exist, then this address must be |
495 | * different from the P2P Device Address, but also locally administered. | 481 | * different from the P2P Device Address, but also locally administered. |
496 | */ | 482 | */ |
497 | memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN); | 483 | memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN); |
484 | p2p->int_addr[0] |= 0x02; | ||
498 | p2p->int_addr[4] ^= 0x80; | 485 | p2p->int_addr[4] ^= 0x80; |
499 | } | 486 | } |
500 | 487 | ||
@@ -773,7 +760,7 @@ exit: | |||
773 | * validates the channels in the request. | 760 | * validates the channels in the request. |
774 | */ | 761 | */ |
775 | static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, | 762 | static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, |
776 | struct net_device *ndev, | 763 | struct brcmf_if *ifp, |
777 | struct cfg80211_scan_request *request, | 764 | struct cfg80211_scan_request *request, |
778 | u16 action) | 765 | u16 action) |
779 | { | 766 | { |
@@ -827,7 +814,8 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, | |||
827 | IEEE80211_CHAN_PASSIVE_SCAN)) | 814 | IEEE80211_CHAN_PASSIVE_SCAN)) |
828 | continue; | 815 | continue; |
829 | 816 | ||
830 | chanspecs[i] = channel_to_chanspec(chan); | 817 | chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf, |
818 | chan); | ||
831 | brcmf_dbg(INFO, "%d: chan=%d, channel spec=%x\n", | 819 | brcmf_dbg(INFO, "%d: chan=%d, channel spec=%x\n", |
832 | num_nodfs, chan->hw_value, chanspecs[i]); | 820 | num_nodfs, chan->hw_value, chanspecs[i]); |
833 | num_nodfs++; | 821 | num_nodfs++; |
@@ -935,8 +923,8 @@ static s32 | |||
935 | brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration) | 923 | brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration) |
936 | { | 924 | { |
937 | struct brcmf_cfg80211_vif *vif; | 925 | struct brcmf_cfg80211_vif *vif; |
926 | struct brcmu_chan ch; | ||
938 | s32 err = 0; | 927 | s32 err = 0; |
939 | u16 chanspec; | ||
940 | 928 | ||
941 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; | 929 | vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; |
942 | if (!vif) { | 930 | if (!vif) { |
@@ -951,9 +939,11 @@ brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration) | |||
951 | goto exit; | 939 | goto exit; |
952 | } | 940 | } |
953 | 941 | ||
954 | chanspec = brcmf_p2p_chnr_to_chspec(channel); | 942 | ch.chnum = channel; |
943 | ch.bw = BRCMU_CHAN_BW_20; | ||
944 | p2p->cfg->d11inf.encchspec(&ch); | ||
955 | err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN, | 945 | err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN, |
956 | chanspec, (u16)duration); | 946 | ch.chspec, (u16)duration); |
957 | if (!err) { | 947 | if (!err) { |
958 | set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status); | 948 | set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status); |
959 | p2p->remain_on_channel_cookie++; | 949 | p2p->remain_on_channel_cookie++; |
@@ -1065,6 +1055,7 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel) | |||
1065 | u32 channel_cnt; | 1055 | u32 channel_cnt; |
1066 | u16 *default_chan_list; | 1056 | u16 *default_chan_list; |
1067 | u32 i; | 1057 | u32 i; |
1058 | struct brcmu_chan ch; | ||
1068 | 1059 | ||
1069 | brcmf_dbg(TRACE, "Enter\n"); | 1060 | brcmf_dbg(TRACE, "Enter\n"); |
1070 | 1061 | ||
@@ -1079,15 +1070,23 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel) | |||
1079 | err = -ENOMEM; | 1070 | err = -ENOMEM; |
1080 | goto exit; | 1071 | goto exit; |
1081 | } | 1072 | } |
1073 | ch.bw = BRCMU_CHAN_BW_20; | ||
1082 | if (channel) { | 1074 | if (channel) { |
1075 | ch.chnum = channel; | ||
1076 | p2p->cfg->d11inf.encchspec(&ch); | ||
1083 | /* insert same channel to the chan_list */ | 1077 | /* insert same channel to the chan_list */ |
1084 | for (i = 0; i < channel_cnt; i++) | 1078 | for (i = 0; i < channel_cnt; i++) |
1085 | default_chan_list[i] = | 1079 | default_chan_list[i] = ch.chspec; |
1086 | brcmf_p2p_chnr_to_chspec(channel); | ||
1087 | } else { | 1080 | } else { |
1088 | default_chan_list[0] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_1); | 1081 | ch.chnum = SOCIAL_CHAN_1; |
1089 | default_chan_list[1] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_2); | 1082 | p2p->cfg->d11inf.encchspec(&ch); |
1090 | default_chan_list[2] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_3); | 1083 | default_chan_list[0] = ch.chspec; |
1084 | ch.chnum = SOCIAL_CHAN_2; | ||
1085 | p2p->cfg->d11inf.encchspec(&ch); | ||
1086 | default_chan_list[1] = ch.chspec; | ||
1087 | ch.chnum = SOCIAL_CHAN_3; | ||
1088 | p2p->cfg->d11inf.encchspec(&ch); | ||
1089 | default_chan_list[2] = ch.chspec; | ||
1091 | } | 1090 | } |
1092 | err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list, | 1091 | err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list, |
1093 | WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START, | 1092 | WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START, |
@@ -1217,6 +1216,7 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg, | |||
1217 | { | 1216 | { |
1218 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1217 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1219 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; | 1218 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; |
1219 | struct brcmu_chan ch; | ||
1220 | u8 *ie; | 1220 | u8 *ie; |
1221 | s32 err; | 1221 | s32 err; |
1222 | u8 p2p_dev_addr[ETH_ALEN]; | 1222 | u8 p2p_dev_addr[ETH_ALEN]; |
@@ -1242,8 +1242,12 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg, | |||
1242 | p2p_dev_addr, sizeof(p2p_dev_addr)); | 1242 | p2p_dev_addr, sizeof(p2p_dev_addr)); |
1243 | if ((err >= 0) && | 1243 | if ((err >= 0) && |
1244 | (!memcmp(p2p_dev_addr, afx_hdl->tx_dst_addr, ETH_ALEN))) { | 1244 | (!memcmp(p2p_dev_addr, afx_hdl->tx_dst_addr, ETH_ALEN))) { |
1245 | afx_hdl->peer_chan = bi->ctl_ch ? bi->ctl_ch : | 1245 | if (!bi->ctl_ch) { |
1246 | CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); | 1246 | ch.chspec = le16_to_cpu(bi->chanspec); |
1247 | cfg->d11inf.decchspec(&ch); | ||
1248 | bi->ctl_ch = ch.chnum; | ||
1249 | } | ||
1250 | afx_hdl->peer_chan = bi->ctl_ch; | ||
1247 | brcmf_dbg(TRACE, "ACTION FRAME SCAN : Peer %pM found, channel : %d\n", | 1251 | brcmf_dbg(TRACE, "ACTION FRAME SCAN : Peer %pM found, channel : %d\n", |
1248 | afx_hdl->tx_dst_addr, afx_hdl->peer_chan); | 1252 | afx_hdl->tx_dst_addr, afx_hdl->peer_chan); |
1249 | complete(&afx_hdl->act_frm_scan); | 1253 | complete(&afx_hdl->act_frm_scan); |
@@ -1261,7 +1265,7 @@ static void | |||
1261 | brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) | 1265 | brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) |
1262 | { | 1266 | { |
1263 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1267 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1264 | struct net_device *ndev = cfg->escan_info.ndev; | 1268 | struct brcmf_if *ifp = cfg->escan_info.ifp; |
1265 | 1269 | ||
1266 | if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) && | 1270 | if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) && |
1267 | (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) || | 1271 | (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) || |
@@ -1271,12 +1275,12 @@ brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) | |||
1271 | * So abort scan for off channel completion. | 1275 | * So abort scan for off channel completion. |
1272 | */ | 1276 | */ |
1273 | if (p2p->af_sent_channel) | 1277 | if (p2p->af_sent_channel) |
1274 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 1278 | brcmf_notify_escan_complete(cfg, ifp, true, true); |
1275 | } else if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, | 1279 | } else if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, |
1276 | &p2p->status)) { | 1280 | &p2p->status)) { |
1277 | brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n"); | 1281 | brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n"); |
1278 | /* So abort scan to cancel listen */ | 1282 | /* So abort scan to cancel listen */ |
1279 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 1283 | brcmf_notify_escan_complete(cfg, ifp, true, true); |
1280 | } | 1284 | } |
1281 | } | 1285 | } |
1282 | 1286 | ||
@@ -1350,12 +1354,14 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1350 | u8 *frame = (u8 *)(rxframe + 1); | 1354 | u8 *frame = (u8 *)(rxframe + 1); |
1351 | struct brcmf_p2p_pub_act_frame *act_frm; | 1355 | struct brcmf_p2p_pub_act_frame *act_frm; |
1352 | struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm; | 1356 | struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm; |
1353 | u16 chanspec = be16_to_cpu(rxframe->chanspec); | 1357 | struct brcmu_chan ch; |
1354 | struct ieee80211_mgmt *mgmt_frame; | 1358 | struct ieee80211_mgmt *mgmt_frame; |
1355 | s32 freq; | 1359 | s32 freq; |
1356 | u16 mgmt_type; | 1360 | u16 mgmt_type; |
1357 | u8 action; | 1361 | u8 action; |
1358 | 1362 | ||
1363 | ch.chspec = be16_to_cpu(rxframe->chanspec); | ||
1364 | cfg->d11inf.decchspec(&ch); | ||
1359 | /* Check if wpa_supplicant has registered for this frame */ | 1365 | /* Check if wpa_supplicant has registered for this frame */ |
1360 | brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg); | 1366 | brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg); |
1361 | mgmt_type = (IEEE80211_STYPE_ACTION & IEEE80211_FCTL_STYPE) >> 4; | 1367 | mgmt_type = (IEEE80211_STYPE_ACTION & IEEE80211_FCTL_STYPE) >> 4; |
@@ -1374,7 +1380,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1374 | &p2p->status) && | 1380 | &p2p->status) && |
1375 | (memcmp(afx_hdl->tx_dst_addr, e->addr, | 1381 | (memcmp(afx_hdl->tx_dst_addr, e->addr, |
1376 | ETH_ALEN) == 0)) { | 1382 | ETH_ALEN) == 0)) { |
1377 | afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec); | 1383 | afx_hdl->peer_chan = ch.chnum; |
1378 | brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n", | 1384 | brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n", |
1379 | afx_hdl->peer_chan); | 1385 | afx_hdl->peer_chan); |
1380 | complete(&afx_hdl->act_frm_scan); | 1386 | complete(&afx_hdl->act_frm_scan); |
@@ -1384,7 +1390,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1384 | /* After complete GO Negotiation, roll back to mpc mode */ | 1390 | /* After complete GO Negotiation, roll back to mpc mode */ |
1385 | if ((action == P2P_PAF_GON_CONF) || | 1391 | if ((action == P2P_PAF_GON_CONF) || |
1386 | (action == P2P_PAF_PROVDIS_RSP)) | 1392 | (action == P2P_PAF_PROVDIS_RSP)) |
1387 | brcmf_set_mpc(ifp->ndev, 1); | 1393 | brcmf_set_mpc(ifp, 1); |
1388 | if (action == P2P_PAF_GON_CONF) { | 1394 | if (action == P2P_PAF_GON_CONF) { |
1389 | brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n"); | 1395 | brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n"); |
1390 | clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); | 1396 | clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); |
@@ -1417,11 +1423,12 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1417 | memcpy(&mgmt_frame->u, frame, mgmt_frame_len); | 1423 | memcpy(&mgmt_frame->u, frame, mgmt_frame_len); |
1418 | mgmt_frame_len += offsetof(struct ieee80211_mgmt, u); | 1424 | mgmt_frame_len += offsetof(struct ieee80211_mgmt, u); |
1419 | 1425 | ||
1420 | freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec), | 1426 | freq = ieee80211_channel_to_frequency(ch.chnum, |
1421 | CHSPEC_IS2G(chanspec) ? | 1427 | ch.band == BRCMU_CHAN_BAND_2G ? |
1422 | IEEE80211_BAND_2GHZ : | 1428 | IEEE80211_BAND_2GHZ : |
1423 | IEEE80211_BAND_5GHZ); | 1429 | IEEE80211_BAND_5GHZ); |
1424 | wdev = ifp->ndev->ieee80211_ptr; | 1430 | |
1431 | wdev = &ifp->vif->wdev; | ||
1425 | cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, | 1432 | cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, |
1426 | GFP_ATOMIC); | 1433 | GFP_ATOMIC); |
1427 | 1434 | ||
@@ -1637,6 +1644,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, | |||
1637 | struct brcmf_fil_af_params_le *af_params) | 1644 | struct brcmf_fil_af_params_le *af_params) |
1638 | { | 1645 | { |
1639 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1646 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1647 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
1640 | struct brcmf_fil_action_frame_le *action_frame; | 1648 | struct brcmf_fil_action_frame_le *action_frame; |
1641 | struct brcmf_config_af_params config_af_params; | 1649 | struct brcmf_config_af_params config_af_params; |
1642 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; | 1650 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; |
@@ -1725,7 +1733,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, | |||
1725 | 1733 | ||
1726 | /* To make sure to send successfully action frame, turn off mpc */ | 1734 | /* To make sure to send successfully action frame, turn off mpc */ |
1727 | if (config_af_params.mpc_onoff == 0) | 1735 | if (config_af_params.mpc_onoff == 0) |
1728 | brcmf_set_mpc(ndev, 0); | 1736 | brcmf_set_mpc(ifp, 0); |
1729 | 1737 | ||
1730 | /* set status and destination address before sending af */ | 1738 | /* set status and destination address before sending af */ |
1731 | if (p2p->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) { | 1739 | if (p2p->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) { |
@@ -1753,7 +1761,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, | |||
1753 | * care of current piggback algo, lets abort the scan here | 1761 | * care of current piggback algo, lets abort the scan here |
1754 | * itself. | 1762 | * itself. |
1755 | */ | 1763 | */ |
1756 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 1764 | brcmf_notify_escan_complete(cfg, ifp, true, true); |
1757 | 1765 | ||
1758 | /* update channel */ | 1766 | /* update channel */ |
1759 | af_params->channel = cpu_to_le32(afx_hdl->peer_chan); | 1767 | af_params->channel = cpu_to_le32(afx_hdl->peer_chan); |
@@ -1820,7 +1828,7 @@ exit: | |||
1820 | clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status); | 1828 | clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status); |
1821 | /* if all done, turn mpc on again */ | 1829 | /* if all done, turn mpc on again */ |
1822 | if (config_af_params.mpc_onoff == 1) | 1830 | if (config_af_params.mpc_onoff == 1) |
1823 | brcmf_set_mpc(ndev, 1); | 1831 | brcmf_set_mpc(ifp, 1); |
1824 | 1832 | ||
1825 | return ack; | 1833 | return ack; |
1826 | } | 1834 | } |
@@ -1839,10 +1847,10 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
1839 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | 1847 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; |
1840 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1848 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1841 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; | 1849 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; |
1842 | struct wireless_dev *wdev; | ||
1843 | struct brcmf_cfg80211_vif *vif = ifp->vif; | 1850 | struct brcmf_cfg80211_vif *vif = ifp->vif; |
1844 | struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data; | 1851 | struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data; |
1845 | u16 chanspec = be16_to_cpu(rxframe->chanspec); | 1852 | u16 chanspec = be16_to_cpu(rxframe->chanspec); |
1853 | struct brcmu_chan ch; | ||
1846 | u8 *mgmt_frame; | 1854 | u8 *mgmt_frame; |
1847 | u32 mgmt_frame_len; | 1855 | u32 mgmt_frame_len; |
1848 | s32 freq; | 1856 | s32 freq; |
@@ -1851,9 +1859,12 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
1851 | brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code, | 1859 | brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code, |
1852 | e->reason); | 1860 | e->reason); |
1853 | 1861 | ||
1862 | ch.chspec = be16_to_cpu(rxframe->chanspec); | ||
1863 | cfg->d11inf.decchspec(&ch); | ||
1864 | |||
1854 | if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) && | 1865 | if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) && |
1855 | (memcmp(afx_hdl->tx_dst_addr, e->addr, ETH_ALEN) == 0)) { | 1866 | (memcmp(afx_hdl->tx_dst_addr, e->addr, ETH_ALEN) == 0)) { |
1856 | afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec); | 1867 | afx_hdl->peer_chan = ch.chnum; |
1857 | brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n", | 1868 | brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n", |
1858 | afx_hdl->peer_chan); | 1869 | afx_hdl->peer_chan); |
1859 | complete(&afx_hdl->act_frm_scan); | 1870 | complete(&afx_hdl->act_frm_scan); |
@@ -1878,12 +1889,13 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
1878 | 1889 | ||
1879 | mgmt_frame = (u8 *)(rxframe + 1); | 1890 | mgmt_frame = (u8 *)(rxframe + 1); |
1880 | mgmt_frame_len = e->datalen - sizeof(*rxframe); | 1891 | mgmt_frame_len = e->datalen - sizeof(*rxframe); |
1881 | freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec), | 1892 | freq = ieee80211_channel_to_frequency(ch.chnum, |
1882 | CHSPEC_IS2G(chanspec) ? | 1893 | ch.band == BRCMU_CHAN_BAND_2G ? |
1883 | IEEE80211_BAND_2GHZ : | 1894 | IEEE80211_BAND_2GHZ : |
1884 | IEEE80211_BAND_5GHZ); | 1895 | IEEE80211_BAND_5GHZ); |
1885 | wdev = ifp->ndev->ieee80211_ptr; | 1896 | |
1886 | cfg80211_rx_mgmt(wdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); | 1897 | cfg80211_rx_mgmt(&vif->wdev, freq, 0, mgmt_frame, mgmt_frame_len, |
1898 | GFP_ATOMIC); | ||
1887 | 1899 | ||
1888 | brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n", | 1900 | brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n", |
1889 | mgmt_frame_len, e->datalen, chanspec, freq); | 1901 | mgmt_frame_len, e->datalen, chanspec, freq); |
@@ -1934,7 +1946,8 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) | |||
1934 | 1946 | ||
1935 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | 1947 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; |
1936 | 1948 | ||
1937 | brcmf_p2p_generate_bss_mac(p2p); | 1949 | brcmf_p2p_generate_bss_mac(p2p, NULL); |
1950 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
1938 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | 1951 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); |
1939 | 1952 | ||
1940 | /* Initialize P2P Discovery in the firmware */ | 1953 | /* Initialize P2P Discovery in the firmware */ |
@@ -2001,21 +2014,19 @@ static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p, | |||
2001 | { | 2014 | { |
2002 | struct brcmf_if *ifp; | 2015 | struct brcmf_if *ifp; |
2003 | struct brcmf_fil_chan_info_le ci; | 2016 | struct brcmf_fil_chan_info_le ci; |
2017 | struct brcmu_chan ch; | ||
2004 | s32 err; | 2018 | s32 err; |
2005 | 2019 | ||
2006 | ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 2020 | ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; |
2007 | 2021 | ||
2008 | *chanspec = 11 & WL_CHANSPEC_CHAN_MASK; | 2022 | ch.chnum = 11; |
2009 | 2023 | ||
2010 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci)); | 2024 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci)); |
2011 | if (!err) { | 2025 | if (!err) |
2012 | *chanspec = le32_to_cpu(ci.hw_channel) & WL_CHANSPEC_CHAN_MASK; | 2026 | ch.chnum = le32_to_cpu(ci.hw_channel); |
2013 | if (*chanspec < CH_MAX_2G_CHANNEL) | 2027 | ch.bw = BRCMU_CHAN_BW_20; |
2014 | *chanspec |= WL_CHANSPEC_BAND_2G; | 2028 | p2p->cfg->d11inf.encchspec(&ch); |
2015 | else | 2029 | *chanspec = ch.chspec; |
2016 | *chanspec |= WL_CHANSPEC_BAND_5G; | ||
2017 | } | ||
2018 | *chanspec |= WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE; | ||
2019 | } | 2030 | } |
2020 | 2031 | ||
2021 | /** | 2032 | /** |
@@ -2040,13 +2051,13 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, | |||
2040 | brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n"); | 2051 | brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n"); |
2041 | return -EPERM; | 2052 | return -EPERM; |
2042 | } | 2053 | } |
2043 | brcmf_notify_escan_complete(cfg, vif->ifp->ndev, true, true); | 2054 | brcmf_notify_escan_complete(cfg, vif->ifp, true, true); |
2044 | vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif; | 2055 | vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif; |
2045 | if (!vif) { | 2056 | if (!vif) { |
2046 | brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n"); | 2057 | brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n"); |
2047 | return -EPERM; | 2058 | return -EPERM; |
2048 | } | 2059 | } |
2049 | brcmf_set_mpc(vif->ifp->ndev, 0); | 2060 | brcmf_set_mpc(vif->ifp, 0); |
2050 | 2061 | ||
2051 | /* In concurrency case, STA may be already associated in a particular */ | 2062 | /* In concurrency case, STA may be already associated in a particular */ |
2052 | /* channel. so retrieve the current channel of primary interface and */ | 2063 | /* channel. so retrieve the current channel of primary interface and */ |
@@ -2124,13 +2135,105 @@ static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif) | |||
2124 | } | 2135 | } |
2125 | 2136 | ||
2126 | /** | 2137 | /** |
2138 | * brcmf_p2p_create_p2pdev() - create a P2P_DEVICE virtual interface. | ||
2139 | * | ||
2140 | * @p2p: P2P specific data. | ||
2141 | * @wiphy: wiphy device of new interface. | ||
2142 | * @addr: mac address for this new interface. | ||
2143 | */ | ||
2144 | static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, | ||
2145 | struct wiphy *wiphy, | ||
2146 | u8 *addr) | ||
2147 | { | ||
2148 | struct brcmf_cfg80211_vif *p2p_vif; | ||
2149 | struct brcmf_if *p2p_ifp; | ||
2150 | struct brcmf_if *pri_ifp; | ||
2151 | int err; | ||
2152 | u32 bssidx; | ||
2153 | |||
2154 | if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif) | ||
2155 | return ERR_PTR(-ENOSPC); | ||
2156 | |||
2157 | p2p_vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE, | ||
2158 | false); | ||
2159 | if (IS_ERR(p2p_vif)) { | ||
2160 | brcmf_err("could not create discovery vif\n"); | ||
2161 | return (struct wireless_dev *)p2p_vif; | ||
2162 | } | ||
2163 | |||
2164 | pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | ||
2165 | brcmf_p2p_generate_bss_mac(p2p, addr); | ||
2166 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | ||
2167 | |||
2168 | brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif); | ||
2169 | |||
2170 | /* Initialize P2P Discovery in the firmware */ | ||
2171 | err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); | ||
2172 | if (err < 0) { | ||
2173 | brcmf_err("set p2p_disc error\n"); | ||
2174 | brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); | ||
2175 | goto fail; | ||
2176 | } | ||
2177 | |||
2178 | /* wait for firmware event */ | ||
2179 | err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD, | ||
2180 | msecs_to_jiffies(1500)); | ||
2181 | brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); | ||
2182 | if (!err) { | ||
2183 | brcmf_err("timeout occurred\n"); | ||
2184 | err = -EIO; | ||
2185 | goto fail; | ||
2186 | } | ||
2187 | |||
2188 | /* discovery interface created */ | ||
2189 | p2p_ifp = p2p_vif->ifp; | ||
2190 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | ||
2191 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
2192 | memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr)); | ||
2193 | |||
2194 | /* verify bsscfg index for P2P discovery */ | ||
2195 | err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); | ||
2196 | if (err < 0) { | ||
2197 | brcmf_err("retrieving discover bsscfg index failed\n"); | ||
2198 | goto fail; | ||
2199 | } | ||
2200 | |||
2201 | WARN_ON(p2p_ifp->bssidx != bssidx); | ||
2202 | |||
2203 | init_completion(&p2p->send_af_done); | ||
2204 | INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); | ||
2205 | init_completion(&p2p->afx_hdl.act_frm_scan); | ||
2206 | init_completion(&p2p->wait_next_af); | ||
2207 | |||
2208 | return &p2p_vif->wdev; | ||
2209 | |||
2210 | fail: | ||
2211 | brcmf_free_vif(p2p_vif); | ||
2212 | return ERR_PTR(err); | ||
2213 | } | ||
2214 | |||
2215 | /** | ||
2216 | * brcmf_p2p_delete_p2pdev() - delete P2P_DEVICE virtual interface. | ||
2217 | * | ||
2218 | * @vif: virtual interface object to delete. | ||
2219 | */ | ||
2220 | static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_vif *vif) | ||
2221 | { | ||
2222 | struct brcmf_p2p_info *p2p = &vif->ifp->drvr->config->p2p; | ||
2223 | |||
2224 | cfg80211_unregister_wdev(&vif->wdev); | ||
2225 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; | ||
2226 | brcmf_free_vif(vif); | ||
2227 | } | ||
2228 | |||
2229 | /** | ||
2127 | * brcmf_p2p_add_vif() - create a new P2P virtual interface. | 2230 | * brcmf_p2p_add_vif() - create a new P2P virtual interface. |
2128 | * | 2231 | * |
2129 | * @wiphy: wiphy device of new interface. | 2232 | * @wiphy: wiphy device of new interface. |
2130 | * @name: name of the new interface. | 2233 | * @name: name of the new interface. |
2131 | * @type: nl80211 interface type. | 2234 | * @type: nl80211 interface type. |
2132 | * @flags: TBD | 2235 | * @flags: not used. |
2133 | * @params: TBD | 2236 | * @params: contains mac address for P2P device. |
2134 | */ | 2237 | */ |
2135 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | 2238 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, |
2136 | enum nl80211_iftype type, u32 *flags, | 2239 | enum nl80211_iftype type, u32 *flags, |
@@ -2157,6 +2260,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | |||
2157 | iftype = BRCMF_FIL_P2P_IF_GO; | 2260 | iftype = BRCMF_FIL_P2P_IF_GO; |
2158 | mode = WL_MODE_AP; | 2261 | mode = WL_MODE_AP; |
2159 | break; | 2262 | break; |
2263 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2264 | return brcmf_p2p_create_p2pdev(&cfg->p2p, wiphy, | ||
2265 | params->macaddr); | ||
2160 | default: | 2266 | default: |
2161 | return ERR_PTR(-EOPNOTSUPP); | 2267 | return ERR_PTR(-EOPNOTSUPP); |
2162 | } | 2268 | } |
@@ -2244,6 +2350,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2244 | break; | 2350 | break; |
2245 | 2351 | ||
2246 | case NL80211_IFTYPE_P2P_DEVICE: | 2352 | case NL80211_IFTYPE_P2P_DEVICE: |
2353 | brcmf_p2p_delete_p2pdev(vif); | ||
2354 | return 0; | ||
2247 | default: | 2355 | default: |
2248 | return -ENOTSUPP; | 2356 | return -ENOTSUPP; |
2249 | break; | 2357 | break; |
@@ -2275,3 +2383,33 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2275 | 2383 | ||
2276 | return err; | 2384 | return err; |
2277 | } | 2385 | } |
2386 | |||
2387 | int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev) | ||
2388 | { | ||
2389 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
2390 | struct brcmf_p2p_info *p2p = &cfg->p2p; | ||
2391 | struct brcmf_cfg80211_vif *vif; | ||
2392 | int err; | ||
2393 | |||
2394 | vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); | ||
2395 | mutex_lock(&cfg->usr_sync); | ||
2396 | err = brcmf_p2p_enable_discovery(p2p); | ||
2397 | if (!err) | ||
2398 | set_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); | ||
2399 | mutex_unlock(&cfg->usr_sync); | ||
2400 | return err; | ||
2401 | } | ||
2402 | |||
2403 | void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) | ||
2404 | { | ||
2405 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
2406 | struct brcmf_p2p_info *p2p = &cfg->p2p; | ||
2407 | struct brcmf_cfg80211_vif *vif; | ||
2408 | |||
2409 | vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); | ||
2410 | mutex_lock(&cfg->usr_sync); | ||
2411 | (void)brcmf_p2p_deinit_discovery(p2p); | ||
2412 | brcmf_abort_scanning(cfg); | ||
2413 | clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); | ||
2414 | mutex_unlock(&cfg->usr_sync); | ||
2415 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index 14be2d5530ce..ca72177388b9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | |||
@@ -40,6 +40,15 @@ | |||
40 | #define BCM4329_CORE_ARM_BASE 0x18002000 | 40 | #define BCM4329_CORE_ARM_BASE 0x18002000 |
41 | #define BCM4329_RAMSIZE 0x48000 | 41 | #define BCM4329_RAMSIZE 0x48000 |
42 | 42 | ||
43 | /* bcm43143 */ | ||
44 | /* SDIO device core */ | ||
45 | #define BCM43143_CORE_BUS_BASE 0x18002000 | ||
46 | /* internal memory core */ | ||
47 | #define BCM43143_CORE_SOCRAM_BASE 0x18004000 | ||
48 | /* ARM Cortex M3 core, ID 0x82a */ | ||
49 | #define BCM43143_CORE_ARM_BASE 0x18003000 | ||
50 | #define BCM43143_RAMSIZE 0x70000 | ||
51 | |||
43 | #define SBCOREREV(sbidh) \ | 52 | #define SBCOREREV(sbidh) \ |
44 | ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \ | 53 | ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \ |
45 | ((sbidh) & SSB_IDHIGH_RCLO)) | 54 | ((sbidh) & SSB_IDHIGH_RCLO)) |
@@ -52,6 +61,9 @@ | |||
52 | #define CIB_REV_MASK 0xff000000 | 61 | #define CIB_REV_MASK 0xff000000 |
53 | #define CIB_REV_SHIFT 24 | 62 | #define CIB_REV_SHIFT 24 |
54 | 63 | ||
64 | /* ARM CR4 core specific control flag bits */ | ||
65 | #define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020 | ||
66 | |||
55 | #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) | 67 | #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) |
56 | /* SDIO Pad drive strength to select value mappings */ | 68 | /* SDIO Pad drive strength to select value mappings */ |
57 | struct sdiod_drive_str { | 69 | struct sdiod_drive_str { |
@@ -70,6 +82,14 @@ static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = { | |||
70 | {0, 0x1} | 82 | {0, 0x1} |
71 | }; | 83 | }; |
72 | 84 | ||
85 | /* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */ | ||
86 | static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = { | ||
87 | {16, 0x7}, | ||
88 | {12, 0x5}, | ||
89 | {8, 0x3}, | ||
90 | {4, 0x1} | ||
91 | }; | ||
92 | |||
73 | u8 | 93 | u8 |
74 | brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid) | 94 | brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid) |
75 | { | 95 | { |
@@ -149,7 +169,7 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
149 | 169 | ||
150 | static void | 170 | static void |
151 | brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, | 171 | brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, |
152 | struct chip_info *ci, u16 coreid) | 172 | struct chip_info *ci, u16 coreid, u32 core_bits) |
153 | { | 173 | { |
154 | u32 regdata, base; | 174 | u32 regdata, base; |
155 | u8 idx; | 175 | u8 idx; |
@@ -235,7 +255,7 @@ brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, | |||
235 | 255 | ||
236 | static void | 256 | static void |
237 | brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, | 257 | brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, |
238 | struct chip_info *ci, u16 coreid) | 258 | struct chip_info *ci, u16 coreid, u32 core_bits) |
239 | { | 259 | { |
240 | u8 idx; | 260 | u8 idx; |
241 | u32 regdata; | 261 | u32 regdata; |
@@ -249,19 +269,36 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, | |||
249 | if ((regdata & BCMA_RESET_CTL_RESET) != 0) | 269 | if ((regdata & BCMA_RESET_CTL_RESET) != 0) |
250 | return; | 270 | return; |
251 | 271 | ||
252 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 0, NULL); | 272 | /* ensure no pending backplane operation |
253 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 273 | * 300uc should be sufficient for backplane ops to be finish |
274 | * extra 10ms is taken into account for firmware load stage | ||
275 | * after 10300us carry on disabling the core anyway | ||
276 | */ | ||
277 | SPINWAIT(brcmf_sdio_regrl(sdiodev, | ||
278 | ci->c_inf[idx].wrapbase+BCMA_RESET_ST, | ||
279 | NULL), 10300); | ||
280 | regdata = brcmf_sdio_regrl(sdiodev, | ||
281 | ci->c_inf[idx].wrapbase+BCMA_RESET_ST, | ||
254 | NULL); | 282 | NULL); |
255 | udelay(10); | 283 | if (regdata) |
284 | brcmf_err("disabling core 0x%x with reset status %x\n", | ||
285 | coreid, regdata); | ||
256 | 286 | ||
257 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 287 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
258 | BCMA_RESET_CTL_RESET, NULL); | 288 | BCMA_RESET_CTL_RESET, NULL); |
259 | udelay(1); | 289 | udelay(1); |
290 | |||
291 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | ||
292 | core_bits, NULL); | ||
293 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | ||
294 | NULL); | ||
295 | usleep_range(10, 20); | ||
296 | |||
260 | } | 297 | } |
261 | 298 | ||
262 | static void | 299 | static void |
263 | brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, | 300 | brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, |
264 | struct chip_info *ci, u16 coreid) | 301 | struct chip_info *ci, u16 coreid, u32 core_bits) |
265 | { | 302 | { |
266 | u32 regdata; | 303 | u32 regdata; |
267 | u8 idx; | 304 | u8 idx; |
@@ -272,7 +309,7 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
272 | * Must do the disable sequence first to work for | 309 | * Must do the disable sequence first to work for |
273 | * arbitrary current core state. | 310 | * arbitrary current core state. |
274 | */ | 311 | */ |
275 | brcmf_sdio_sb_coredisable(sdiodev, ci, coreid); | 312 | brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, 0); |
276 | 313 | ||
277 | /* | 314 | /* |
278 | * Now do the initialization sequence. | 315 | * Now do the initialization sequence. |
@@ -325,7 +362,7 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
325 | 362 | ||
326 | static void | 363 | static void |
327 | brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, | 364 | brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, |
328 | struct chip_info *ci, u16 coreid) | 365 | struct chip_info *ci, u16 coreid, u32 core_bits) |
329 | { | 366 | { |
330 | u8 idx; | 367 | u8 idx; |
331 | u32 regdata; | 368 | u32 regdata; |
@@ -333,31 +370,69 @@ brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
333 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 370 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
334 | 371 | ||
335 | /* must disable first to work for arbitrary current core state */ | 372 | /* must disable first to work for arbitrary current core state */ |
336 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid); | 373 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits); |
337 | 374 | ||
338 | /* now do initialization sequence */ | 375 | /* now do initialization sequence */ |
339 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 376 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
340 | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL); | 377 | core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL); |
341 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 378 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
342 | NULL); | 379 | NULL); |
343 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 380 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
344 | 0, NULL); | 381 | 0, NULL); |
382 | regdata = brcmf_sdio_regrl(sdiodev, | ||
383 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | ||
384 | NULL); | ||
345 | udelay(1); | 385 | udelay(1); |
346 | 386 | ||
347 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 387 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
348 | BCMA_IOCTL_CLK, NULL); | 388 | core_bits | BCMA_IOCTL_CLK, NULL); |
349 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 389 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
350 | NULL); | 390 | NULL); |
351 | udelay(1); | 391 | udelay(1); |
352 | } | 392 | } |
353 | 393 | ||
394 | #ifdef DEBUG | ||
395 | /* safety check for chipinfo */ | ||
396 | static int brcmf_sdio_chip_cichk(struct chip_info *ci) | ||
397 | { | ||
398 | u8 core_idx; | ||
399 | |||
400 | /* check RAM core presence for ARM CM3 core */ | ||
401 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3); | ||
402 | if (BRCMF_MAX_CORENUM != core_idx) { | ||
403 | core_idx = brcmf_sdio_chip_getinfidx(ci, | ||
404 | BCMA_CORE_INTERNAL_MEM); | ||
405 | if (BRCMF_MAX_CORENUM == core_idx) { | ||
406 | brcmf_err("RAM core not provided with ARM CM3 core\n"); | ||
407 | return -ENODEV; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | /* check RAM base for ARM CR4 core */ | ||
412 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4); | ||
413 | if (BRCMF_MAX_CORENUM != core_idx) { | ||
414 | if (ci->rambase == 0) { | ||
415 | brcmf_err("RAM base not provided with ARM CR4 core\n"); | ||
416 | return -ENOMEM; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | #else /* DEBUG */ | ||
423 | static inline int brcmf_sdio_chip_cichk(struct chip_info *ci) | ||
424 | { | ||
425 | return 0; | ||
426 | } | ||
427 | #endif | ||
428 | |||
354 | static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | 429 | static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, |
355 | struct chip_info *ci, u32 regs) | 430 | struct chip_info *ci, u32 regs) |
356 | { | 431 | { |
357 | u32 regdata; | 432 | u32 regdata; |
433 | int ret; | ||
358 | 434 | ||
359 | /* | 435 | /* Get CC core rev |
360 | * Get CC core rev | ||
361 | * Chipid is assume to be at offset 0 from regs arg | 436 | * Chipid is assume to be at offset 0 from regs arg |
362 | * For different chiptypes or old sdio hosts w/o chipcommon, | 437 | * For different chiptypes or old sdio hosts w/o chipcommon, |
363 | * other ways of recognition should be added here. | 438 | * other ways of recognition should be added here. |
@@ -375,6 +450,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | |||
375 | 450 | ||
376 | /* Address of cores for new chips should be added here */ | 451 | /* Address of cores for new chips should be added here */ |
377 | switch (ci->chip) { | 452 | switch (ci->chip) { |
453 | case BCM43143_CHIP_ID: | ||
454 | ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000; | ||
455 | ci->c_inf[0].cib = 0x2b000000; | ||
456 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
457 | ci->c_inf[1].base = BCM43143_CORE_BUS_BASE; | ||
458 | ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000; | ||
459 | ci->c_inf[1].cib = 0x18000000; | ||
460 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
461 | ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE; | ||
462 | ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000; | ||
463 | ci->c_inf[2].cib = 0x14000000; | ||
464 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
465 | ci->c_inf[3].base = BCM43143_CORE_ARM_BASE; | ||
466 | ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000; | ||
467 | ci->c_inf[3].cib = 0x07000000; | ||
468 | ci->ramsize = BCM43143_RAMSIZE; | ||
469 | break; | ||
378 | case BCM43241_CHIP_ID: | 470 | case BCM43241_CHIP_ID: |
379 | ci->c_inf[0].wrapbase = 0x18100000; | 471 | ci->c_inf[0].wrapbase = 0x18100000; |
380 | ci->c_inf[0].cib = 0x2a084411; | 472 | ci->c_inf[0].cib = 0x2a084411; |
@@ -435,11 +527,29 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | |||
435 | ci->c_inf[3].cib = 0x07004211; | 527 | ci->c_inf[3].cib = 0x07004211; |
436 | ci->ramsize = 0x80000; | 528 | ci->ramsize = 0x80000; |
437 | break; | 529 | break; |
530 | case BCM4335_CHIP_ID: | ||
531 | ci->c_inf[0].wrapbase = 0x18100000; | ||
532 | ci->c_inf[0].cib = 0x2b084411; | ||
533 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
534 | ci->c_inf[1].base = 0x18005000; | ||
535 | ci->c_inf[1].wrapbase = 0x18105000; | ||
536 | ci->c_inf[1].cib = 0x0f004211; | ||
537 | ci->c_inf[2].id = BCMA_CORE_ARM_CR4; | ||
538 | ci->c_inf[2].base = 0x18002000; | ||
539 | ci->c_inf[2].wrapbase = 0x18102000; | ||
540 | ci->c_inf[2].cib = 0x01084411; | ||
541 | ci->ramsize = 0xc0000; | ||
542 | ci->rambase = 0x180000; | ||
543 | break; | ||
438 | default: | 544 | default: |
439 | brcmf_err("chipid 0x%x is not supported\n", ci->chip); | 545 | brcmf_err("chipid 0x%x is not supported\n", ci->chip); |
440 | return -ENODEV; | 546 | return -ENODEV; |
441 | } | 547 | } |
442 | 548 | ||
549 | ret = brcmf_sdio_chip_cichk(ci); | ||
550 | if (ret) | ||
551 | return ret; | ||
552 | |||
443 | switch (ci->socitype) { | 553 | switch (ci->socitype) { |
444 | case SOCI_SB: | 554 | case SOCI_SB: |
445 | ci->iscoreup = brcmf_sdio_sb_iscoreup; | 555 | ci->iscoreup = brcmf_sdio_sb_iscoreup; |
@@ -539,7 +649,7 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, | |||
539 | * Make sure any on-chip ARM is off (in case strapping is wrong), | 649 | * Make sure any on-chip ARM is off (in case strapping is wrong), |
540 | * or downloaded code was already running. | 650 | * or downloaded code was already running. |
541 | */ | 651 | */ |
542 | ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3); | 652 | ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); |
543 | } | 653 | } |
544 | 654 | ||
545 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, | 655 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, |
@@ -600,21 +710,37 @@ void | |||
600 | brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | 710 | brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, |
601 | struct chip_info *ci, u32 drivestrength) | 711 | struct chip_info *ci, u32 drivestrength) |
602 | { | 712 | { |
603 | struct sdiod_drive_str *str_tab = NULL; | 713 | const struct sdiod_drive_str *str_tab = NULL; |
604 | u32 str_mask = 0; | 714 | u32 str_mask; |
605 | u32 str_shift = 0; | 715 | u32 str_shift; |
606 | char chn[8]; | 716 | char chn[8]; |
607 | u32 base = ci->c_inf[0].base; | 717 | u32 base = ci->c_inf[0].base; |
718 | u32 i; | ||
719 | u32 drivestrength_sel = 0; | ||
720 | u32 cc_data_temp; | ||
721 | u32 addr; | ||
608 | 722 | ||
609 | if (!(ci->c_inf[0].caps & CC_CAP_PMU)) | 723 | if (!(ci->c_inf[0].caps & CC_CAP_PMU)) |
610 | return; | 724 | return; |
611 | 725 | ||
612 | switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { | 726 | switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { |
613 | case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): | 727 | case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): |
614 | str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8; | 728 | str_tab = sdiod_drvstr_tab1_1v8; |
615 | str_mask = 0x00003800; | 729 | str_mask = 0x00003800; |
616 | str_shift = 11; | 730 | str_shift = 11; |
617 | break; | 731 | break; |
732 | case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): | ||
733 | /* note: 43143 does not support tristate */ | ||
734 | i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1; | ||
735 | if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) { | ||
736 | str_tab = sdiod_drvstr_tab2_3v3; | ||
737 | str_mask = 0x00000007; | ||
738 | str_shift = 0; | ||
739 | } else | ||
740 | brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n", | ||
741 | brcmf_sdio_chip_name(ci->chip, chn, 8), | ||
742 | drivestrength); | ||
743 | break; | ||
618 | default: | 744 | default: |
619 | brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", | 745 | brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", |
620 | brcmf_sdio_chip_name(ci->chip, chn, 8), | 746 | brcmf_sdio_chip_name(ci->chip, chn, 8), |
@@ -623,30 +749,207 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
623 | } | 749 | } |
624 | 750 | ||
625 | if (str_tab != NULL) { | 751 | if (str_tab != NULL) { |
626 | u32 drivestrength_sel = 0; | ||
627 | u32 cc_data_temp; | ||
628 | int i; | ||
629 | |||
630 | for (i = 0; str_tab[i].strength != 0; i++) { | 752 | for (i = 0; str_tab[i].strength != 0; i++) { |
631 | if (drivestrength >= str_tab[i].strength) { | 753 | if (drivestrength >= str_tab[i].strength) { |
632 | drivestrength_sel = str_tab[i].sel; | 754 | drivestrength_sel = str_tab[i].sel; |
633 | break; | 755 | break; |
634 | } | 756 | } |
635 | } | 757 | } |
636 | 758 | addr = CORE_CC_REG(base, chipcontrol_addr); | |
637 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr), | 759 | brcmf_sdio_regwl(sdiodev, addr, 1, NULL); |
638 | 1, NULL); | 760 | cc_data_temp = brcmf_sdio_regrl(sdiodev, addr, NULL); |
639 | cc_data_temp = | ||
640 | brcmf_sdio_regrl(sdiodev, | ||
641 | CORE_CC_REG(base, chipcontrol_addr), | ||
642 | NULL); | ||
643 | cc_data_temp &= ~str_mask; | 761 | cc_data_temp &= ~str_mask; |
644 | drivestrength_sel <<= str_shift; | 762 | drivestrength_sel <<= str_shift; |
645 | cc_data_temp |= drivestrength_sel; | 763 | cc_data_temp |= drivestrength_sel; |
646 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr), | 764 | brcmf_sdio_regwl(sdiodev, addr, cc_data_temp, NULL); |
647 | cc_data_temp, NULL); | ||
648 | 765 | ||
649 | brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n", | 766 | brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n", |
650 | drivestrength, cc_data_temp); | 767 | str_tab[i].strength, drivestrength, cc_data_temp); |
651 | } | 768 | } |
652 | } | 769 | } |
770 | |||
771 | #ifdef DEBUG | ||
772 | static bool | ||
773 | brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr, | ||
774 | char *nvram_dat, uint nvram_sz) | ||
775 | { | ||
776 | char *nvram_ularray; | ||
777 | int err; | ||
778 | bool ret = true; | ||
779 | |||
780 | /* read back and verify */ | ||
781 | brcmf_dbg(INFO, "Compare NVRAM dl & ul; size=%d\n", nvram_sz); | ||
782 | nvram_ularray = kmalloc(nvram_sz, GFP_KERNEL); | ||
783 | /* do not proceed while no memory but */ | ||
784 | if (!nvram_ularray) | ||
785 | return true; | ||
786 | |||
787 | /* Upload image to verify downloaded contents. */ | ||
788 | memset(nvram_ularray, 0xaa, nvram_sz); | ||
789 | |||
790 | /* Read the vars list to temp buffer for comparison */ | ||
791 | err = brcmf_sdio_ramrw(sdiodev, false, nvram_addr, nvram_ularray, | ||
792 | nvram_sz); | ||
793 | if (err) { | ||
794 | brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n", | ||
795 | err, nvram_sz, nvram_addr); | ||
796 | } else if (memcmp(nvram_dat, nvram_ularray, nvram_sz)) { | ||
797 | brcmf_err("Downloaded NVRAM image is corrupted\n"); | ||
798 | ret = false; | ||
799 | } | ||
800 | kfree(nvram_ularray); | ||
801 | |||
802 | return ret; | ||
803 | } | ||
804 | #else /* DEBUG */ | ||
805 | static inline bool | ||
806 | brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr, | ||
807 | char *nvram_dat, uint nvram_sz) | ||
808 | { | ||
809 | return true; | ||
810 | } | ||
811 | #endif /* DEBUG */ | ||
812 | |||
813 | static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev, | ||
814 | struct chip_info *ci, | ||
815 | char *nvram_dat, uint nvram_sz) | ||
816 | { | ||
817 | int err; | ||
818 | u32 nvram_addr; | ||
819 | u32 token; | ||
820 | __le32 token_le; | ||
821 | |||
822 | nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase; | ||
823 | |||
824 | /* Write the vars list */ | ||
825 | err = brcmf_sdio_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz); | ||
826 | if (err) { | ||
827 | brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n", | ||
828 | err, nvram_sz, nvram_addr); | ||
829 | return false; | ||
830 | } | ||
831 | |||
832 | if (!brcmf_sdio_chip_verifynvram(sdiodev, nvram_addr, | ||
833 | nvram_dat, nvram_sz)) | ||
834 | return false; | ||
835 | |||
836 | /* generate token: | ||
837 | * nvram size, converted to words, in lower 16-bits, checksum | ||
838 | * in upper 16-bits. | ||
839 | */ | ||
840 | token = nvram_sz / 4; | ||
841 | token = (~token << 16) | (token & 0x0000FFFF); | ||
842 | token_le = cpu_to_le32(token); | ||
843 | |||
844 | brcmf_dbg(INFO, "RAM size: %d\n", ci->ramsize); | ||
845 | brcmf_dbg(INFO, "nvram is placed at %d, size %d, token=0x%08x\n", | ||
846 | nvram_addr, nvram_sz, token); | ||
847 | |||
848 | /* Write the length token to the last word */ | ||
849 | if (brcmf_sdio_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase), | ||
850 | (u8 *)&token_le, 4)) | ||
851 | return false; | ||
852 | |||
853 | return true; | ||
854 | } | ||
855 | |||
856 | static void | ||
857 | brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev, | ||
858 | struct chip_info *ci) | ||
859 | { | ||
860 | u32 zeros = 0; | ||
861 | |||
862 | ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); | ||
863 | ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0); | ||
864 | |||
865 | /* clear length token */ | ||
866 | brcmf_sdio_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4); | ||
867 | } | ||
868 | |||
869 | static bool | ||
870 | brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | ||
871 | char *nvram_dat, uint nvram_sz) | ||
872 | { | ||
873 | u8 core_idx; | ||
874 | u32 reg_addr; | ||
875 | |||
876 | if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) { | ||
877 | brcmf_err("SOCRAM core is down after reset?\n"); | ||
878 | return false; | ||
879 | } | ||
880 | |||
881 | if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz)) | ||
882 | return false; | ||
883 | |||
884 | /* clear all interrupts */ | ||
885 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV); | ||
886 | reg_addr = ci->c_inf[core_idx].base; | ||
887 | reg_addr += offsetof(struct sdpcmd_regs, intstatus); | ||
888 | brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); | ||
889 | |||
890 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); | ||
891 | |||
892 | return true; | ||
893 | } | ||
894 | |||
895 | static inline void | ||
896 | brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev, | ||
897 | struct chip_info *ci) | ||
898 | { | ||
899 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, | ||
900 | ARMCR4_BCMA_IOCTL_CPUHALT); | ||
901 | } | ||
902 | |||
903 | static bool | ||
904 | brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | ||
905 | char *nvram_dat, uint nvram_sz) | ||
906 | { | ||
907 | u8 core_idx; | ||
908 | u32 reg_addr; | ||
909 | |||
910 | if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz)) | ||
911 | return false; | ||
912 | |||
913 | /* clear all interrupts */ | ||
914 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV); | ||
915 | reg_addr = ci->c_inf[core_idx].base; | ||
916 | reg_addr += offsetof(struct sdpcmd_regs, intstatus); | ||
917 | brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); | ||
918 | |||
919 | /* Write reset vector to address 0 */ | ||
920 | brcmf_sdio_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec, | ||
921 | sizeof(ci->rst_vec)); | ||
922 | |||
923 | /* restore ARM */ | ||
924 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0); | ||
925 | |||
926 | return true; | ||
927 | } | ||
928 | |||
929 | void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, | ||
930 | struct chip_info *ci) | ||
931 | { | ||
932 | u8 arm_core_idx; | ||
933 | |||
934 | arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3); | ||
935 | if (BRCMF_MAX_CORENUM != arm_core_idx) { | ||
936 | brcmf_sdio_chip_cm3_enterdl(sdiodev, ci); | ||
937 | return; | ||
938 | } | ||
939 | |||
940 | brcmf_sdio_chip_cr4_enterdl(sdiodev, ci); | ||
941 | } | ||
942 | |||
943 | bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, | ||
944 | struct chip_info *ci, char *nvram_dat, | ||
945 | uint nvram_sz) | ||
946 | { | ||
947 | u8 arm_core_idx; | ||
948 | |||
949 | arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3); | ||
950 | if (BRCMF_MAX_CORENUM != arm_core_idx) | ||
951 | return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci, nvram_dat, | ||
952 | nvram_sz); | ||
953 | |||
954 | return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, nvram_dat, nvram_sz); | ||
955 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h index ce974d76bd92..83c041f1bf4a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h | |||
@@ -73,15 +73,17 @@ struct chip_info { | |||
73 | u32 pmurev; | 73 | u32 pmurev; |
74 | u32 pmucaps; | 74 | u32 pmucaps; |
75 | u32 ramsize; | 75 | u32 ramsize; |
76 | u32 rambase; | ||
77 | u32 rst_vec; /* reset vertor for ARM CR4 core */ | ||
76 | 78 | ||
77 | bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | 79 | bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, |
78 | u16 coreid); | 80 | u16 coreid); |
79 | u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | 81 | u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, |
80 | u16 coreid); | 82 | u16 coreid); |
81 | void (*coredisable)(struct brcmf_sdio_dev *sdiodev, | 83 | void (*coredisable)(struct brcmf_sdio_dev *sdiodev, |
82 | struct chip_info *ci, u16 coreid); | 84 | struct chip_info *ci, u16 coreid, u32 core_bits); |
83 | void (*resetcore)(struct brcmf_sdio_dev *sdiodev, | 85 | void (*resetcore)(struct brcmf_sdio_dev *sdiodev, |
84 | struct chip_info *ci, u16 coreid); | 86 | struct chip_info *ci, u16 coreid, u32 core_bits); |
85 | }; | 87 | }; |
86 | 88 | ||
87 | struct sbconfig { | 89 | struct sbconfig { |
@@ -124,6 +126,95 @@ struct sbconfig { | |||
124 | u32 sbidhigh; /* identification */ | 126 | u32 sbidhigh; /* identification */ |
125 | }; | 127 | }; |
126 | 128 | ||
129 | /* sdio core registers */ | ||
130 | struct sdpcmd_regs { | ||
131 | u32 corecontrol; /* 0x00, rev8 */ | ||
132 | u32 corestatus; /* rev8 */ | ||
133 | u32 PAD[1]; | ||
134 | u32 biststatus; /* rev8 */ | ||
135 | |||
136 | /* PCMCIA access */ | ||
137 | u16 pcmciamesportaladdr; /* 0x010, rev8 */ | ||
138 | u16 PAD[1]; | ||
139 | u16 pcmciamesportalmask; /* rev8 */ | ||
140 | u16 PAD[1]; | ||
141 | u16 pcmciawrframebc; /* rev8 */ | ||
142 | u16 PAD[1]; | ||
143 | u16 pcmciaunderflowtimer; /* rev8 */ | ||
144 | u16 PAD[1]; | ||
145 | |||
146 | /* interrupt */ | ||
147 | u32 intstatus; /* 0x020, rev8 */ | ||
148 | u32 hostintmask; /* rev8 */ | ||
149 | u32 intmask; /* rev8 */ | ||
150 | u32 sbintstatus; /* rev8 */ | ||
151 | u32 sbintmask; /* rev8 */ | ||
152 | u32 funcintmask; /* rev4 */ | ||
153 | u32 PAD[2]; | ||
154 | u32 tosbmailbox; /* 0x040, rev8 */ | ||
155 | u32 tohostmailbox; /* rev8 */ | ||
156 | u32 tosbmailboxdata; /* rev8 */ | ||
157 | u32 tohostmailboxdata; /* rev8 */ | ||
158 | |||
159 | /* synchronized access to registers in SDIO clock domain */ | ||
160 | u32 sdioaccess; /* 0x050, rev8 */ | ||
161 | u32 PAD[3]; | ||
162 | |||
163 | /* PCMCIA frame control */ | ||
164 | u8 pcmciaframectrl; /* 0x060, rev8 */ | ||
165 | u8 PAD[3]; | ||
166 | u8 pcmciawatermark; /* rev8 */ | ||
167 | u8 PAD[155]; | ||
168 | |||
169 | /* interrupt batching control */ | ||
170 | u32 intrcvlazy; /* 0x100, rev8 */ | ||
171 | u32 PAD[3]; | ||
172 | |||
173 | /* counters */ | ||
174 | u32 cmd52rd; /* 0x110, rev8 */ | ||
175 | u32 cmd52wr; /* rev8 */ | ||
176 | u32 cmd53rd; /* rev8 */ | ||
177 | u32 cmd53wr; /* rev8 */ | ||
178 | u32 abort; /* rev8 */ | ||
179 | u32 datacrcerror; /* rev8 */ | ||
180 | u32 rdoutofsync; /* rev8 */ | ||
181 | u32 wroutofsync; /* rev8 */ | ||
182 | u32 writebusy; /* rev8 */ | ||
183 | u32 readwait; /* rev8 */ | ||
184 | u32 readterm; /* rev8 */ | ||
185 | u32 writeterm; /* rev8 */ | ||
186 | u32 PAD[40]; | ||
187 | u32 clockctlstatus; /* rev8 */ | ||
188 | u32 PAD[7]; | ||
189 | |||
190 | u32 PAD[128]; /* DMA engines */ | ||
191 | |||
192 | /* SDIO/PCMCIA CIS region */ | ||
193 | char cis[512]; /* 0x400-0x5ff, rev6 */ | ||
194 | |||
195 | /* PCMCIA function control registers */ | ||
196 | char pcmciafcr[256]; /* 0x600-6ff, rev6 */ | ||
197 | u16 PAD[55]; | ||
198 | |||
199 | /* PCMCIA backplane access */ | ||
200 | u16 backplanecsr; /* 0x76E, rev6 */ | ||
201 | u16 backplaneaddr0; /* rev6 */ | ||
202 | u16 backplaneaddr1; /* rev6 */ | ||
203 | u16 backplaneaddr2; /* rev6 */ | ||
204 | u16 backplaneaddr3; /* rev6 */ | ||
205 | u16 backplanedata0; /* rev6 */ | ||
206 | u16 backplanedata1; /* rev6 */ | ||
207 | u16 backplanedata2; /* rev6 */ | ||
208 | u16 backplanedata3; /* rev6 */ | ||
209 | u16 PAD[31]; | ||
210 | |||
211 | /* sprom "size" & "blank" info */ | ||
212 | u16 spromstatus; /* 0x7BE, rev2 */ | ||
213 | u32 PAD[464]; | ||
214 | |||
215 | u16 PAD[0x80]; | ||
216 | }; | ||
217 | |||
127 | extern int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, | 218 | extern int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, |
128 | struct chip_info **ci_ptr, u32 regs); | 219 | struct chip_info **ci_ptr, u32 regs); |
129 | extern void brcmf_sdio_chip_detach(struct chip_info **ci_ptr); | 220 | extern void brcmf_sdio_chip_detach(struct chip_info **ci_ptr); |
@@ -131,6 +222,10 @@ extern void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
131 | struct chip_info *ci, | 222 | struct chip_info *ci, |
132 | u32 drivestrength); | 223 | u32 drivestrength); |
133 | extern u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid); | 224 | extern u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid); |
134 | 225 | extern void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, | |
226 | struct chip_info *ci); | ||
227 | extern bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, | ||
228 | struct chip_info *ci, char *nvram_dat, | ||
229 | uint nvram_sz); | ||
135 | 230 | ||
136 | #endif /* _BRCMFMAC_SDIO_CHIP_H_ */ | 231 | #endif /* _BRCMFMAC_SDIO_CHIP_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 0d30afd8c672..7c1b6332747e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
@@ -48,7 +48,13 @@ | |||
48 | #define SBSDIO_NUM_FUNCTION 3 | 48 | #define SBSDIO_NUM_FUNCTION 3 |
49 | 49 | ||
50 | /* function 0 vendor specific CCCR registers */ | 50 | /* function 0 vendor specific CCCR registers */ |
51 | #define SDIO_CCCR_BRCM_SEPINT 0xf2 | 51 | #define SDIO_CCCR_BRCM_CARDCAP 0xf0 |
52 | #define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02 | ||
53 | #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04 | ||
54 | #define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08 | ||
55 | #define SDIO_CCCR_BRCM_CARDCTRL 0xf1 | ||
56 | #define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02 | ||
57 | #define SDIO_CCCR_BRCM_SEPINT 0xf2 | ||
52 | 58 | ||
53 | #define SDIO_SEPINT_MASK 0x01 | 59 | #define SDIO_SEPINT_MASK 0x01 |
54 | #define SDIO_SEPINT_OE 0x02 | 60 | #define SDIO_SEPINT_OE 0x02 |
@@ -97,9 +103,23 @@ | |||
97 | #define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B | 103 | #define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B |
98 | /* Read Frame Byte Count High */ | 104 | /* Read Frame Byte Count High */ |
99 | #define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C | 105 | #define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C |
106 | /* MesBusyCtl (rev 11) */ | ||
107 | #define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D | ||
108 | /* Sdio Core Rev 12 */ | ||
109 | #define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E | ||
110 | #define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1 | ||
111 | #define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0 | ||
112 | #define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2 | ||
113 | #define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1 | ||
114 | #define SBSDIO_FUNC1_SLEEPCSR 0x1001F | ||
115 | #define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1 | ||
116 | #define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0 | ||
117 | #define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1 | ||
118 | #define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2 | ||
119 | #define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1 | ||
100 | 120 | ||
101 | #define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ | 121 | #define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ |
102 | #define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */ | 122 | #define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001F /* f1 misc register end */ |
103 | 123 | ||
104 | /* function 1 OCP space */ | 124 | /* function 1 OCP space */ |
105 | 125 | ||
@@ -154,13 +174,11 @@ struct brcmf_sdio_dev { | |||
154 | wait_queue_head_t request_buffer_wait; | 174 | wait_queue_head_t request_buffer_wait; |
155 | struct device *dev; | 175 | struct device *dev; |
156 | struct brcmf_bus *bus_if; | 176 | struct brcmf_bus *bus_if; |
157 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | 177 | struct brcmfmac_sdio_platform_data *pdata; |
158 | unsigned int irq; /* oob interrupt number */ | 178 | bool oob_irq_requested; |
159 | unsigned long irq_flags; /* board specific oob flags */ | ||
160 | bool irq_en; /* irq enable flags */ | 179 | bool irq_en; /* irq enable flags */ |
161 | spinlock_t irq_en_lock; | 180 | spinlock_t irq_en_lock; |
162 | bool irq_wake; /* irq wake enable flags */ | 181 | bool irq_wake; /* irq wake enable flags */ |
163 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
164 | }; | 182 | }; |
165 | 183 | ||
166 | /* Register/deregister interrupt handler. */ | 184 | /* Register/deregister interrupt handler. */ |
@@ -224,6 +242,8 @@ brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
224 | */ | 242 | */ |
225 | extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, | 243 | extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, |
226 | u32 addr, u8 *buf, uint nbytes); | 244 | u32 addr, u8 *buf, uint nbytes); |
245 | extern int brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, | ||
246 | u32 address, u8 *data, uint size); | ||
227 | 247 | ||
228 | /* Issue an abort to the specified function */ | 248 | /* Issue an abort to the specified function */ |
229 | extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); | 249 | extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); |
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..9df1f7a681e0 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h | |||
@@ -0,0 +1,101 @@ | |||
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 | TRACE_EVENT(brcmf_hexdump, | ||
77 | TP_PROTO(void *data, size_t len), | ||
78 | TP_ARGS(data, len), | ||
79 | TP_STRUCT__entry( | ||
80 | __field(unsigned long, len) | ||
81 | __dynamic_array(u8, hdata, len) | ||
82 | ), | ||
83 | TP_fast_assign( | ||
84 | __entry->len = len; | ||
85 | memcpy(__get_dynamic_array(hdata), data, len); | ||
86 | ), | ||
87 | TP_printk("hexdump [length=%lu]", __entry->len) | ||
88 | ); | ||
89 | |||
90 | #ifdef CONFIG_BRCM_TRACING | ||
91 | |||
92 | #undef TRACE_INCLUDE_PATH | ||
93 | #define TRACE_INCLUDE_PATH . | ||
94 | #undef TRACE_INCLUDE_FILE | ||
95 | #define TRACE_INCLUDE_FILE tracepoint | ||
96 | |||
97 | #include <trace/define_trace.h> | ||
98 | |||
99 | #endif /* CONFIG_BRCM_TRACING */ | ||
100 | |||
101 | #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..3b3eb94b5472 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <brcmu_wifi.h> | 26 | #include <brcmu_wifi.h> |
27 | #include "dhd.h" | 27 | #include "dhd.h" |
28 | #include "dhd_dbg.h" | 28 | #include "dhd_dbg.h" |
29 | #include "tracepoint.h" | ||
29 | #include "fwil_types.h" | 30 | #include "fwil_types.h" |
30 | #include "p2p.h" | 31 | #include "p2p.h" |
31 | #include "wl_cfg80211.h" | 32 | #include "wl_cfg80211.h" |
@@ -182,64 +183,6 @@ static struct ieee80211_channel __wl_5ghz_a_channels[] = { | |||
182 | CHAN5G(216, 0), | 183 | CHAN5G(216, 0), |
183 | }; | 184 | }; |
184 | 185 | ||
185 | static struct ieee80211_channel __wl_5ghz_n_channels[] = { | ||
186 | CHAN5G(32, 0), CHAN5G(34, 0), | ||
187 | CHAN5G(36, 0), CHAN5G(38, 0), | ||
188 | CHAN5G(40, 0), CHAN5G(42, 0), | ||
189 | CHAN5G(44, 0), CHAN5G(46, 0), | ||
190 | CHAN5G(48, 0), CHAN5G(50, 0), | ||
191 | CHAN5G(52, 0), CHAN5G(54, 0), | ||
192 | CHAN5G(56, 0), CHAN5G(58, 0), | ||
193 | CHAN5G(60, 0), CHAN5G(62, 0), | ||
194 | CHAN5G(64, 0), CHAN5G(66, 0), | ||
195 | CHAN5G(68, 0), CHAN5G(70, 0), | ||
196 | CHAN5G(72, 0), CHAN5G(74, 0), | ||
197 | CHAN5G(76, 0), CHAN5G(78, 0), | ||
198 | CHAN5G(80, 0), CHAN5G(82, 0), | ||
199 | CHAN5G(84, 0), CHAN5G(86, 0), | ||
200 | CHAN5G(88, 0), CHAN5G(90, 0), | ||
201 | CHAN5G(92, 0), CHAN5G(94, 0), | ||
202 | CHAN5G(96, 0), CHAN5G(98, 0), | ||
203 | CHAN5G(100, 0), CHAN5G(102, 0), | ||
204 | CHAN5G(104, 0), CHAN5G(106, 0), | ||
205 | CHAN5G(108, 0), CHAN5G(110, 0), | ||
206 | CHAN5G(112, 0), CHAN5G(114, 0), | ||
207 | CHAN5G(116, 0), CHAN5G(118, 0), | ||
208 | CHAN5G(120, 0), CHAN5G(122, 0), | ||
209 | CHAN5G(124, 0), CHAN5G(126, 0), | ||
210 | CHAN5G(128, 0), CHAN5G(130, 0), | ||
211 | CHAN5G(132, 0), CHAN5G(134, 0), | ||
212 | CHAN5G(136, 0), CHAN5G(138, 0), | ||
213 | CHAN5G(140, 0), CHAN5G(142, 0), | ||
214 | CHAN5G(144, 0), CHAN5G(145, 0), | ||
215 | CHAN5G(146, 0), CHAN5G(147, 0), | ||
216 | CHAN5G(148, 0), CHAN5G(149, 0), | ||
217 | CHAN5G(150, 0), CHAN5G(151, 0), | ||
218 | CHAN5G(152, 0), CHAN5G(153, 0), | ||
219 | CHAN5G(154, 0), CHAN5G(155, 0), | ||
220 | CHAN5G(156, 0), CHAN5G(157, 0), | ||
221 | CHAN5G(158, 0), CHAN5G(159, 0), | ||
222 | CHAN5G(160, 0), CHAN5G(161, 0), | ||
223 | CHAN5G(162, 0), CHAN5G(163, 0), | ||
224 | CHAN5G(164, 0), CHAN5G(165, 0), | ||
225 | CHAN5G(166, 0), CHAN5G(168, 0), | ||
226 | CHAN5G(170, 0), CHAN5G(172, 0), | ||
227 | CHAN5G(174, 0), CHAN5G(176, 0), | ||
228 | CHAN5G(178, 0), CHAN5G(180, 0), | ||
229 | CHAN5G(182, 0), CHAN5G(184, 0), | ||
230 | CHAN5G(186, 0), CHAN5G(188, 0), | ||
231 | CHAN5G(190, 0), CHAN5G(192, 0), | ||
232 | CHAN5G(194, 0), CHAN5G(196, 0), | ||
233 | CHAN5G(198, 0), CHAN5G(200, 0), | ||
234 | CHAN5G(202, 0), CHAN5G(204, 0), | ||
235 | CHAN5G(206, 0), CHAN5G(208, 0), | ||
236 | CHAN5G(210, 0), CHAN5G(212, 0), | ||
237 | CHAN5G(214, 0), CHAN5G(216, 0), | ||
238 | CHAN5G(218, 0), CHAN5G(220, 0), | ||
239 | CHAN5G(222, 0), CHAN5G(224, 0), | ||
240 | CHAN5G(226, 0), CHAN5G(228, 0), | ||
241 | }; | ||
242 | |||
243 | static struct ieee80211_supported_band __wl_band_2ghz = { | 186 | static struct ieee80211_supported_band __wl_band_2ghz = { |
244 | .band = IEEE80211_BAND_2GHZ, | 187 | .band = IEEE80211_BAND_2GHZ, |
245 | .channels = __wl_2ghz_channels, | 188 | .channels = __wl_2ghz_channels, |
@@ -256,12 +199,28 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = { | |||
256 | .n_bitrates = wl_a_rates_size, | 199 | .n_bitrates = wl_a_rates_size, |
257 | }; | 200 | }; |
258 | 201 | ||
259 | static struct ieee80211_supported_band __wl_band_5ghz_n = { | 202 | /* This is to override regulatory domains defined in cfg80211 module (reg.c) |
260 | .band = IEEE80211_BAND_5GHZ, | 203 | * By default world regulatory domain defined in reg.c puts the flags |
261 | .channels = __wl_5ghz_n_channels, | 204 | * NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for |
262 | .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels), | 205 | * 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't |
263 | .bitrates = wl_a_rates, | 206 | * start p2p operations on 5GHz channels. All the changes in world regulatory |
264 | .n_bitrates = wl_a_rates_size, | 207 | * domain are to be done here. |
208 | */ | ||
209 | static const struct ieee80211_regdomain brcmf_regdom = { | ||
210 | .n_reg_rules = 4, | ||
211 | .alpha2 = "99", | ||
212 | .reg_rules = { | ||
213 | /* IEEE 802.11b/g, channels 1..11 */ | ||
214 | REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), | ||
215 | /* If any */ | ||
216 | /* IEEE 802.11 channel 14 - Only JP enables | ||
217 | * this and for 802.11b only | ||
218 | */ | ||
219 | REG_RULE(2484-10, 2484+10, 20, 6, 20, 0), | ||
220 | /* IEEE 802.11a, channel 36..64 */ | ||
221 | REG_RULE(5150-10, 5350+10, 40, 6, 20, 0), | ||
222 | /* IEEE 802.11a, channel 100..165 */ | ||
223 | REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), } | ||
265 | }; | 224 | }; |
266 | 225 | ||
267 | static const u32 __wl_cipher_suites[] = { | 226 | static const u32 __wl_cipher_suites[] = { |
@@ -375,22 +334,16 @@ static u8 brcmf_mw_to_qdbm(u16 mw) | |||
375 | return qdbm; | 334 | return qdbm; |
376 | } | 335 | } |
377 | 336 | ||
378 | u16 channel_to_chanspec(struct ieee80211_channel *ch) | 337 | u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, |
338 | struct ieee80211_channel *ch) | ||
379 | { | 339 | { |
380 | u16 chanspec; | 340 | struct brcmu_chan ch_inf; |
381 | 341 | ||
382 | chanspec = ieee80211_frequency_to_channel(ch->center_freq); | 342 | ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq); |
383 | chanspec &= WL_CHANSPEC_CHAN_MASK; | 343 | ch_inf.bw = BRCMU_CHAN_BW_20; |
344 | d11inf->encchspec(&ch_inf); | ||
384 | 345 | ||
385 | if (ch->band == IEEE80211_BAND_2GHZ) | 346 | return ch_inf.chspec; |
386 | chanspec |= WL_CHANSPEC_BAND_2G; | ||
387 | else | ||
388 | chanspec |= WL_CHANSPEC_BAND_5G; | ||
389 | |||
390 | chanspec |= WL_CHANSPEC_BW_20; | ||
391 | chanspec |= WL_CHANSPEC_CTL_SB_NONE; | ||
392 | |||
393 | return chanspec; | ||
394 | } | 347 | } |
395 | 348 | ||
396 | /* Traverse a string of 1-byte tag/1-byte length/variable-length value | 349 | /* Traverse a string of 1-byte tag/1-byte length/variable-length value |
@@ -523,17 +476,16 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, | |||
523 | return ERR_PTR(-EOPNOTSUPP); | 476 | return ERR_PTR(-EOPNOTSUPP); |
524 | case NL80211_IFTYPE_P2P_CLIENT: | 477 | case NL80211_IFTYPE_P2P_CLIENT: |
525 | case NL80211_IFTYPE_P2P_GO: | 478 | case NL80211_IFTYPE_P2P_GO: |
479 | case NL80211_IFTYPE_P2P_DEVICE: | ||
526 | return brcmf_p2p_add_vif(wiphy, name, type, flags, params); | 480 | return brcmf_p2p_add_vif(wiphy, name, type, flags, params); |
527 | case NL80211_IFTYPE_UNSPECIFIED: | 481 | case NL80211_IFTYPE_UNSPECIFIED: |
528 | case NL80211_IFTYPE_P2P_DEVICE: | ||
529 | default: | 482 | default: |
530 | return ERR_PTR(-EINVAL); | 483 | return ERR_PTR(-EINVAL); |
531 | } | 484 | } |
532 | } | 485 | } |
533 | 486 | ||
534 | void brcmf_set_mpc(struct net_device *ndev, int mpc) | 487 | void brcmf_set_mpc(struct brcmf_if *ifp, int mpc) |
535 | { | 488 | { |
536 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
537 | s32 err = 0; | 489 | s32 err = 0; |
538 | 490 | ||
539 | if (check_vif_up(ifp->vif)) { | 491 | if (check_vif_up(ifp->vif)) { |
@@ -546,10 +498,9 @@ void brcmf_set_mpc(struct net_device *ndev, int mpc) | |||
546 | } | 498 | } |
547 | } | 499 | } |
548 | 500 | ||
549 | s32 | 501 | s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, |
550 | brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | 502 | struct brcmf_if *ifp, bool aborted, |
551 | struct net_device *ndev, | 503 | bool fw_abort) |
552 | bool aborted, bool fw_abort) | ||
553 | { | 504 | { |
554 | struct brcmf_scan_params_le params_le; | 505 | struct brcmf_scan_params_le params_le; |
555 | struct cfg80211_scan_request *scan_request; | 506 | struct cfg80211_scan_request *scan_request; |
@@ -580,7 +531,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | |||
580 | /* Scan is aborted by setting channel_list[0] to -1 */ | 531 | /* Scan is aborted by setting channel_list[0] to -1 */ |
581 | params_le.channel_list[0] = cpu_to_le16(-1); | 532 | params_le.channel_list[0] = cpu_to_le16(-1); |
582 | /* E-Scan (or anyother type) can be aborted by SCAN */ | 533 | /* E-Scan (or anyother type) can be aborted by SCAN */ |
583 | err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN, | 534 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, |
584 | ¶ms_le, sizeof(params_le)); | 535 | ¶ms_le, sizeof(params_le)); |
585 | if (err) | 536 | if (err) |
586 | brcmf_err("Scan abort failed\n"); | 537 | brcmf_err("Scan abort failed\n"); |
@@ -594,12 +545,12 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | |||
594 | cfg->sched_escan = false; | 545 | cfg->sched_escan = false; |
595 | if (!aborted) | 546 | if (!aborted) |
596 | cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); | 547 | cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); |
597 | brcmf_set_mpc(ndev, 1); | 548 | brcmf_set_mpc(ifp, 1); |
598 | } else if (scan_request) { | 549 | } else if (scan_request) { |
599 | brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n", | 550 | brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n", |
600 | aborted ? "Aborted" : "Done"); | 551 | aborted ? "Aborted" : "Done"); |
601 | cfg80211_scan_done(scan_request, aborted); | 552 | cfg80211_scan_done(scan_request, aborted); |
602 | brcmf_set_mpc(ndev, 1); | 553 | brcmf_set_mpc(ifp, 1); |
603 | } | 554 | } |
604 | if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) | 555 | if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) |
605 | brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n"); | 556 | brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n"); |
@@ -619,9 +570,9 @@ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
619 | 570 | ||
620 | if (ndev) { | 571 | if (ndev) { |
621 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) && | 572 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) && |
622 | cfg->escan_info.ndev == ndev) | 573 | cfg->escan_info.ifp == netdev_priv(ndev)) |
623 | brcmf_notify_escan_complete(cfg, ndev, true, | 574 | brcmf_notify_escan_complete(cfg, netdev_priv(ndev), |
624 | true); | 575 | true, true); |
625 | 576 | ||
626 | brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1); | 577 | brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1); |
627 | } | 578 | } |
@@ -637,9 +588,9 @@ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
637 | return -EOPNOTSUPP; | 588 | return -EOPNOTSUPP; |
638 | case NL80211_IFTYPE_P2P_CLIENT: | 589 | case NL80211_IFTYPE_P2P_CLIENT: |
639 | case NL80211_IFTYPE_P2P_GO: | 590 | case NL80211_IFTYPE_P2P_GO: |
591 | case NL80211_IFTYPE_P2P_DEVICE: | ||
640 | return brcmf_p2p_del_vif(wiphy, wdev); | 592 | return brcmf_p2p_del_vif(wiphy, wdev); |
641 | case NL80211_IFTYPE_UNSPECIFIED: | 593 | case NL80211_IFTYPE_UNSPECIFIED: |
642 | case NL80211_IFTYPE_P2P_DEVICE: | ||
643 | default: | 594 | default: |
644 | return -EINVAL; | 595 | return -EINVAL; |
645 | } | 596 | } |
@@ -723,7 +674,8 @@ done: | |||
723 | return err; | 674 | return err; |
724 | } | 675 | } |
725 | 676 | ||
726 | static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, | 677 | static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, |
678 | struct brcmf_scan_params_le *params_le, | ||
727 | struct cfg80211_scan_request *request) | 679 | struct cfg80211_scan_request *request) |
728 | { | 680 | { |
729 | u32 n_ssids; | 681 | u32 n_ssids; |
@@ -755,7 +707,8 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, | |||
755 | n_channels); | 707 | n_channels); |
756 | if (n_channels > 0) { | 708 | if (n_channels > 0) { |
757 | for (i = 0; i < n_channels; i++) { | 709 | for (i = 0; i < n_channels; i++) { |
758 | chanspec = channel_to_chanspec(request->channels[i]); | 710 | chanspec = channel_to_chanspec(&cfg->d11inf, |
711 | request->channels[i]); | ||
759 | brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n", | 712 | brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n", |
760 | request->channels[i]->hw_value, chanspec); | 713 | request->channels[i]->hw_value, chanspec); |
761 | params_le->channel_list[i] = cpu_to_le16(chanspec); | 714 | params_le->channel_list[i] = cpu_to_le16(chanspec); |
@@ -803,7 +756,7 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, | |||
803 | } | 756 | } |
804 | 757 | ||
805 | static s32 | 758 | static s32 |
806 | brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, | 759 | brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, |
807 | struct cfg80211_scan_request *request, u16 action) | 760 | struct cfg80211_scan_request *request, u16 action) |
808 | { | 761 | { |
809 | s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + | 762 | s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + |
@@ -827,13 +780,12 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, | |||
827 | goto exit; | 780 | goto exit; |
828 | } | 781 | } |
829 | BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN); | 782 | BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN); |
830 | brcmf_escan_prep(¶ms->params_le, request); | 783 | brcmf_escan_prep(cfg, ¶ms->params_le, request); |
831 | params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION); | 784 | params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION); |
832 | params->action = cpu_to_le16(action); | 785 | params->action = cpu_to_le16(action); |
833 | params->sync_id = cpu_to_le16(0x1234); | 786 | params->sync_id = cpu_to_le16(0x1234); |
834 | 787 | ||
835 | err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan", | 788 | err = brcmf_fil_iovar_data_set(ifp, "escan", params, params_size); |
836 | params, params_size); | ||
837 | if (err) { | 789 | if (err) { |
838 | if (err == -EBUSY) | 790 | if (err == -EBUSY) |
839 | brcmf_dbg(INFO, "system busy : escan canceled\n"); | 791 | brcmf_dbg(INFO, "system busy : escan canceled\n"); |
@@ -848,7 +800,7 @@ exit: | |||
848 | 800 | ||
849 | static s32 | 801 | static s32 |
850 | brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, | 802 | brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, |
851 | struct net_device *ndev, struct cfg80211_scan_request *request) | 803 | struct brcmf_if *ifp, struct cfg80211_scan_request *request) |
852 | { | 804 | { |
853 | s32 err; | 805 | s32 err; |
854 | u32 passive_scan; | 806 | u32 passive_scan; |
@@ -856,35 +808,35 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, | |||
856 | struct escan_info *escan = &cfg->escan_info; | 808 | struct escan_info *escan = &cfg->escan_info; |
857 | 809 | ||
858 | brcmf_dbg(SCAN, "Enter\n"); | 810 | brcmf_dbg(SCAN, "Enter\n"); |
859 | escan->ndev = ndev; | 811 | escan->ifp = ifp; |
860 | escan->wiphy = wiphy; | 812 | escan->wiphy = wiphy; |
861 | escan->escan_state = WL_ESCAN_STATE_SCANNING; | 813 | escan->escan_state = WL_ESCAN_STATE_SCANNING; |
862 | passive_scan = cfg->active_scan ? 0 : 1; | 814 | passive_scan = cfg->active_scan ? 0 : 1; |
863 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN, | 815 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, |
864 | passive_scan); | 816 | passive_scan); |
865 | if (err) { | 817 | if (err) { |
866 | brcmf_err("error (%d)\n", err); | 818 | brcmf_err("error (%d)\n", err); |
867 | return err; | 819 | return err; |
868 | } | 820 | } |
869 | brcmf_set_mpc(ndev, 0); | 821 | brcmf_set_mpc(ifp, 0); |
870 | results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf; | 822 | results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf; |
871 | results->version = 0; | 823 | results->version = 0; |
872 | results->count = 0; | 824 | results->count = 0; |
873 | results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE; | 825 | results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE; |
874 | 826 | ||
875 | err = escan->run(cfg, ndev, request, WL_ESCAN_ACTION_START); | 827 | err = escan->run(cfg, ifp, request, WL_ESCAN_ACTION_START); |
876 | if (err) | 828 | if (err) |
877 | brcmf_set_mpc(ndev, 1); | 829 | brcmf_set_mpc(ifp, 1); |
878 | return err; | 830 | return err; |
879 | } | 831 | } |
880 | 832 | ||
881 | static s32 | 833 | static s32 |
882 | brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | 834 | brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, |
883 | struct cfg80211_scan_request *request, | 835 | struct cfg80211_scan_request *request, |
884 | struct cfg80211_ssid *this_ssid) | 836 | struct cfg80211_ssid *this_ssid) |
885 | { | 837 | { |
886 | struct brcmf_if *ifp = netdev_priv(ndev); | 838 | struct brcmf_if *ifp = vif->ifp; |
887 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | 839 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
888 | struct cfg80211_ssid *ssids; | 840 | struct cfg80211_ssid *ssids; |
889 | struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int; | 841 | struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int; |
890 | u32 passive_scan; | 842 | u32 passive_scan; |
@@ -910,10 +862,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
910 | } | 862 | } |
911 | 863 | ||
912 | /* If scan req comes for p2p0, send it over primary I/F */ | 864 | /* If scan req comes for p2p0, send it over primary I/F */ |
913 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) { | 865 | if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) |
914 | ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 866 | vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; |
915 | ndev = ifp->ndev; | ||
916 | } | ||
917 | 867 | ||
918 | /* Arm scan timeout timer */ | 868 | /* Arm scan timeout timer */ |
919 | mod_timer(&cfg->escan_timeout, jiffies + | 869 | mod_timer(&cfg->escan_timeout, jiffies + |
@@ -934,11 +884,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
934 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 884 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
935 | if (escan_req) { | 885 | if (escan_req) { |
936 | cfg->escan_info.run = brcmf_run_escan; | 886 | cfg->escan_info.run = brcmf_run_escan; |
937 | err = brcmf_p2p_scan_prep(wiphy, request, ifp->vif); | 887 | err = brcmf_p2p_scan_prep(wiphy, request, vif); |
938 | if (err) | 888 | if (err) |
939 | goto scan_out; | 889 | goto scan_out; |
940 | 890 | ||
941 | err = brcmf_do_escan(cfg, wiphy, ndev, request); | 891 | err = brcmf_do_escan(cfg, wiphy, vif->ifp, request); |
942 | if (err) | 892 | if (err) |
943 | goto scan_out; | 893 | goto scan_out; |
944 | } else { | 894 | } else { |
@@ -962,7 +912,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
962 | brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err); | 912 | brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err); |
963 | goto scan_out; | 913 | goto scan_out; |
964 | } | 914 | } |
965 | brcmf_set_mpc(ndev, 0); | 915 | brcmf_set_mpc(ifp, 0); |
966 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, | 916 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, |
967 | &sr->ssid_le, sizeof(sr->ssid_le)); | 917 | &sr->ssid_le, sizeof(sr->ssid_le)); |
968 | if (err) { | 918 | if (err) { |
@@ -972,7 +922,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
972 | else | 922 | else |
973 | brcmf_err("WLC_SCAN error (%d)\n", err); | 923 | brcmf_err("WLC_SCAN error (%d)\n", err); |
974 | 924 | ||
975 | brcmf_set_mpc(ndev, 1); | 925 | brcmf_set_mpc(ifp, 1); |
976 | goto scan_out; | 926 | goto scan_out; |
977 | } | 927 | } |
978 | } | 928 | } |
@@ -990,16 +940,15 @@ scan_out: | |||
990 | static s32 | 940 | static s32 |
991 | brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) | 941 | brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) |
992 | { | 942 | { |
993 | struct net_device *ndev = request->wdev->netdev; | 943 | struct brcmf_cfg80211_vif *vif; |
994 | s32 err = 0; | 944 | s32 err = 0; |
995 | 945 | ||
996 | brcmf_dbg(TRACE, "Enter\n"); | 946 | brcmf_dbg(TRACE, "Enter\n"); |
997 | 947 | vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev); | |
998 | if (!check_vif_up(container_of(request->wdev, | 948 | if (!check_vif_up(vif)) |
999 | struct brcmf_cfg80211_vif, wdev))) | ||
1000 | return -EIO; | 949 | return -EIO; |
1001 | 950 | ||
1002 | err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL); | 951 | err = brcmf_cfg80211_escan(wiphy, vif, request, NULL); |
1003 | 952 | ||
1004 | if (err) | 953 | if (err) |
1005 | brcmf_err("scan error (%d)\n", err); | 954 | brcmf_err("scan error (%d)\n", err); |
@@ -1229,7 +1178,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
1229 | params->chandef.chan->center_freq); | 1178 | params->chandef.chan->center_freq); |
1230 | if (params->channel_fixed) { | 1179 | if (params->channel_fixed) { |
1231 | /* adding chanspec */ | 1180 | /* adding chanspec */ |
1232 | chanspec = channel_to_chanspec(params->chandef.chan); | 1181 | chanspec = channel_to_chanspec(&cfg->d11inf, |
1182 | params->chandef.chan); | ||
1233 | join_params.params_le.chanspec_list[0] = | 1183 | join_params.params_le.chanspec_list[0] = |
1234 | cpu_to_le16(chanspec); | 1184 | cpu_to_le16(chanspec); |
1235 | join_params.params_le.chanspec_num = cpu_to_le32(1); | 1185 | join_params.params_le.chanspec_num = cpu_to_le32(1); |
@@ -1619,7 +1569,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1619 | if (chan) { | 1569 | if (chan) { |
1620 | cfg->channel = | 1570 | cfg->channel = |
1621 | ieee80211_frequency_to_channel(chan->center_freq); | 1571 | ieee80211_frequency_to_channel(chan->center_freq); |
1622 | chanspec = channel_to_chanspec(chan); | 1572 | chanspec = channel_to_chanspec(&cfg->d11inf, chan); |
1623 | brcmf_dbg(CONN, "channel=%d, center_req=%d, chanspec=0x%04x\n", | 1573 | brcmf_dbg(CONN, "channel=%d, center_req=%d, chanspec=0x%04x\n", |
1624 | cfg->channel, chan->center_freq, chanspec); | 1574 | cfg->channel, chan->center_freq, chanspec); |
1625 | } else { | 1575 | } else { |
@@ -1891,8 +1841,10 @@ static s32 | |||
1891 | brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, | 1841 | brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, |
1892 | u8 key_idx, const u8 *mac_addr, struct key_params *params) | 1842 | u8 key_idx, const u8 *mac_addr, struct key_params *params) |
1893 | { | 1843 | { |
1844 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
1894 | struct brcmf_wsec_key key; | 1845 | struct brcmf_wsec_key key; |
1895 | s32 err = 0; | 1846 | s32 err = 0; |
1847 | u8 keybuf[8]; | ||
1896 | 1848 | ||
1897 | memset(&key, 0, sizeof(key)); | 1849 | memset(&key, 0, sizeof(key)); |
1898 | key.index = (u32) key_idx; | 1850 | key.index = (u32) key_idx; |
@@ -1916,8 +1868,9 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, | |||
1916 | brcmf_dbg(CONN, "Setting the key index %d\n", key.index); | 1868 | brcmf_dbg(CONN, "Setting the key index %d\n", key.index); |
1917 | memcpy(key.data, params->key, key.len); | 1869 | memcpy(key.data, params->key, key.len); |
1918 | 1870 | ||
1919 | if (params->cipher == WLAN_CIPHER_SUITE_TKIP) { | 1871 | if ((ifp->vif->mode != WL_MODE_AP) && |
1920 | u8 keybuf[8]; | 1872 | (params->cipher == WLAN_CIPHER_SUITE_TKIP)) { |
1873 | brcmf_dbg(CONN, "Swapping RX/TX MIC key\n"); | ||
1921 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); | 1874 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); |
1922 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); | 1875 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); |
1923 | memcpy(&key.data[16], keybuf, sizeof(keybuf)); | 1876 | memcpy(&key.data[16], keybuf, sizeof(keybuf)); |
@@ -2013,7 +1966,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2013 | break; | 1966 | break; |
2014 | case WLAN_CIPHER_SUITE_TKIP: | 1967 | case WLAN_CIPHER_SUITE_TKIP: |
2015 | if (ifp->vif->mode != WL_MODE_AP) { | 1968 | if (ifp->vif->mode != WL_MODE_AP) { |
2016 | brcmf_dbg(CONN, "Swapping key\n"); | 1969 | brcmf_dbg(CONN, "Swapping RX/TX MIC key\n"); |
2017 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); | 1970 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); |
2018 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); | 1971 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); |
2019 | memcpy(&key.data[16], keybuf, sizeof(keybuf)); | 1972 | memcpy(&key.data[16], keybuf, sizeof(keybuf)); |
@@ -2118,8 +2071,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2118 | err = -EAGAIN; | 2071 | err = -EAGAIN; |
2119 | goto done; | 2072 | goto done; |
2120 | } | 2073 | } |
2121 | switch (wsec & ~SES_OW_ENABLED) { | 2074 | if (wsec & WEP_ENABLED) { |
2122 | case WEP_ENABLED: | ||
2123 | sec = &profile->sec; | 2075 | sec = &profile->sec; |
2124 | if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { | 2076 | if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { |
2125 | params.cipher = WLAN_CIPHER_SUITE_WEP40; | 2077 | params.cipher = WLAN_CIPHER_SUITE_WEP40; |
@@ -2128,16 +2080,13 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2128 | params.cipher = WLAN_CIPHER_SUITE_WEP104; | 2080 | params.cipher = WLAN_CIPHER_SUITE_WEP104; |
2129 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n"); | 2081 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n"); |
2130 | } | 2082 | } |
2131 | break; | 2083 | } else if (wsec & TKIP_ENABLED) { |
2132 | case TKIP_ENABLED: | ||
2133 | params.cipher = WLAN_CIPHER_SUITE_TKIP; | 2084 | params.cipher = WLAN_CIPHER_SUITE_TKIP; |
2134 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n"); | 2085 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n"); |
2135 | break; | 2086 | } else if (wsec & AES_ENABLED) { |
2136 | case AES_ENABLED: | ||
2137 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; | 2087 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; |
2138 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n"); | 2088 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n"); |
2139 | break; | 2089 | } else { |
2140 | default: | ||
2141 | brcmf_err("Invalid algo (0x%x)\n", wsec); | 2090 | brcmf_err("Invalid algo (0x%x)\n", wsec); |
2142 | err = -EINVAL; | 2091 | err = -EINVAL; |
2143 | goto done; | 2092 | goto done; |
@@ -2279,6 +2228,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, | |||
2279 | struct ieee80211_channel *notify_channel; | 2228 | struct ieee80211_channel *notify_channel; |
2280 | struct cfg80211_bss *bss; | 2229 | struct cfg80211_bss *bss; |
2281 | struct ieee80211_supported_band *band; | 2230 | struct ieee80211_supported_band *band; |
2231 | struct brcmu_chan ch; | ||
2282 | s32 err = 0; | 2232 | s32 err = 0; |
2283 | u16 channel; | 2233 | u16 channel; |
2284 | u32 freq; | 2234 | u32 freq; |
@@ -2293,8 +2243,12 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, | |||
2293 | return 0; | 2243 | return 0; |
2294 | } | 2244 | } |
2295 | 2245 | ||
2296 | channel = bi->ctl_ch ? bi->ctl_ch : | 2246 | if (!bi->ctl_ch) { |
2297 | CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); | 2247 | ch.chspec = le16_to_cpu(bi->chanspec); |
2248 | cfg->d11inf.decchspec(&ch); | ||
2249 | bi->ctl_ch = ch.chnum; | ||
2250 | } | ||
2251 | channel = bi->ctl_ch; | ||
2298 | 2252 | ||
2299 | if (channel <= CH_MAX_2G_CHANNEL) | 2253 | if (channel <= CH_MAX_2G_CHANNEL) |
2300 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; | 2254 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; |
@@ -2369,9 +2323,9 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, | |||
2369 | struct brcmf_bss_info_le *bi = NULL; | 2323 | struct brcmf_bss_info_le *bi = NULL; |
2370 | struct ieee80211_supported_band *band; | 2324 | struct ieee80211_supported_band *band; |
2371 | struct cfg80211_bss *bss; | 2325 | struct cfg80211_bss *bss; |
2326 | struct brcmu_chan ch; | ||
2372 | u8 *buf = NULL; | 2327 | u8 *buf = NULL; |
2373 | s32 err = 0; | 2328 | s32 err = 0; |
2374 | u16 channel; | ||
2375 | u32 freq; | 2329 | u32 freq; |
2376 | u16 notify_capability; | 2330 | u16 notify_capability; |
2377 | u16 notify_interval; | 2331 | u16 notify_interval; |
@@ -2398,15 +2352,15 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, | |||
2398 | 2352 | ||
2399 | bi = (struct brcmf_bss_info_le *)(buf + 4); | 2353 | bi = (struct brcmf_bss_info_le *)(buf + 4); |
2400 | 2354 | ||
2401 | channel = bi->ctl_ch ? bi->ctl_ch : | 2355 | ch.chspec = le16_to_cpu(bi->chanspec); |
2402 | CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); | 2356 | cfg->d11inf.decchspec(&ch); |
2403 | 2357 | ||
2404 | if (channel <= CH_MAX_2G_CHANNEL) | 2358 | if (ch.band == BRCMU_CHAN_BAND_2G) |
2405 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; | 2359 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; |
2406 | else | 2360 | else |
2407 | band = wiphy->bands[IEEE80211_BAND_5GHZ]; | 2361 | band = wiphy->bands[IEEE80211_BAND_5GHZ]; |
2408 | 2362 | ||
2409 | freq = ieee80211_channel_to_frequency(channel, band->band); | 2363 | freq = ieee80211_channel_to_frequency(ch.chnum, band->band); |
2410 | notify_channel = ieee80211_get_channel(wiphy, freq); | 2364 | notify_channel = ieee80211_get_channel(wiphy, freq); |
2411 | 2365 | ||
2412 | notify_capability = le16_to_cpu(bi->capability); | 2366 | notify_capability = le16_to_cpu(bi->capability); |
@@ -2415,7 +2369,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, | |||
2415 | notify_ielen = le32_to_cpu(bi->ie_length); | 2369 | notify_ielen = le32_to_cpu(bi->ie_length); |
2416 | notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100; | 2370 | notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100; |
2417 | 2371 | ||
2418 | brcmf_dbg(CONN, "channel: %d(%d)\n", channel, freq); | 2372 | brcmf_dbg(CONN, "channel: %d(%d)\n", ch.chnum, freq); |
2419 | brcmf_dbg(CONN, "capability: %X\n", notify_capability); | 2373 | brcmf_dbg(CONN, "capability: %X\n", notify_capability); |
2420 | brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval); | 2374 | brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval); |
2421 | brcmf_dbg(CONN, "signal: %d\n", notify_signal); | 2375 | brcmf_dbg(CONN, "signal: %d\n", notify_signal); |
@@ -2511,7 +2465,7 @@ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) | |||
2511 | set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); | 2465 | set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); |
2512 | if (cfg->scan_request) { | 2466 | if (cfg->scan_request) { |
2513 | escan->escan_state = WL_ESCAN_STATE_IDLE; | 2467 | escan->escan_state = WL_ESCAN_STATE_IDLE; |
2514 | brcmf_notify_escan_complete(cfg, escan->ndev, true, true); | 2468 | brcmf_notify_escan_complete(cfg, escan->ifp, true, true); |
2515 | } | 2469 | } |
2516 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 2470 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
2517 | clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); | 2471 | clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); |
@@ -2523,7 +2477,7 @@ static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work) | |||
2523 | container_of(work, struct brcmf_cfg80211_info, | 2477 | container_of(work, struct brcmf_cfg80211_info, |
2524 | escan_timeout_work); | 2478 | escan_timeout_work); |
2525 | 2479 | ||
2526 | brcmf_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true); | 2480 | brcmf_notify_escan_complete(cfg, cfg->escan_info.ifp, true, true); |
2527 | } | 2481 | } |
2528 | 2482 | ||
2529 | static void brcmf_escan_timeout(unsigned long data) | 2483 | static void brcmf_escan_timeout(unsigned long data) |
@@ -2538,12 +2492,19 @@ static void brcmf_escan_timeout(unsigned long data) | |||
2538 | } | 2492 | } |
2539 | 2493 | ||
2540 | static s32 | 2494 | static s32 |
2541 | brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss, | 2495 | brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg, |
2496 | struct brcmf_bss_info_le *bss, | ||
2542 | struct brcmf_bss_info_le *bss_info_le) | 2497 | struct brcmf_bss_info_le *bss_info_le) |
2543 | { | 2498 | { |
2499 | struct brcmu_chan ch_bss, ch_bss_info_le; | ||
2500 | |||
2501 | ch_bss.chspec = le16_to_cpu(bss->chanspec); | ||
2502 | cfg->d11inf.decchspec(&ch_bss); | ||
2503 | ch_bss_info_le.chspec = le16_to_cpu(bss_info_le->chanspec); | ||
2504 | cfg->d11inf.decchspec(&ch_bss_info_le); | ||
2505 | |||
2544 | if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) && | 2506 | if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) && |
2545 | (CHSPEC_BAND(le16_to_cpu(bss_info_le->chanspec)) == | 2507 | ch_bss.band == ch_bss_info_le.band && |
2546 | CHSPEC_BAND(le16_to_cpu(bss->chanspec))) && | ||
2547 | bss_info_le->SSID_len == bss->SSID_len && | 2508 | bss_info_le->SSID_len == bss->SSID_len && |
2548 | !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) { | 2509 | !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) { |
2549 | if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == | 2510 | if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == |
@@ -2574,7 +2535,6 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
2574 | const struct brcmf_event_msg *e, void *data) | 2535 | const struct brcmf_event_msg *e, void *data) |
2575 | { | 2536 | { |
2576 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | 2537 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; |
2577 | struct net_device *ndev = ifp->ndev; | ||
2578 | s32 status; | 2538 | s32 status; |
2579 | s32 err = 0; | 2539 | s32 err = 0; |
2580 | struct brcmf_escan_result_le *escan_result_le; | 2540 | struct brcmf_escan_result_le *escan_result_le; |
@@ -2587,9 +2547,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
2587 | 2547 | ||
2588 | status = e->status; | 2548 | status = e->status; |
2589 | 2549 | ||
2590 | if (!ndev || !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | 2550 | if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
2591 | brcmf_err("scan not ready ndev %p drv_status %x\n", ndev, | 2551 | brcmf_err("scan not ready, bssidx=%d\n", ifp->bssidx); |
2592 | !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)); | ||
2593 | return -EPERM; | 2552 | return -EPERM; |
2594 | } | 2553 | } |
2595 | 2554 | ||
@@ -2643,7 +2602,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
2643 | bss = bss ? (struct brcmf_bss_info_le *) | 2602 | bss = bss ? (struct brcmf_bss_info_le *) |
2644 | ((unsigned char *)bss + | 2603 | ((unsigned char *)bss + |
2645 | le32_to_cpu(bss->length)) : list->bss_info_le; | 2604 | le32_to_cpu(bss->length)) : list->bss_info_le; |
2646 | if (brcmf_compare_update_same_bss(bss, bss_info_le)) | 2605 | if (brcmf_compare_update_same_bss(cfg, bss, |
2606 | bss_info_le)) | ||
2647 | goto exit; | 2607 | goto exit; |
2648 | } | 2608 | } |
2649 | memcpy(&(cfg->escan_info.escan_buf[list->buflen]), | 2609 | memcpy(&(cfg->escan_info.escan_buf[list->buflen]), |
@@ -2660,7 +2620,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
2660 | cfg->escan_info.escan_buf; | 2620 | cfg->escan_info.escan_buf; |
2661 | brcmf_inform_bss(cfg); | 2621 | brcmf_inform_bss(cfg); |
2662 | aborted = status != BRCMF_E_STATUS_SUCCESS; | 2622 | aborted = status != BRCMF_E_STATUS_SUCCESS; |
2663 | brcmf_notify_escan_complete(cfg, ndev, aborted, | 2623 | brcmf_notify_escan_complete(cfg, ifp, aborted, |
2664 | false); | 2624 | false); |
2665 | } else | 2625 | } else |
2666 | brcmf_dbg(SCAN, "Ignored scan complete result 0x%x\n", | 2626 | brcmf_dbg(SCAN, "Ignored scan complete result 0x%x\n", |
@@ -2738,7 +2698,7 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, | |||
2738 | brcmf_abort_scanning(cfg); | 2698 | brcmf_abort_scanning(cfg); |
2739 | 2699 | ||
2740 | /* Turn off watchdog timer */ | 2700 | /* Turn off watchdog timer */ |
2741 | brcmf_set_mpc(ndev, 1); | 2701 | brcmf_set_mpc(netdev_priv(ndev), 1); |
2742 | 2702 | ||
2743 | exit: | 2703 | exit: |
2744 | brcmf_dbg(TRACE, "Exit\n"); | 2704 | brcmf_dbg(TRACE, "Exit\n"); |
@@ -2896,7 +2856,6 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, | |||
2896 | const struct brcmf_event_msg *e, void *data) | 2856 | const struct brcmf_event_msg *e, void *data) |
2897 | { | 2857 | { |
2898 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | 2858 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; |
2899 | struct net_device *ndev = ifp->ndev; | ||
2900 | struct brcmf_pno_net_info_le *netinfo, *netinfo_start; | 2859 | struct brcmf_pno_net_info_le *netinfo, *netinfo_start; |
2901 | struct cfg80211_scan_request *request = NULL; | 2860 | struct cfg80211_scan_request *request = NULL; |
2902 | struct cfg80211_ssid *ssid = NULL; | 2861 | struct cfg80211_ssid *ssid = NULL; |
@@ -2980,7 +2939,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, | |||
2980 | } | 2939 | } |
2981 | 2940 | ||
2982 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 2941 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
2983 | err = brcmf_do_escan(cfg, wiphy, ndev, request); | 2942 | err = brcmf_do_escan(cfg, wiphy, ifp, request); |
2984 | if (err) { | 2943 | if (err) { |
2985 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 2944 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
2986 | goto out_err; | 2945 | goto out_err; |
@@ -3052,16 +3011,16 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, | |||
3052 | int i; | 3011 | int i; |
3053 | int ret = 0; | 3012 | int ret = 0; |
3054 | 3013 | ||
3055 | brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", | 3014 | brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", |
3056 | request->n_match_sets, request->n_ssids); | 3015 | request->n_match_sets, request->n_ssids); |
3057 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | 3016 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
3058 | brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); | 3017 | brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); |
3059 | return -EAGAIN; | 3018 | return -EAGAIN; |
3060 | } | 3019 | } |
3061 | 3020 | ||
3062 | if (!request || !request->n_ssids || !request->n_match_sets) { | 3021 | if (!request->n_ssids || !request->n_match_sets) { |
3063 | brcmf_err("Invalid sched scan req!! n_ssids:%d\n", | 3022 | brcmf_err("Invalid sched scan req!! n_ssids:%d\n", |
3064 | request ? request->n_ssids : 0); | 3023 | request->n_ssids); |
3065 | return -EINVAL; | 3024 | return -EINVAL; |
3066 | } | 3025 | } |
3067 | 3026 | ||
@@ -3137,7 +3096,7 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, | |||
3137 | brcmf_dbg(SCAN, "enter\n"); | 3096 | brcmf_dbg(SCAN, "enter\n"); |
3138 | brcmf_dev_pno_clean(ndev); | 3097 | brcmf_dev_pno_clean(ndev); |
3139 | if (cfg->sched_escan) | 3098 | if (cfg->sched_escan) |
3140 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 3099 | brcmf_notify_escan_complete(cfg, netdev_priv(ndev), true, true); |
3141 | return 0; | 3100 | return 0; |
3142 | } | 3101 | } |
3143 | 3102 | ||
@@ -3709,7 +3668,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
3709 | ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len); | 3668 | ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len); |
3710 | } | 3669 | } |
3711 | 3670 | ||
3712 | brcmf_set_mpc(ndev, 0); | 3671 | brcmf_set_mpc(ifp, 0); |
3713 | 3672 | ||
3714 | /* find the RSN_IE */ | 3673 | /* find the RSN_IE */ |
3715 | rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail, | 3674 | rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail, |
@@ -3817,15 +3776,16 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
3817 | 3776 | ||
3818 | exit: | 3777 | exit: |
3819 | if (err) | 3778 | if (err) |
3820 | brcmf_set_mpc(ndev, 1); | 3779 | brcmf_set_mpc(ifp, 1); |
3821 | return err; | 3780 | return err; |
3822 | } | 3781 | } |
3823 | 3782 | ||
3824 | static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) | 3783 | static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) |
3825 | { | 3784 | { |
3826 | struct brcmf_if *ifp = netdev_priv(ndev); | 3785 | struct brcmf_if *ifp = netdev_priv(ndev); |
3827 | s32 err = -EPERM; | 3786 | s32 err; |
3828 | struct brcmf_fil_bss_enable_le bss_enable; | 3787 | struct brcmf_fil_bss_enable_le bss_enable; |
3788 | struct brcmf_join_params join_params; | ||
3829 | 3789 | ||
3830 | brcmf_dbg(TRACE, "Enter\n"); | 3790 | brcmf_dbg(TRACE, "Enter\n"); |
3831 | 3791 | ||
@@ -3833,16 +3793,21 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) | |||
3833 | /* Due to most likely deauths outstanding we sleep */ | 3793 | /* Due to most likely deauths outstanding we sleep */ |
3834 | /* first to make sure they get processed by fw. */ | 3794 | /* first to make sure they get processed by fw. */ |
3835 | msleep(400); | 3795 | msleep(400); |
3836 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); | 3796 | |
3837 | if (err < 0) { | 3797 | memset(&join_params, 0, sizeof(join_params)); |
3838 | brcmf_err("setting AP mode failed %d\n", err); | 3798 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, |
3839 | goto exit; | 3799 | &join_params, sizeof(join_params)); |
3840 | } | 3800 | if (err < 0) |
3801 | brcmf_err("SET SSID error (%d)\n", err); | ||
3841 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0); | 3802 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0); |
3842 | if (err < 0) { | 3803 | if (err < 0) |
3843 | brcmf_err("BRCMF_C_UP error %d\n", err); | 3804 | brcmf_err("BRCMF_C_UP error %d\n", err); |
3844 | goto exit; | 3805 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); |
3845 | } | 3806 | if (err < 0) |
3807 | brcmf_err("setting AP mode failed %d\n", err); | ||
3808 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0); | ||
3809 | if (err < 0) | ||
3810 | brcmf_err("setting INFRA mode failed %d\n", err); | ||
3846 | } else { | 3811 | } else { |
3847 | bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx); | 3812 | bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx); |
3848 | bss_enable.enable = cpu_to_le32(0); | 3813 | bss_enable.enable = cpu_to_le32(0); |
@@ -3851,11 +3816,10 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) | |||
3851 | if (err < 0) | 3816 | if (err < 0) |
3852 | brcmf_err("bss_enable config failed %d\n", err); | 3817 | brcmf_err("bss_enable config failed %d\n", err); |
3853 | } | 3818 | } |
3854 | brcmf_set_mpc(ndev, 1); | 3819 | brcmf_set_mpc(ifp, 1); |
3855 | set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); | 3820 | set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); |
3856 | clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); | 3821 | clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); |
3857 | 3822 | ||
3858 | exit: | ||
3859 | return err; | 3823 | return err; |
3860 | } | 3824 | } |
3861 | 3825 | ||
@@ -3909,13 +3873,13 @@ brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy, | |||
3909 | struct wireless_dev *wdev, | 3873 | struct wireless_dev *wdev, |
3910 | u16 frame_type, bool reg) | 3874 | u16 frame_type, bool reg) |
3911 | { | 3875 | { |
3912 | struct brcmf_if *ifp = netdev_priv(wdev->netdev); | 3876 | struct brcmf_cfg80211_vif *vif; |
3913 | struct brcmf_cfg80211_vif *vif = ifp->vif; | ||
3914 | u16 mgmt_type; | 3877 | u16 mgmt_type; |
3915 | 3878 | ||
3916 | brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg); | 3879 | brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg); |
3917 | 3880 | ||
3918 | mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; | 3881 | mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; |
3882 | vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); | ||
3919 | if (reg) | 3883 | if (reg) |
3920 | vif->mgmt_rx_reg |= BIT(mgmt_type); | 3884 | vif->mgmt_rx_reg |= BIT(mgmt_type); |
3921 | else | 3885 | else |
@@ -3931,7 +3895,6 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3931 | { | 3895 | { |
3932 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3896 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3933 | const struct ieee80211_mgmt *mgmt; | 3897 | const struct ieee80211_mgmt *mgmt; |
3934 | struct brcmf_if *ifp; | ||
3935 | struct brcmf_cfg80211_vif *vif; | 3898 | struct brcmf_cfg80211_vif *vif; |
3936 | s32 err = 0; | 3899 | s32 err = 0; |
3937 | s32 ie_offset; | 3900 | s32 ie_offset; |
@@ -3967,8 +3930,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3967 | ie_offset = DOT11_MGMT_HDR_LEN + | 3930 | ie_offset = DOT11_MGMT_HDR_LEN + |
3968 | DOT11_BCN_PRB_FIXED_LEN; | 3931 | DOT11_BCN_PRB_FIXED_LEN; |
3969 | ie_len = len - ie_offset; | 3932 | ie_len = len - ie_offset; |
3970 | ifp = netdev_priv(wdev->netdev); | 3933 | vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); |
3971 | vif = ifp->vif; | ||
3972 | if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) | 3934 | if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) |
3973 | vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; | 3935 | vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; |
3974 | err = brcmf_vif_set_mgmt_ie(vif, | 3936 | err = brcmf_vif_set_mgmt_ie(vif, |
@@ -4003,7 +3965,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
4003 | *cookie, le16_to_cpu(action_frame->len), | 3965 | *cookie, le16_to_cpu(action_frame->len), |
4004 | chan->center_freq); | 3966 | chan->center_freq); |
4005 | 3967 | ||
4006 | ack = brcmf_p2p_send_action_frame(cfg, wdev->netdev, | 3968 | ack = brcmf_p2p_send_action_frame(cfg, cfg_to_ndev(cfg), |
4007 | af_params); | 3969 | af_params); |
4008 | 3970 | ||
4009 | cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, | 3971 | cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, |
@@ -4075,6 +4037,8 @@ static struct cfg80211_ops wl_cfg80211_ops = { | |||
4075 | .mgmt_tx = brcmf_cfg80211_mgmt_tx, | 4037 | .mgmt_tx = brcmf_cfg80211_mgmt_tx, |
4076 | .remain_on_channel = brcmf_p2p_remain_on_channel, | 4038 | .remain_on_channel = brcmf_p2p_remain_on_channel, |
4077 | .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel, | 4039 | .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel, |
4040 | .start_p2p_device = brcmf_p2p_start_device, | ||
4041 | .stop_p2p_device = brcmf_p2p_stop_device, | ||
4078 | #ifdef CONFIG_NL80211_TESTMODE | 4042 | #ifdef CONFIG_NL80211_TESTMODE |
4079 | .testmode_cmd = brcmf_cfg80211_testmode | 4043 | .testmode_cmd = brcmf_cfg80211_testmode |
4080 | #endif | 4044 | #endif |
@@ -4162,6 +4126,11 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { | |||
4162 | BIT(IEEE80211_STYPE_AUTH >> 4) | | 4126 | BIT(IEEE80211_STYPE_AUTH >> 4) | |
4163 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | 4127 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | |
4164 | BIT(IEEE80211_STYPE_ACTION >> 4) | 4128 | BIT(IEEE80211_STYPE_ACTION >> 4) |
4129 | }, | ||
4130 | [NL80211_IFTYPE_P2P_DEVICE] = { | ||
4131 | .tx = 0xffff, | ||
4132 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
4133 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
4165 | } | 4134 | } |
4166 | }; | 4135 | }; |
4167 | 4136 | ||
@@ -4188,13 +4157,6 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | |||
4188 | wiphy->iface_combinations = brcmf_iface_combos; | 4157 | wiphy->iface_combinations = brcmf_iface_combos; |
4189 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); | 4158 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); |
4190 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; | 4159 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; |
4191 | wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set | ||
4192 | * it as 11a by default. | ||
4193 | * This will be updated with | ||
4194 | * 11n phy tables in | ||
4195 | * "ifconfig up" | ||
4196 | * if phy has 11n capability | ||
4197 | */ | ||
4198 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 4160 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
4199 | wiphy->cipher_suites = __wl_cipher_suites; | 4161 | wiphy->cipher_suites = __wl_cipher_suites; |
4200 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | 4162 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); |
@@ -4204,6 +4166,9 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | |||
4204 | wiphy->mgmt_stypes = brcmf_txrx_stypes; | 4166 | wiphy->mgmt_stypes = brcmf_txrx_stypes; |
4205 | wiphy->max_remain_on_channel_duration = 5000; | 4167 | wiphy->max_remain_on_channel_duration = 5000; |
4206 | brcmf_wiphy_pno_params(wiphy); | 4168 | brcmf_wiphy_pno_params(wiphy); |
4169 | brcmf_dbg(INFO, "Registering custom regulatory\n"); | ||
4170 | wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | ||
4171 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | ||
4207 | err = wiphy_register(wiphy); | 4172 | err = wiphy_register(wiphy); |
4208 | if (err < 0) { | 4173 | if (err < 0) { |
4209 | brcmf_err("Could not register wiphy device (%d)\n", err); | 4174 | brcmf_err("Could not register wiphy device (%d)\n", err); |
@@ -4387,9 +4352,9 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, | |||
4387 | struct ieee80211_channel *notify_channel = NULL; | 4352 | struct ieee80211_channel *notify_channel = NULL; |
4388 | struct ieee80211_supported_band *band; | 4353 | struct ieee80211_supported_band *band; |
4389 | struct brcmf_bss_info_le *bi; | 4354 | struct brcmf_bss_info_le *bi; |
4355 | struct brcmu_chan ch; | ||
4390 | u32 freq; | 4356 | u32 freq; |
4391 | s32 err = 0; | 4357 | s32 err = 0; |
4392 | u32 target_channel; | ||
4393 | u8 *buf; | 4358 | u8 *buf; |
4394 | 4359 | ||
4395 | brcmf_dbg(TRACE, "Enter\n"); | 4360 | brcmf_dbg(TRACE, "Enter\n"); |
@@ -4413,15 +4378,15 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, | |||
4413 | goto done; | 4378 | goto done; |
4414 | 4379 | ||
4415 | bi = (struct brcmf_bss_info_le *)(buf + 4); | 4380 | bi = (struct brcmf_bss_info_le *)(buf + 4); |
4416 | target_channel = bi->ctl_ch ? bi->ctl_ch : | 4381 | ch.chspec = le16_to_cpu(bi->chanspec); |
4417 | CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); | 4382 | cfg->d11inf.decchspec(&ch); |
4418 | 4383 | ||
4419 | if (target_channel <= CH_MAX_2G_CHANNEL) | 4384 | if (ch.band == BRCMU_CHAN_BAND_2G) |
4420 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; | 4385 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; |
4421 | else | 4386 | else |
4422 | band = wiphy->bands[IEEE80211_BAND_5GHZ]; | 4387 | band = wiphy->bands[IEEE80211_BAND_5GHZ]; |
4423 | 4388 | ||
4424 | freq = ieee80211_channel_to_frequency(target_channel, band->band); | 4389 | freq = ieee80211_channel_to_frequency(ch.chnum, band->band); |
4425 | notify_channel = ieee80211_get_channel(wiphy, freq); | 4390 | notify_channel = ieee80211_get_channel(wiphy, freq); |
4426 | 4391 | ||
4427 | done: | 4392 | done: |
@@ -4622,9 +4587,11 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp, | |||
4622 | 4587 | ||
4623 | ifp->vif = vif; | 4588 | ifp->vif = vif; |
4624 | vif->ifp = ifp; | 4589 | vif->ifp = ifp; |
4625 | vif->wdev.netdev = ifp->ndev; | 4590 | if (ifp->ndev) { |
4626 | ifp->ndev->ieee80211_ptr = &vif->wdev; | 4591 | vif->wdev.netdev = ifp->ndev; |
4627 | SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy)); | 4592 | ifp->ndev->ieee80211_ptr = &vif->wdev; |
4593 | SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy)); | ||
4594 | } | ||
4628 | mutex_unlock(&event->vif_event_lock); | 4595 | mutex_unlock(&event->vif_event_lock); |
4629 | wake_up(&event->vif_wq); | 4596 | wake_up(&event->vif_wq); |
4630 | return 0; | 4597 | return 0; |
@@ -4773,6 +4740,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
4773 | struct brcmf_cfg80211_vif *vif; | 4740 | struct brcmf_cfg80211_vif *vif; |
4774 | struct brcmf_if *ifp; | 4741 | struct brcmf_if *ifp; |
4775 | s32 err = 0; | 4742 | s32 err = 0; |
4743 | s32 io_type; | ||
4776 | 4744 | ||
4777 | if (!ndev) { | 4745 | if (!ndev) { |
4778 | brcmf_err("ndev is invalid\n"); | 4746 | brcmf_err("ndev is invalid\n"); |
@@ -4814,6 +4782,15 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
4814 | goto cfg80211_p2p_attach_out; | 4782 | goto cfg80211_p2p_attach_out; |
4815 | } | 4783 | } |
4816 | 4784 | ||
4785 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, | ||
4786 | &io_type); | ||
4787 | if (err) { | ||
4788 | brcmf_err("Failed to get D11 version (%d)\n", err); | ||
4789 | goto cfg80211_p2p_attach_out; | ||
4790 | } | ||
4791 | cfg->d11inf.io_type = (u8)io_type; | ||
4792 | brcmu_d11_attach(&cfg->d11inf); | ||
4793 | |||
4817 | return cfg; | 4794 | return cfg; |
4818 | 4795 | ||
4819 | cfg80211_p2p_attach_out: | 4796 | cfg80211_p2p_attach_out: |
@@ -4927,34 +4904,234 @@ dongle_scantime_out: | |||
4927 | return err; | 4904 | return err; |
4928 | } | 4905 | } |
4929 | 4906 | ||
4930 | static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg) | 4907 | |
4908 | static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap) | ||
4909 | { | ||
4910 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | ||
4911 | struct ieee80211_channel *band_chan_arr; | ||
4912 | struct brcmf_chanspec_list *list; | ||
4913 | struct brcmu_chan ch; | ||
4914 | s32 err; | ||
4915 | u8 *pbuf; | ||
4916 | u32 i, j; | ||
4917 | u32 total; | ||
4918 | enum ieee80211_band band; | ||
4919 | u32 channel; | ||
4920 | u32 *n_cnt; | ||
4921 | bool ht40_allowed; | ||
4922 | u32 index; | ||
4923 | u32 ht40_flag; | ||
4924 | bool update; | ||
4925 | u32 array_size; | ||
4926 | |||
4927 | pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); | ||
4928 | |||
4929 | if (pbuf == NULL) | ||
4930 | return -ENOMEM; | ||
4931 | |||
4932 | list = (struct brcmf_chanspec_list *)pbuf; | ||
4933 | |||
4934 | err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf, | ||
4935 | BRCMF_DCMD_MEDLEN); | ||
4936 | if (err) { | ||
4937 | brcmf_err("get chanspecs error (%d)\n", err); | ||
4938 | goto exit; | ||
4939 | } | ||
4940 | |||
4941 | __wl_band_2ghz.n_channels = 0; | ||
4942 | __wl_band_5ghz_a.n_channels = 0; | ||
4943 | |||
4944 | total = le32_to_cpu(list->count); | ||
4945 | for (i = 0; i < total; i++) { | ||
4946 | ch.chspec = (u16)le32_to_cpu(list->element[i]); | ||
4947 | cfg->d11inf.decchspec(&ch); | ||
4948 | |||
4949 | if (ch.band == BRCMU_CHAN_BAND_2G) { | ||
4950 | band_chan_arr = __wl_2ghz_channels; | ||
4951 | array_size = ARRAY_SIZE(__wl_2ghz_channels); | ||
4952 | n_cnt = &__wl_band_2ghz.n_channels; | ||
4953 | band = IEEE80211_BAND_2GHZ; | ||
4954 | ht40_allowed = (bw_cap == WLC_N_BW_40ALL); | ||
4955 | } else if (ch.band == BRCMU_CHAN_BAND_5G) { | ||
4956 | band_chan_arr = __wl_5ghz_a_channels; | ||
4957 | array_size = ARRAY_SIZE(__wl_5ghz_a_channels); | ||
4958 | n_cnt = &__wl_band_5ghz_a.n_channels; | ||
4959 | band = IEEE80211_BAND_5GHZ; | ||
4960 | ht40_allowed = !(bw_cap == WLC_N_BW_20ALL); | ||
4961 | } else { | ||
4962 | brcmf_err("Invalid channel Sepc. 0x%x.\n", ch.chspec); | ||
4963 | continue; | ||
4964 | } | ||
4965 | if (!ht40_allowed && ch.bw == BRCMU_CHAN_BW_40) | ||
4966 | continue; | ||
4967 | update = false; | ||
4968 | for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { | ||
4969 | if (band_chan_arr[j].hw_value == ch.chnum) { | ||
4970 | update = true; | ||
4971 | break; | ||
4972 | } | ||
4973 | } | ||
4974 | if (update) | ||
4975 | index = j; | ||
4976 | else | ||
4977 | index = *n_cnt; | ||
4978 | if (index < array_size) { | ||
4979 | band_chan_arr[index].center_freq = | ||
4980 | ieee80211_channel_to_frequency(ch.chnum, band); | ||
4981 | band_chan_arr[index].hw_value = ch.chnum; | ||
4982 | |||
4983 | if (ch.bw == BRCMU_CHAN_BW_40 && ht40_allowed) { | ||
4984 | /* assuming the order is HT20, HT40 Upper, | ||
4985 | * HT40 lower from chanspecs | ||
4986 | */ | ||
4987 | ht40_flag = band_chan_arr[index].flags & | ||
4988 | IEEE80211_CHAN_NO_HT40; | ||
4989 | if (ch.sb == BRCMU_CHAN_SB_U) { | ||
4990 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | ||
4991 | band_chan_arr[index].flags &= | ||
4992 | ~IEEE80211_CHAN_NO_HT40; | ||
4993 | band_chan_arr[index].flags |= | ||
4994 | IEEE80211_CHAN_NO_HT40PLUS; | ||
4995 | } else { | ||
4996 | /* It should be one of | ||
4997 | * IEEE80211_CHAN_NO_HT40 or | ||
4998 | * IEEE80211_CHAN_NO_HT40PLUS | ||
4999 | */ | ||
5000 | band_chan_arr[index].flags &= | ||
5001 | ~IEEE80211_CHAN_NO_HT40; | ||
5002 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | ||
5003 | band_chan_arr[index].flags |= | ||
5004 | IEEE80211_CHAN_NO_HT40MINUS; | ||
5005 | } | ||
5006 | } else { | ||
5007 | band_chan_arr[index].flags = | ||
5008 | IEEE80211_CHAN_NO_HT40; | ||
5009 | ch.bw = BRCMU_CHAN_BW_20; | ||
5010 | cfg->d11inf.encchspec(&ch); | ||
5011 | channel = ch.chspec; | ||
5012 | err = brcmf_fil_bsscfg_int_get(ifp, | ||
5013 | "per_chan_info", | ||
5014 | &channel); | ||
5015 | if (!err) { | ||
5016 | if (channel & WL_CHAN_RADAR) | ||
5017 | band_chan_arr[index].flags |= | ||
5018 | (IEEE80211_CHAN_RADAR | | ||
5019 | IEEE80211_CHAN_NO_IBSS); | ||
5020 | if (channel & WL_CHAN_PASSIVE) | ||
5021 | band_chan_arr[index].flags |= | ||
5022 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
5023 | } | ||
5024 | } | ||
5025 | if (!update) | ||
5026 | (*n_cnt)++; | ||
5027 | } | ||
5028 | } | ||
5029 | exit: | ||
5030 | kfree(pbuf); | ||
5031 | return err; | ||
5032 | } | ||
5033 | |||
5034 | |||
5035 | static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | ||
4931 | { | 5036 | { |
4932 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 5037 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
4933 | struct wiphy *wiphy; | 5038 | struct wiphy *wiphy; |
4934 | s32 phy_list; | 5039 | s32 phy_list; |
5040 | u32 band_list[3]; | ||
5041 | u32 nmode; | ||
5042 | u32 bw_cap = 0; | ||
4935 | s8 phy; | 5043 | s8 phy; |
4936 | s32 err = 0; | 5044 | s32 err; |
5045 | u32 nband; | ||
5046 | s32 i; | ||
5047 | struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; | ||
5048 | s32 index; | ||
4937 | 5049 | ||
4938 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST, | 5050 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST, |
4939 | &phy_list, sizeof(phy_list)); | 5051 | &phy_list, sizeof(phy_list)); |
4940 | if (err) { | 5052 | if (err) { |
4941 | brcmf_err("error (%d)\n", err); | 5053 | brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err); |
4942 | return err; | 5054 | return err; |
4943 | } | 5055 | } |
4944 | 5056 | ||
4945 | phy = ((char *)&phy_list)[0]; | 5057 | phy = ((char *)&phy_list)[0]; |
4946 | brcmf_dbg(INFO, "%c phy\n", phy); | 5058 | brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy); |
4947 | if (phy == 'n' || phy == 'a') { | 5059 | |
4948 | wiphy = cfg_to_wiphy(cfg); | 5060 | |
4949 | wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n; | 5061 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, |
5062 | &band_list, sizeof(band_list)); | ||
5063 | if (err) { | ||
5064 | brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err); | ||
5065 | return err; | ||
5066 | } | ||
5067 | brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n", | ||
5068 | band_list[0], band_list[1], band_list[2]); | ||
5069 | |||
5070 | err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); | ||
5071 | if (err) { | ||
5072 | brcmf_err("nmode error (%d)\n", err); | ||
5073 | } else { | ||
5074 | err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &bw_cap); | ||
5075 | if (err) | ||
5076 | brcmf_err("mimo_bw_cap error (%d)\n", err); | ||
4950 | } | 5077 | } |
5078 | brcmf_dbg(INFO, "nmode=%d, mimo_bw_cap=%d\n", nmode, bw_cap); | ||
5079 | |||
5080 | err = brcmf_construct_reginfo(cfg, bw_cap); | ||
5081 | if (err) { | ||
5082 | brcmf_err("brcmf_construct_reginfo failed (%d)\n", err); | ||
5083 | return err; | ||
5084 | } | ||
5085 | |||
5086 | nband = band_list[0]; | ||
5087 | memset(bands, 0, sizeof(bands)); | ||
5088 | |||
5089 | for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) { | ||
5090 | index = -1; | ||
5091 | if ((band_list[i] == WLC_BAND_5G) && | ||
5092 | (__wl_band_5ghz_a.n_channels > 0)) { | ||
5093 | index = IEEE80211_BAND_5GHZ; | ||
5094 | bands[index] = &__wl_band_5ghz_a; | ||
5095 | if ((bw_cap == WLC_N_BW_40ALL) || | ||
5096 | (bw_cap == WLC_N_BW_20IN2G_40IN5G)) | ||
5097 | bands[index]->ht_cap.cap |= | ||
5098 | IEEE80211_HT_CAP_SGI_40; | ||
5099 | } else if ((band_list[i] == WLC_BAND_2G) && | ||
5100 | (__wl_band_2ghz.n_channels > 0)) { | ||
5101 | index = IEEE80211_BAND_2GHZ; | ||
5102 | bands[index] = &__wl_band_2ghz; | ||
5103 | if (bw_cap == WLC_N_BW_40ALL) | ||
5104 | bands[index]->ht_cap.cap |= | ||
5105 | IEEE80211_HT_CAP_SGI_40; | ||
5106 | } | ||
5107 | |||
5108 | if ((index >= 0) && nmode) { | ||
5109 | bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | ||
5110 | bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; | ||
5111 | bands[index]->ht_cap.ht_supported = true; | ||
5112 | bands[index]->ht_cap.ampdu_factor = | ||
5113 | IEEE80211_HT_MAX_AMPDU_64K; | ||
5114 | bands[index]->ht_cap.ampdu_density = | ||
5115 | IEEE80211_HT_MPDU_DENSITY_16; | ||
5116 | /* An HT shall support all EQM rates for one spatial | ||
5117 | * stream | ||
5118 | */ | ||
5119 | bands[index]->ht_cap.mcs.rx_mask[0] = 0xff; | ||
5120 | } | ||
5121 | } | ||
5122 | |||
5123 | wiphy = cfg_to_wiphy(cfg); | ||
5124 | wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ]; | ||
5125 | wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ]; | ||
5126 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | ||
4951 | 5127 | ||
4952 | return err; | 5128 | return err; |
4953 | } | 5129 | } |
4954 | 5130 | ||
5131 | |||
4955 | static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg) | 5132 | static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg) |
4956 | { | 5133 | { |
4957 | return wl_update_wiphybands(cfg); | 5134 | return brcmf_update_wiphybands(cfg); |
4958 | } | 5135 | } |
4959 | 5136 | ||
4960 | static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | 5137 | static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) |
@@ -5060,6 +5237,13 @@ s32 brcmf_cfg80211_down(struct net_device *ndev) | |||
5060 | return err; | 5237 | return err; |
5061 | } | 5238 | } |
5062 | 5239 | ||
5240 | enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp) | ||
5241 | { | ||
5242 | struct wireless_dev *wdev = &ifp->vif->wdev; | ||
5243 | |||
5244 | return wdev->iftype; | ||
5245 | } | ||
5246 | |||
5063 | u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state) | 5247 | u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state) |
5064 | { | 5248 | { |
5065 | struct brcmf_cfg80211_vif *vif; | 5249 | struct brcmf_cfg80211_vif *vif; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 8b5d4989906c..0b9263e7dca4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | |||
@@ -17,6 +17,9 @@ | |||
17 | #ifndef _wl_cfg80211_h_ | 17 | #ifndef _wl_cfg80211_h_ |
18 | #define _wl_cfg80211_h_ | 18 | #define _wl_cfg80211_h_ |
19 | 19 | ||
20 | /* for brcmu_d11inf */ | ||
21 | #include <brcmu_d11.h> | ||
22 | |||
20 | #define WL_NUM_SCAN_MAX 10 | 23 | #define WL_NUM_SCAN_MAX 10 |
21 | #define WL_NUM_PMKIDS_MAX MAXPMKID | 24 | #define WL_NUM_PMKIDS_MAX MAXPMKID |
22 | #define WL_TLV_INFO_MAX 1024 | 25 | #define WL_TLV_INFO_MAX 1024 |
@@ -238,9 +241,8 @@ struct escan_info { | |||
238 | u32 escan_state; | 241 | u32 escan_state; |
239 | u8 escan_buf[WL_ESCAN_BUF_SIZE]; | 242 | u8 escan_buf[WL_ESCAN_BUF_SIZE]; |
240 | struct wiphy *wiphy; | 243 | struct wiphy *wiphy; |
241 | struct net_device *ndev; | 244 | struct brcmf_if *ifp; |
242 | s32 (*run)(struct brcmf_cfg80211_info *cfg, | 245 | s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, |
243 | struct net_device *ndev, | ||
244 | struct cfg80211_scan_request *request, u16 action); | 246 | struct cfg80211_scan_request *request, u16 action); |
245 | }; | 247 | }; |
246 | 248 | ||
@@ -409,6 +411,7 @@ struct brcmf_cfg80211_info { | |||
409 | u8 vif_cnt; | 411 | u8 vif_cnt; |
410 | struct brcmf_cfg80211_vif_event vif_event; | 412 | struct brcmf_cfg80211_vif_event vif_event; |
411 | struct completion vif_disabled; | 413 | struct completion vif_disabled; |
414 | struct brcmu_d11inf d11inf; | ||
412 | }; | 415 | }; |
413 | 416 | ||
414 | /** | 417 | /** |
@@ -475,6 +478,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
475 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); | 478 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); |
476 | s32 brcmf_cfg80211_up(struct net_device *ndev); | 479 | s32 brcmf_cfg80211_up(struct net_device *ndev); |
477 | s32 brcmf_cfg80211_down(struct net_device *ndev); | 480 | s32 brcmf_cfg80211_down(struct net_device *ndev); |
481 | enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp); | ||
478 | 482 | ||
479 | struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, | 483 | struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, |
480 | enum nl80211_iftype type, | 484 | enum nl80211_iftype type, |
@@ -485,7 +489,8 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, | |||
485 | const u8 *vndr_ie_buf, u32 vndr_ie_len); | 489 | const u8 *vndr_ie_buf, u32 vndr_ie_len); |
486 | s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif); | 490 | s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif); |
487 | struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key); | 491 | struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key); |
488 | u16 channel_to_chanspec(struct ieee80211_channel *ch); | 492 | u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, |
493 | struct ieee80211_channel *ch); | ||
489 | u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state); | 494 | u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state); |
490 | void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, | 495 | void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, |
491 | struct brcmf_cfg80211_vif *vif); | 496 | struct brcmf_cfg80211_vif *vif); |
@@ -493,9 +498,9 @@ bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); | |||
493 | int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, | 498 | int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, |
494 | u8 action, ulong timeout); | 499 | u8 action, ulong timeout); |
495 | s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | 500 | s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, |
496 | struct net_device *ndev, | 501 | struct brcmf_if *ifp, bool aborted, |
497 | bool aborted, bool fw_abort); | 502 | bool fw_abort); |
498 | void brcmf_set_mpc(struct net_device *ndev, int mpc); | 503 | void brcmf_set_mpc(struct brcmf_if *ndev, int mpc); |
499 | void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); | 504 | void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); |
500 | 505 | ||
501 | #endif /* _wl_cfg80211_h_ */ | 506 | #endif /* _wl_cfg80211_h_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile index d3d4151c3eda..32464acccd90 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile | |||
@@ -21,7 +21,7 @@ ccflags-y := \ | |||
21 | -Idrivers/net/wireless/brcm80211/brcmsmac/phy \ | 21 | -Idrivers/net/wireless/brcm80211/brcmsmac/phy \ |
22 | -Idrivers/net/wireless/brcm80211/include | 22 | -Idrivers/net/wireless/brcm80211/include |
23 | 23 | ||
24 | BRCMSMAC_OFILES := \ | 24 | brcmsmac-y := \ |
25 | mac80211_if.o \ | 25 | mac80211_if.o \ |
26 | ucode_loader.o \ | 26 | ucode_loader.o \ |
27 | ampdu.o \ | 27 | ampdu.o \ |
@@ -43,7 +43,6 @@ BRCMSMAC_OFILES := \ | |||
43 | brcms_trace_events.o \ | 43 | brcms_trace_events.o \ |
44 | debug.o | 44 | debug.o |
45 | 45 | ||
46 | MODULEPFX := brcmsmac | 46 | brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o |
47 | 47 | ||
48 | obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o | 48 | obj-$(CONFIG_BRCMSMAC) += brcmsmac.o |
49 | $(MODULEPFX)-objs = $(BRCMSMAC_OFILES) | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index f0888a9ee32e..e4fd1ee3d690 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c | |||
@@ -318,12 +318,6 @@ | |||
318 | #define IS_SIM(chippkg) \ | 318 | #define IS_SIM(chippkg) \ |
319 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) | 319 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) |
320 | 320 | ||
321 | #ifdef DEBUG | ||
322 | #define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) | ||
323 | #else | ||
324 | #define SI_MSG(fmt, ...) no_printk(fmt, ##__VA_ARGS__) | ||
325 | #endif /* DEBUG */ | ||
326 | |||
327 | #define GOODCOREADDR(x, b) \ | 321 | #define GOODCOREADDR(x, b) \ |
328 | (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ | 322 | (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ |
329 | IS_ALIGNED((x), SI_CORE_SIZE)) | 323 | IS_ALIGNED((x), SI_CORE_SIZE)) |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/d11.h b/drivers/net/wireless/brcm80211/brcmsmac/d11.h index 3f659e09f1cc..9035cc4d6ff3 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/d11.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/d11.h | |||
@@ -457,6 +457,7 @@ struct d11regs { | |||
457 | /*== maccontrol register ==*/ | 457 | /*== maccontrol register ==*/ |
458 | #define MCTL_GMODE (1U << 31) | 458 | #define MCTL_GMODE (1U << 31) |
459 | #define MCTL_DISCARD_PMQ (1 << 30) | 459 | #define MCTL_DISCARD_PMQ (1 << 30) |
460 | #define MCTL_TBTTHOLD (1 << 28) | ||
460 | #define MCTL_WAKE (1 << 26) | 461 | #define MCTL_WAKE (1 << 26) |
461 | #define MCTL_HPS (1 << 25) | 462 | #define MCTL_HPS (1 << 25) |
462 | #define MCTL_PROMISC (1 << 24) | 463 | #define MCTL_PROMISC (1 << 24) |
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 70731d23ddb1..db663230088d 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Broadcom Corporation | 2 | * Copyright (c) 2010 Broadcom Corporation |
3 | * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de> | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * 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 | * purpose with or without fee is hereby granted, provided that the above |
@@ -34,6 +35,7 @@ | |||
34 | #include "mac80211_if.h" | 35 | #include "mac80211_if.h" |
35 | #include "main.h" | 36 | #include "main.h" |
36 | #include "debug.h" | 37 | #include "debug.h" |
38 | #include "led.h" | ||
37 | 39 | ||
38 | #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ | 40 | #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ |
39 | #define BRCMS_FLUSH_TIMEOUT 500 /* msec */ | 41 | #define BRCMS_FLUSH_TIMEOUT 500 /* msec */ |
@@ -355,18 +357,26 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
355 | { | 357 | { |
356 | struct brcms_info *wl = hw->priv; | 358 | struct brcms_info *wl = hw->priv; |
357 | 359 | ||
358 | /* Just STA for now */ | 360 | /* Just STA, AP and ADHOC for now */ |
359 | if (vif->type != NL80211_IFTYPE_STATION) { | 361 | if (vif->type != NL80211_IFTYPE_STATION && |
362 | vif->type != NL80211_IFTYPE_AP && | ||
363 | vif->type != NL80211_IFTYPE_ADHOC) { | ||
360 | brcms_err(wl->wlc->hw->d11core, | 364 | brcms_err(wl->wlc->hw->d11core, |
361 | "%s: Attempt to add type %d, only STA for now\n", | 365 | "%s: Attempt to add type %d, only STA, AP and AdHoc for now\n", |
362 | __func__, vif->type); | 366 | __func__, vif->type); |
363 | return -EOPNOTSUPP; | 367 | return -EOPNOTSUPP; |
364 | } | 368 | } |
365 | 369 | ||
366 | spin_lock_bh(&wl->lock); | 370 | spin_lock_bh(&wl->lock); |
367 | memcpy(wl->pub->cur_etheraddr, vif->addr, sizeof(vif->addr)); | ||
368 | wl->mute_tx = false; | 371 | wl->mute_tx = false; |
369 | brcms_c_mute(wl->wlc, false); | 372 | brcms_c_mute(wl->wlc, false); |
373 | if (vif->type == NL80211_IFTYPE_STATION) | ||
374 | brcms_c_start_station(wl->wlc, vif->addr); | ||
375 | else if (vif->type == NL80211_IFTYPE_AP) | ||
376 | brcms_c_start_ap(wl->wlc, vif->addr, vif->bss_conf.bssid, | ||
377 | vif->bss_conf.ssid, vif->bss_conf.ssid_len); | ||
378 | else if (vif->type == NL80211_IFTYPE_ADHOC) | ||
379 | brcms_c_start_adhoc(wl->wlc, vif->addr); | ||
370 | spin_unlock_bh(&wl->lock); | 380 | spin_unlock_bh(&wl->lock); |
371 | 381 | ||
372 | return 0; | 382 | return 0; |
@@ -518,14 +528,43 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw, | |||
518 | brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid); | 528 | brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid); |
519 | spin_unlock_bh(&wl->lock); | 529 | spin_unlock_bh(&wl->lock); |
520 | } | 530 | } |
521 | if (changed & BSS_CHANGED_BEACON) | 531 | if (changed & BSS_CHANGED_SSID) { |
532 | /* BSSID changed, for whatever reason (IBSS and managed mode) */ | ||
533 | spin_lock_bh(&wl->lock); | ||
534 | brcms_c_set_ssid(wl->wlc, info->ssid, info->ssid_len); | ||
535 | spin_unlock_bh(&wl->lock); | ||
536 | } | ||
537 | if (changed & BSS_CHANGED_BEACON) { | ||
522 | /* Beacon data changed, retrieve new beacon (beaconing modes) */ | 538 | /* Beacon data changed, retrieve new beacon (beaconing modes) */ |
523 | brcms_err(core, "%s: beacon changed\n", __func__); | 539 | struct sk_buff *beacon; |
540 | u16 tim_offset = 0; | ||
541 | |||
542 | spin_lock_bh(&wl->lock); | ||
543 | beacon = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL); | ||
544 | brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset, | ||
545 | info->dtim_period); | ||
546 | spin_unlock_bh(&wl->lock); | ||
547 | } | ||
548 | |||
549 | if (changed & BSS_CHANGED_AP_PROBE_RESP) { | ||
550 | struct sk_buff *probe_resp; | ||
551 | |||
552 | spin_lock_bh(&wl->lock); | ||
553 | probe_resp = ieee80211_proberesp_get(hw, vif); | ||
554 | brcms_c_set_new_probe_resp(wl->wlc, probe_resp); | ||
555 | spin_unlock_bh(&wl->lock); | ||
556 | } | ||
524 | 557 | ||
525 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 558 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
526 | /* Beaconing should be enabled/disabled (beaconing modes) */ | 559 | /* Beaconing should be enabled/disabled (beaconing modes) */ |
527 | brcms_err(core, "%s: Beacon enabled: %s\n", __func__, | 560 | brcms_err(core, "%s: Beacon enabled: %s\n", __func__, |
528 | info->enable_beacon ? "true" : "false"); | 561 | info->enable_beacon ? "true" : "false"); |
562 | if (info->enable_beacon && | ||
563 | hw->wiphy->flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) { | ||
564 | brcms_c_enable_probe_resp(wl->wlc, true); | ||
565 | } else { | ||
566 | brcms_c_enable_probe_resp(wl->wlc, false); | ||
567 | } | ||
529 | } | 568 | } |
530 | 569 | ||
531 | if (changed & BSS_CHANGED_CQM) { | 570 | if (changed & BSS_CHANGED_CQM) { |
@@ -738,6 +777,28 @@ static void brcms_ops_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
738 | "ret=%d\n", jiffies_to_msecs(ret)); | 777 | "ret=%d\n", jiffies_to_msecs(ret)); |
739 | } | 778 | } |
740 | 779 | ||
780 | static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
781 | { | ||
782 | struct brcms_info *wl = hw->priv; | ||
783 | u64 tsf; | ||
784 | |||
785 | spin_lock_bh(&wl->lock); | ||
786 | tsf = brcms_c_tsf_get(wl->wlc); | ||
787 | spin_unlock_bh(&wl->lock); | ||
788 | |||
789 | return tsf; | ||
790 | } | ||
791 | |||
792 | static void brcms_ops_set_tsf(struct ieee80211_hw *hw, | ||
793 | struct ieee80211_vif *vif, u64 tsf) | ||
794 | { | ||
795 | struct brcms_info *wl = hw->priv; | ||
796 | |||
797 | spin_lock_bh(&wl->lock); | ||
798 | brcms_c_tsf_set(wl->wlc, tsf); | ||
799 | spin_unlock_bh(&wl->lock); | ||
800 | } | ||
801 | |||
741 | static const struct ieee80211_ops brcms_ops = { | 802 | static const struct ieee80211_ops brcms_ops = { |
742 | .tx = brcms_ops_tx, | 803 | .tx = brcms_ops_tx, |
743 | .start = brcms_ops_start, | 804 | .start = brcms_ops_start, |
@@ -754,6 +815,8 @@ static const struct ieee80211_ops brcms_ops = { | |||
754 | .ampdu_action = brcms_ops_ampdu_action, | 815 | .ampdu_action = brcms_ops_ampdu_action, |
755 | .rfkill_poll = brcms_ops_rfkill_poll, | 816 | .rfkill_poll = brcms_ops_rfkill_poll, |
756 | .flush = brcms_ops_flush, | 817 | .flush = brcms_ops_flush, |
818 | .get_tsf = brcms_ops_get_tsf, | ||
819 | .set_tsf = brcms_ops_set_tsf, | ||
757 | }; | 820 | }; |
758 | 821 | ||
759 | void brcms_dpc(unsigned long data) | 822 | void brcms_dpc(unsigned long data) |
@@ -904,6 +967,7 @@ static void brcms_remove(struct bcma_device *pdev) | |||
904 | struct brcms_info *wl = hw->priv; | 967 | struct brcms_info *wl = hw->priv; |
905 | 968 | ||
906 | if (wl->wlc) { | 969 | if (wl->wlc) { |
970 | brcms_led_unregister(wl); | ||
907 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); | 971 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); |
908 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); | 972 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); |
909 | ieee80211_unregister_hw(hw); | 973 | ieee80211_unregister_hw(hw); |
@@ -994,7 +1058,16 @@ static int ieee_hw_init(struct ieee80211_hw *hw) | |||
994 | 1058 | ||
995 | /* channel change time is dependent on chip and band */ | 1059 | /* channel change time is dependent on chip and band */ |
996 | hw->channel_change_time = 7 * 1000; | 1060 | hw->channel_change_time = 7 * 1000; |
997 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1061 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1062 | BIT(NL80211_IFTYPE_AP) | | ||
1063 | BIT(NL80211_IFTYPE_ADHOC); | ||
1064 | |||
1065 | /* | ||
1066 | * deactivate sending probe responses by ucude, because this will | ||
1067 | * cause problems when WPS is used. | ||
1068 | * | ||
1069 | * hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
1070 | */ | ||
998 | 1071 | ||
999 | hw->rate_control_algorithm = "minstrel_ht"; | 1072 | hw->rate_control_algorithm = "minstrel_ht"; |
1000 | 1073 | ||
@@ -1151,6 +1224,8 @@ static int brcms_bcma_probe(struct bcma_device *pdev) | |||
1151 | pr_err("%s: brcms_attach failed!\n", __func__); | 1224 | pr_err("%s: brcms_attach failed!\n", __func__); |
1152 | return -ENODEV; | 1225 | return -ENODEV; |
1153 | } | 1226 | } |
1227 | brcms_led_register(wl); | ||
1228 | |||
1154 | return 0; | 1229 | return 0; |
1155 | } | 1230 | } |
1156 | 1231 | ||
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 e0dc1838cd19..28e7aeedd184 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Broadcom Corporation | 2 | * Copyright (c) 2010 Broadcom Corporation |
3 | * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de> | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * 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 | * purpose with or without fee is hereby granted, provided that the above |
@@ -448,6 +449,10 @@ static void brcms_c_detach_mfree(struct brcms_c_info *wlc) | |||
448 | kfree(wlc->corestate); | 449 | kfree(wlc->corestate); |
449 | kfree(wlc->hw->bandstate[0]); | 450 | kfree(wlc->hw->bandstate[0]); |
450 | kfree(wlc->hw); | 451 | kfree(wlc->hw); |
452 | if (wlc->beacon) | ||
453 | dev_kfree_skb_any(wlc->beacon); | ||
454 | if (wlc->probe_resp) | ||
455 | dev_kfree_skb_any(wlc->probe_resp); | ||
451 | 456 | ||
452 | /* free the wlc */ | 457 | /* free the wlc */ |
453 | kfree(wlc); | 458 | kfree(wlc); |
@@ -1069,7 +1074,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) | |||
1069 | 1074 | ||
1070 | static void brcms_c_tbtt(struct brcms_c_info *wlc) | 1075 | static void brcms_c_tbtt(struct brcms_c_info *wlc) |
1071 | { | 1076 | { |
1072 | if (!wlc->bsscfg->BSS) | 1077 | if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC) |
1073 | /* | 1078 | /* |
1074 | * DirFrmQ is now valid...defer setting until end | 1079 | * DirFrmQ is now valid...defer setting until end |
1075 | * of ATIM window | 1080 | * of ATIM window |
@@ -2163,6 +2168,32 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) | |||
2163 | } | 2168 | } |
2164 | } | 2169 | } |
2165 | 2170 | ||
2171 | void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr) | ||
2172 | { | ||
2173 | memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr)); | ||
2174 | wlc->bsscfg->type = BRCMS_TYPE_STATION; | ||
2175 | } | ||
2176 | |||
2177 | void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid, | ||
2178 | u8 *ssid, size_t ssid_len) | ||
2179 | { | ||
2180 | brcms_c_set_ssid(wlc, ssid, ssid_len); | ||
2181 | |||
2182 | memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr)); | ||
2183 | memcpy(wlc->bsscfg->BSSID, bssid, sizeof(wlc->bsscfg->BSSID)); | ||
2184 | wlc->bsscfg->type = BRCMS_TYPE_AP; | ||
2185 | |||
2186 | brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, MCTL_AP | MCTL_INFRA); | ||
2187 | } | ||
2188 | |||
2189 | void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr) | ||
2190 | { | ||
2191 | memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr)); | ||
2192 | wlc->bsscfg->type = BRCMS_TYPE_ADHOC; | ||
2193 | |||
2194 | brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, 0); | ||
2195 | } | ||
2196 | |||
2166 | /* Initialize GPIOs that are controlled by D11 core */ | 2197 | /* Initialize GPIOs that are controlled by D11 core */ |
2167 | static void brcms_c_gpio_init(struct brcms_c_info *wlc) | 2198 | static void brcms_c_gpio_init(struct brcms_c_info *wlc) |
2168 | { | 2199 | { |
@@ -3043,8 +3074,6 @@ static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail) | |||
3043 | */ | 3074 | */ |
3044 | static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) | 3075 | static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) |
3045 | { | 3076 | { |
3046 | struct brcms_bss_cfg *cfg = wlc->bsscfg; | ||
3047 | |||
3048 | /* disallow PS when one of the following global conditions meets */ | 3077 | /* disallow PS when one of the following global conditions meets */ |
3049 | if (!wlc->pub->associated) | 3078 | if (!wlc->pub->associated) |
3050 | return false; | 3079 | return false; |
@@ -3053,16 +3082,11 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) | |||
3053 | if (wlc->filter_flags & FIF_PROMISC_IN_BSS) | 3082 | if (wlc->filter_flags & FIF_PROMISC_IN_BSS) |
3054 | return false; | 3083 | return false; |
3055 | 3084 | ||
3056 | if (cfg->associated) { | 3085 | if (wlc->bsscfg->type == BRCMS_TYPE_AP) |
3057 | /* | 3086 | return false; |
3058 | * disallow PS when one of the following | ||
3059 | * bsscfg specific conditions meets | ||
3060 | */ | ||
3061 | if (!cfg->BSS) | ||
3062 | return false; | ||
3063 | 3087 | ||
3088 | if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC) | ||
3064 | return false; | 3089 | return false; |
3065 | } | ||
3066 | 3090 | ||
3067 | return true; | 3091 | return true; |
3068 | } | 3092 | } |
@@ -3771,7 +3795,7 @@ static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg) | |||
3771 | struct brcms_c_info *wlc = bsscfg->wlc; | 3795 | struct brcms_c_info *wlc = bsscfg->wlc; |
3772 | 3796 | ||
3773 | /* enter the MAC addr into the RXE match registers */ | 3797 | /* enter the MAC addr into the RXE match registers */ |
3774 | brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr); | 3798 | brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, wlc->pub->cur_etheraddr); |
3775 | 3799 | ||
3776 | brcms_c_ampdu_macaddr_upd(wlc); | 3800 | brcms_c_ampdu_macaddr_upd(wlc); |
3777 | 3801 | ||
@@ -3787,6 +3811,15 @@ static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg) | |||
3787 | brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID); | 3811 | brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID); |
3788 | } | 3812 | } |
3789 | 3813 | ||
3814 | void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len) | ||
3815 | { | ||
3816 | u8 len = min_t(u8, sizeof(wlc->bsscfg->SSID), ssid_len); | ||
3817 | memset(wlc->bsscfg->SSID, 0, sizeof(wlc->bsscfg->SSID)); | ||
3818 | |||
3819 | memcpy(wlc->bsscfg->SSID, ssid, len); | ||
3820 | wlc->bsscfg->SSID_len = len; | ||
3821 | } | ||
3822 | |||
3790 | static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot) | 3823 | static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot) |
3791 | { | 3824 | { |
3792 | wlc_hw->shortslot = shortslot; | 3825 | wlc_hw->shortslot = shortslot; |
@@ -3821,7 +3854,7 @@ static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec) | |||
3821 | if (wlc->home_chanspec != chanspec) { | 3854 | if (wlc->home_chanspec != chanspec) { |
3822 | wlc->home_chanspec = chanspec; | 3855 | wlc->home_chanspec = chanspec; |
3823 | 3856 | ||
3824 | if (wlc->bsscfg->associated) | 3857 | if (wlc->pub->associated) |
3825 | wlc->bsscfg->current_bss->chanspec = chanspec; | 3858 | wlc->bsscfg->current_bss->chanspec = chanspec; |
3826 | } | 3859 | } |
3827 | } | 3860 | } |
@@ -4091,10 +4124,14 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, | |||
4091 | *shm_entry++); | 4124 | *shm_entry++); |
4092 | } | 4125 | } |
4093 | 4126 | ||
4094 | if (suspend) { | 4127 | if (suspend) |
4095 | brcms_c_suspend_mac_and_wait(wlc); | 4128 | brcms_c_suspend_mac_and_wait(wlc); |
4129 | |||
4130 | brcms_c_update_beacon(wlc); | ||
4131 | brcms_c_update_probe_resp(wlc, false); | ||
4132 | |||
4133 | if (suspend) | ||
4096 | brcms_c_enable_mac(wlc); | 4134 | brcms_c_enable_mac(wlc); |
4097 | } | ||
4098 | } | 4135 | } |
4099 | 4136 | ||
4100 | static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend) | 4137 | static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend) |
@@ -4332,7 +4369,6 @@ static void brcms_c_info_init(struct brcms_c_info *wlc, int unit) | |||
4332 | 4369 | ||
4333 | /* WME QoS mode is Auto by default */ | 4370 | /* WME QoS mode is Auto by default */ |
4334 | wlc->pub->_ampdu = AMPDU_AGG_HOST; | 4371 | wlc->pub->_ampdu = AMPDU_AGG_HOST; |
4335 | wlc->pub->bcmerror = 0; | ||
4336 | } | 4372 | } |
4337 | 4373 | ||
4338 | static uint brcms_c_attach_module(struct brcms_c_info *wlc) | 4374 | static uint brcms_c_attach_module(struct brcms_c_info *wlc) |
@@ -5072,8 +5108,8 @@ int brcms_c_up(struct brcms_c_info *wlc) | |||
5072 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; | 5108 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; |
5073 | mboolset(wlc->pub->radio_disabled, | 5109 | mboolset(wlc->pub->radio_disabled, |
5074 | WL_RADIO_HW_DISABLE); | 5110 | WL_RADIO_HW_DISABLE); |
5075 | 5111 | if (bsscfg->type == BRCMS_TYPE_STATION || | |
5076 | if (bsscfg->enable && bsscfg->BSS) | 5112 | bsscfg->type == BRCMS_TYPE_ADHOC) |
5077 | brcms_err(wlc->hw->d11core, | 5113 | brcms_err(wlc->hw->d11core, |
5078 | "wl%d: up: rfdisable -> " | 5114 | "wl%d: up: rfdisable -> " |
5079 | "bsscfg_disable()\n", | 5115 | "bsscfg_disable()\n", |
@@ -5434,7 +5470,7 @@ static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc) | |||
5434 | u8 r; | 5470 | u8 r; |
5435 | bool war = false; | 5471 | bool war = false; |
5436 | 5472 | ||
5437 | if (wlc->bsscfg->associated) | 5473 | if (wlc->pub->associated) |
5438 | r = wlc->bsscfg->current_bss->rateset.rates[0]; | 5474 | r = wlc->bsscfg->current_bss->rateset.rates[0]; |
5439 | else | 5475 | else |
5440 | r = wlc->default_bss->rateset.rates[0]; | 5476 | r = wlc->default_bss->rateset.rates[0]; |
@@ -5528,7 +5564,7 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs) | |||
5528 | /* merge rateset coming in with the current mcsset */ | 5564 | /* merge rateset coming in with the current mcsset */ |
5529 | if (wlc->pub->_n_enab & SUPPORT_11N) { | 5565 | if (wlc->pub->_n_enab & SUPPORT_11N) { |
5530 | struct brcms_bss_info *mcsset_bss; | 5566 | struct brcms_bss_info *mcsset_bss; |
5531 | if (wlc->bsscfg->associated) | 5567 | if (wlc->pub->associated) |
5532 | mcsset_bss = wlc->bsscfg->current_bss; | 5568 | mcsset_bss = wlc->bsscfg->current_bss; |
5533 | else | 5569 | else |
5534 | mcsset_bss = wlc->default_bss; | 5570 | mcsset_bss = wlc->default_bss; |
@@ -5543,12 +5579,36 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs) | |||
5543 | return bcmerror; | 5579 | return bcmerror; |
5544 | } | 5580 | } |
5545 | 5581 | ||
5582 | static void brcms_c_time_lock(struct brcms_c_info *wlc) | ||
5583 | { | ||
5584 | bcma_set32(wlc->hw->d11core, D11REGOFFS(maccontrol), MCTL_TBTTHOLD); | ||
5585 | /* Commit the write */ | ||
5586 | bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol)); | ||
5587 | } | ||
5588 | |||
5589 | static void brcms_c_time_unlock(struct brcms_c_info *wlc) | ||
5590 | { | ||
5591 | bcma_mask32(wlc->hw->d11core, D11REGOFFS(maccontrol), ~MCTL_TBTTHOLD); | ||
5592 | /* Commit the write */ | ||
5593 | bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol)); | ||
5594 | } | ||
5595 | |||
5546 | int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period) | 5596 | int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period) |
5547 | { | 5597 | { |
5598 | u32 bcnint_us; | ||
5599 | |||
5548 | if (period == 0) | 5600 | if (period == 0) |
5549 | return -EINVAL; | 5601 | return -EINVAL; |
5550 | 5602 | ||
5551 | wlc->default_bss->beacon_period = period; | 5603 | wlc->default_bss->beacon_period = period; |
5604 | |||
5605 | bcnint_us = period << 10; | ||
5606 | brcms_c_time_lock(wlc); | ||
5607 | bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfprep), | ||
5608 | (bcnint_us << CFPREP_CBI_SHIFT)); | ||
5609 | bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfpstart), bcnint_us); | ||
5610 | brcms_c_time_unlock(wlc); | ||
5611 | |||
5552 | return 0; | 5612 | return 0; |
5553 | } | 5613 | } |
5554 | 5614 | ||
@@ -7291,72 +7351,110 @@ brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len) | |||
7291 | } | 7351 | } |
7292 | } | 7352 | } |
7293 | 7353 | ||
7294 | /* Max buffering needed for beacon template/prb resp template is 142 bytes. | 7354 | int brcms_c_get_header_len(void) |
7295 | * | ||
7296 | * PLCP header is 6 bytes. | ||
7297 | * 802.11 A3 header is 24 bytes. | ||
7298 | * Max beacon frame body template length is 112 bytes. | ||
7299 | * Max probe resp frame body template length is 110 bytes. | ||
7300 | * | ||
7301 | * *len on input contains the max length of the packet available. | ||
7302 | * | ||
7303 | * The *len value is set to the number of bytes in buf used, and starts | ||
7304 | * with the PLCP and included up to, but not including, the 4 byte FCS. | ||
7305 | */ | ||
7306 | static void | ||
7307 | brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type, | ||
7308 | u32 bcn_rspec, | ||
7309 | struct brcms_bss_cfg *cfg, u16 *buf, int *len) | ||
7310 | { | 7355 | { |
7311 | static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; | 7356 | return TXOFF; |
7312 | struct cck_phy_hdr *plcp; | 7357 | } |
7313 | struct ieee80211_mgmt *h; | ||
7314 | int hdr_len, body_len; | ||
7315 | |||
7316 | hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN; | ||
7317 | 7358 | ||
7318 | /* calc buffer size provided for frame body */ | 7359 | static void brcms_c_beacon_write(struct brcms_c_info *wlc, |
7319 | body_len = *len - hdr_len; | 7360 | struct sk_buff *beacon, u16 tim_offset, |
7320 | /* return actual size */ | 7361 | u16 dtim_period, bool bcn0, bool bcn1) |
7321 | *len = hdr_len + body_len; | 7362 | { |
7363 | size_t len; | ||
7364 | struct ieee80211_tx_info *tx_info; | ||
7365 | struct brcms_hardware *wlc_hw = wlc->hw; | ||
7366 | struct ieee80211_hw *ieee_hw = brcms_c_pub(wlc)->ieee_hw; | ||
7322 | 7367 | ||
7323 | /* format PHY and MAC headers */ | 7368 | /* Get tx_info */ |
7324 | memset(buf, 0, hdr_len); | 7369 | tx_info = IEEE80211_SKB_CB(beacon); |
7325 | 7370 | ||
7326 | plcp = (struct cck_phy_hdr *) buf; | 7371 | len = min_t(size_t, beacon->len, BCN_TMPL_LEN); |
7372 | wlc->bcn_rspec = ieee80211_get_tx_rate(ieee_hw, tx_info)->hw_value; | ||
7327 | 7373 | ||
7328 | /* | 7374 | brcms_c_compute_plcp(wlc, wlc->bcn_rspec, |
7329 | * PLCP for Probe Response frames are filled in from | 7375 | len + FCS_LEN - D11_PHY_HDR_LEN, beacon->data); |
7330 | * core's rate table | ||
7331 | */ | ||
7332 | if (type == IEEE80211_STYPE_BEACON) | ||
7333 | /* fill in PLCP */ | ||
7334 | brcms_c_compute_plcp(wlc, bcn_rspec, | ||
7335 | (DOT11_MAC_HDR_LEN + body_len + FCS_LEN), | ||
7336 | (u8 *) plcp); | ||
7337 | 7376 | ||
7338 | /* "Regular" and 16 MBSS but not for 4 MBSS */ | 7377 | /* "Regular" and 16 MBSS but not for 4 MBSS */ |
7339 | /* Update the phytxctl for the beacon based on the rspec */ | 7378 | /* Update the phytxctl for the beacon based on the rspec */ |
7340 | brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec); | 7379 | brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec); |
7341 | 7380 | ||
7342 | h = (struct ieee80211_mgmt *)&plcp[1]; | 7381 | if (bcn0) { |
7382 | /* write the probe response into the template region */ | ||
7383 | brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, | ||
7384 | (len + 3) & ~3, beacon->data); | ||
7343 | 7385 | ||
7344 | /* fill in 802.11 header */ | 7386 | /* write beacon length to SCR */ |
7345 | h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type); | 7387 | brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len); |
7388 | } | ||
7389 | if (bcn1) { | ||
7390 | /* write the probe response into the template region */ | ||
7391 | brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, | ||
7392 | (len + 3) & ~3, beacon->data); | ||
7346 | 7393 | ||
7347 | /* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */ | 7394 | /* write beacon length to SCR */ |
7348 | /* A1 filled in by MAC for prb resp, broadcast for bcn */ | 7395 | brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len); |
7349 | if (type == IEEE80211_STYPE_BEACON) | 7396 | } |
7350 | memcpy(&h->da, ðer_bcast, ETH_ALEN); | ||
7351 | memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN); | ||
7352 | memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN); | ||
7353 | 7397 | ||
7354 | /* SEQ filled in by MAC */ | 7398 | if (tim_offset != 0) { |
7399 | brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON, | ||
7400 | tim_offset + D11B_PHY_HDR_LEN); | ||
7401 | brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, dtim_period); | ||
7402 | } else { | ||
7403 | brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON, | ||
7404 | len + D11B_PHY_HDR_LEN); | ||
7405 | brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, 0); | ||
7406 | } | ||
7355 | } | 7407 | } |
7356 | 7408 | ||
7357 | int brcms_c_get_header_len(void) | 7409 | static void brcms_c_update_beacon_hw(struct brcms_c_info *wlc, |
7410 | struct sk_buff *beacon, u16 tim_offset, | ||
7411 | u16 dtim_period) | ||
7358 | { | 7412 | { |
7359 | return TXOFF; | 7413 | struct brcms_hardware *wlc_hw = wlc->hw; |
7414 | struct bcma_device *core = wlc_hw->d11core; | ||
7415 | |||
7416 | /* Hardware beaconing for this config */ | ||
7417 | u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD; | ||
7418 | |||
7419 | /* Check if both templates are in use, if so sched. an interrupt | ||
7420 | * that will call back into this routine | ||
7421 | */ | ||
7422 | if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid) | ||
7423 | /* clear any previous status */ | ||
7424 | bcma_write32(core, D11REGOFFS(macintstatus), MI_BCNTPL); | ||
7425 | |||
7426 | if (wlc->beacon_template_virgin) { | ||
7427 | wlc->beacon_template_virgin = false; | ||
7428 | brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true, | ||
7429 | true); | ||
7430 | /* mark beacon0 valid */ | ||
7431 | bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD); | ||
7432 | return; | ||
7433 | } | ||
7434 | |||
7435 | /* Check that after scheduling the interrupt both of the | ||
7436 | * templates are still busy. if not clear the int. & remask | ||
7437 | */ | ||
7438 | if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid) { | ||
7439 | wlc->defmacintmask |= MI_BCNTPL; | ||
7440 | return; | ||
7441 | } | ||
7442 | |||
7443 | if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN0VLD)) { | ||
7444 | brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true, | ||
7445 | false); | ||
7446 | /* mark beacon0 valid */ | ||
7447 | bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD); | ||
7448 | return; | ||
7449 | } | ||
7450 | if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN1VLD)) { | ||
7451 | brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, | ||
7452 | false, true); | ||
7453 | /* mark beacon0 valid */ | ||
7454 | bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN1VLD); | ||
7455 | return; | ||
7456 | } | ||
7457 | return; | ||
7360 | } | 7458 | } |
7361 | 7459 | ||
7362 | /* | 7460 | /* |
@@ -7366,9 +7464,57 @@ void brcms_c_update_beacon(struct brcms_c_info *wlc) | |||
7366 | { | 7464 | { |
7367 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; | 7465 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; |
7368 | 7466 | ||
7369 | if (bsscfg->up && !bsscfg->BSS) | 7467 | if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP || |
7468 | bsscfg->type == BRCMS_TYPE_ADHOC)) { | ||
7370 | /* Clear the soft intmask */ | 7469 | /* Clear the soft intmask */ |
7371 | wlc->defmacintmask &= ~MI_BCNTPL; | 7470 | wlc->defmacintmask &= ~MI_BCNTPL; |
7471 | if (!wlc->beacon) | ||
7472 | return; | ||
7473 | brcms_c_update_beacon_hw(wlc, wlc->beacon, | ||
7474 | wlc->beacon_tim_offset, | ||
7475 | wlc->beacon_dtim_period); | ||
7476 | } | ||
7477 | } | ||
7478 | |||
7479 | void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon, | ||
7480 | u16 tim_offset, u16 dtim_period) | ||
7481 | { | ||
7482 | if (!beacon) | ||
7483 | return; | ||
7484 | if (wlc->beacon) | ||
7485 | dev_kfree_skb_any(wlc->beacon); | ||
7486 | wlc->beacon = beacon; | ||
7487 | |||
7488 | /* add PLCP */ | ||
7489 | skb_push(wlc->beacon, D11_PHY_HDR_LEN); | ||
7490 | wlc->beacon_tim_offset = tim_offset; | ||
7491 | wlc->beacon_dtim_period = dtim_period; | ||
7492 | brcms_c_update_beacon(wlc); | ||
7493 | } | ||
7494 | |||
7495 | void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc, | ||
7496 | struct sk_buff *probe_resp) | ||
7497 | { | ||
7498 | if (!probe_resp) | ||
7499 | return; | ||
7500 | if (wlc->probe_resp) | ||
7501 | dev_kfree_skb_any(wlc->probe_resp); | ||
7502 | wlc->probe_resp = probe_resp; | ||
7503 | |||
7504 | /* add PLCP */ | ||
7505 | skb_push(wlc->probe_resp, D11_PHY_HDR_LEN); | ||
7506 | brcms_c_update_probe_resp(wlc, false); | ||
7507 | } | ||
7508 | |||
7509 | void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable) | ||
7510 | { | ||
7511 | /* | ||
7512 | * prevent ucode from sending probe responses by setting the timeout | ||
7513 | * to 1, it can not send it in that time frame. | ||
7514 | */ | ||
7515 | wlc->prb_resp_timeout = enable ? BRCMS_PRB_RESP_TIMEOUT : 1; | ||
7516 | brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout); | ||
7517 | /* TODO: if (enable) => also deactivate receiving of probe request */ | ||
7372 | } | 7518 | } |
7373 | 7519 | ||
7374 | /* Write ssid into shared memory */ | 7520 | /* Write ssid into shared memory */ |
@@ -7390,30 +7536,19 @@ brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg) | |||
7390 | static void | 7536 | static void |
7391 | brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, | 7537 | brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, |
7392 | struct brcms_bss_cfg *cfg, | 7538 | struct brcms_bss_cfg *cfg, |
7539 | struct sk_buff *probe_resp, | ||
7393 | bool suspend) | 7540 | bool suspend) |
7394 | { | 7541 | { |
7395 | u16 *prb_resp; | 7542 | int len; |
7396 | int len = BCN_TMPL_LEN; | ||
7397 | |||
7398 | prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC); | ||
7399 | if (!prb_resp) | ||
7400 | return; | ||
7401 | |||
7402 | /* | ||
7403 | * write the probe response to hardware, or save in | ||
7404 | * the config structure | ||
7405 | */ | ||
7406 | 7543 | ||
7407 | /* create the probe response template */ | 7544 | len = min_t(size_t, probe_resp->len, BCN_TMPL_LEN); |
7408 | brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0, | ||
7409 | cfg, prb_resp, &len); | ||
7410 | 7545 | ||
7411 | if (suspend) | 7546 | if (suspend) |
7412 | brcms_c_suspend_mac_and_wait(wlc); | 7547 | brcms_c_suspend_mac_and_wait(wlc); |
7413 | 7548 | ||
7414 | /* write the probe response into the template region */ | 7549 | /* write the probe response into the template region */ |
7415 | brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE, | 7550 | brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE, |
7416 | (len + 3) & ~3, prb_resp); | 7551 | (len + 3) & ~3, probe_resp->data); |
7417 | 7552 | ||
7418 | /* write the length of the probe response frame (+PLCP/-FCS) */ | 7553 | /* write the length of the probe response frame (+PLCP/-FCS) */ |
7419 | brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len); | 7554 | brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len); |
@@ -7427,13 +7562,11 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, | |||
7427 | * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table() | 7562 | * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table() |
7428 | * by subtracting the PLCP len and adding the FCS. | 7563 | * by subtracting the PLCP len and adding the FCS. |
7429 | */ | 7564 | */ |
7430 | len += (-D11_PHY_HDR_LEN + FCS_LEN); | 7565 | brcms_c_mod_prb_rsp_rate_table(wlc, |
7431 | brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len); | 7566 | (u16)len + FCS_LEN - D11_PHY_HDR_LEN); |
7432 | 7567 | ||
7433 | if (suspend) | 7568 | if (suspend) |
7434 | brcms_c_enable_mac(wlc); | 7569 | brcms_c_enable_mac(wlc); |
7435 | |||
7436 | kfree(prb_resp); | ||
7437 | } | 7570 | } |
7438 | 7571 | ||
7439 | void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) | 7572 | void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) |
@@ -7441,8 +7574,13 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) | |||
7441 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; | 7574 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; |
7442 | 7575 | ||
7443 | /* update AP or IBSS probe responses */ | 7576 | /* update AP or IBSS probe responses */ |
7444 | if (bsscfg->up && !bsscfg->BSS) | 7577 | if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP || |
7445 | brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); | 7578 | bsscfg->type == BRCMS_TYPE_ADHOC)) { |
7579 | if (!wlc->probe_resp) | ||
7580 | return; | ||
7581 | brcms_c_bss_update_probe_resp(wlc, bsscfg, wlc->probe_resp, | ||
7582 | suspend); | ||
7583 | } | ||
7446 | } | 7584 | } |
7447 | 7585 | ||
7448 | int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, | 7586 | int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, |
@@ -7481,7 +7619,6 @@ void brcms_c_scan_stop(struct brcms_c_info *wlc) | |||
7481 | void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state) | 7619 | void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state) |
7482 | { | 7620 | { |
7483 | wlc->pub->associated = state; | 7621 | wlc->pub->associated = state; |
7484 | wlc->bsscfg->associated = state; | ||
7485 | } | 7622 | } |
7486 | 7623 | ||
7487 | /* | 7624 | /* |
@@ -7526,6 +7663,36 @@ void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) | |||
7526 | brcms_c_bcn_li_upd(wlc); | 7663 | brcms_c_bcn_li_upd(wlc); |
7527 | } | 7664 | } |
7528 | 7665 | ||
7666 | u64 brcms_c_tsf_get(struct brcms_c_info *wlc) | ||
7667 | { | ||
7668 | u32 tsf_h, tsf_l; | ||
7669 | u64 tsf; | ||
7670 | |||
7671 | brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h); | ||
7672 | |||
7673 | tsf = tsf_h; | ||
7674 | tsf <<= 32; | ||
7675 | tsf |= tsf_l; | ||
7676 | |||
7677 | return tsf; | ||
7678 | } | ||
7679 | |||
7680 | void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf) | ||
7681 | { | ||
7682 | u32 tsf_h, tsf_l; | ||
7683 | |||
7684 | brcms_c_time_lock(wlc); | ||
7685 | |||
7686 | tsf_l = tsf; | ||
7687 | tsf_h = (tsf >> 32); | ||
7688 | |||
7689 | /* read the tsf timer low, then high to get an atomic read */ | ||
7690 | bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerlow), tsf_l); | ||
7691 | bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerhigh), tsf_h); | ||
7692 | |||
7693 | brcms_c_time_unlock(wlc); | ||
7694 | } | ||
7695 | |||
7529 | int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr) | 7696 | int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr) |
7530 | { | 7697 | { |
7531 | uint qdbm; | 7698 | uint qdbm; |
@@ -7737,6 +7904,10 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) | |||
7737 | brcms_rfkill_set_hw_state(wlc->wl); | 7904 | brcms_rfkill_set_hw_state(wlc->wl); |
7738 | } | 7905 | } |
7739 | 7906 | ||
7907 | /* BCN template is available */ | ||
7908 | if (macintstatus & MI_BCNTPL) | ||
7909 | brcms_c_update_beacon(wlc); | ||
7910 | |||
7740 | /* it isn't done and needs to be resched if macintstatus is non-zero */ | 7911 | /* it isn't done and needs to be resched if macintstatus is non-zero */ |
7741 | return wlc->macintstatus != 0; | 7912 | return wlc->macintstatus != 0; |
7742 | 7913 | ||
@@ -7765,7 +7936,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | |||
7765 | brcms_c_set_bssid(wlc->bsscfg); | 7936 | brcms_c_set_bssid(wlc->bsscfg); |
7766 | 7937 | ||
7767 | /* Update tsf_cfprep if associated and up */ | 7938 | /* Update tsf_cfprep if associated and up */ |
7768 | if (wlc->pub->associated && wlc->bsscfg->up) { | 7939 | if (wlc->pub->associated && wlc->pub->up) { |
7769 | u32 bi; | 7940 | u32 bi; |
7770 | 7941 | ||
7771 | /* get beacon period and convert to uS */ | 7942 | /* get beacon period and convert to uS */ |
@@ -7810,9 +7981,14 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | |||
7810 | 7981 | ||
7811 | /* read the ucode version if we have not yet done so */ | 7982 | /* read the ucode version if we have not yet done so */ |
7812 | if (wlc->ucode_rev == 0) { | 7983 | if (wlc->ucode_rev == 0) { |
7813 | wlc->ucode_rev = | 7984 | u16 rev; |
7814 | brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16); | 7985 | u16 patch; |
7815 | wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); | 7986 | |
7987 | rev = brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR); | ||
7988 | patch = brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); | ||
7989 | wlc->ucode_rev = (rev << NBITS(u16)) | patch; | ||
7990 | snprintf(wlc->wiphy->fw_version, | ||
7991 | sizeof(wlc->wiphy->fw_version), "%u.%u", rev, patch); | ||
7816 | } | 7992 | } |
7817 | 7993 | ||
7818 | /* ..now really unleash hell (allow the MAC out of suspend) */ | 7994 | /* ..now really unleash hell (allow the MAC out of suspend) */ |
@@ -7868,6 +8044,7 @@ brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit, | |||
7868 | pub->unit = unit; | 8044 | pub->unit = unit; |
7869 | pub->_piomode = piomode; | 8045 | pub->_piomode = piomode; |
7870 | wlc->bandinit_pending = false; | 8046 | wlc->bandinit_pending = false; |
8047 | wlc->beacon_template_virgin = true; | ||
7871 | 8048 | ||
7872 | /* populate struct brcms_c_info with default values */ | 8049 | /* populate struct brcms_c_info with default values */ |
7873 | brcms_c_info_init(wlc, unit); | 8050 | brcms_c_info_init(wlc, unit); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h index fb447747c2c6..b5d7a38b53fe 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h | |||
@@ -492,6 +492,8 @@ struct brcms_c_info { | |||
492 | bool radio_monitor; | 492 | bool radio_monitor; |
493 | bool going_down; | 493 | bool going_down; |
494 | 494 | ||
495 | bool beacon_template_virgin; | ||
496 | |||
495 | struct brcms_timer *wdtimer; | 497 | struct brcms_timer *wdtimer; |
496 | struct brcms_timer *radio_timer; | 498 | struct brcms_timer *radio_timer; |
497 | 499 | ||
@@ -561,6 +563,11 @@ struct brcms_c_info { | |||
561 | 563 | ||
562 | struct wiphy *wiphy; | 564 | struct wiphy *wiphy; |
563 | struct scb pri_scb; | 565 | struct scb pri_scb; |
566 | |||
567 | struct sk_buff *beacon; | ||
568 | u16 beacon_tim_offset; | ||
569 | u16 beacon_dtim_period; | ||
570 | struct sk_buff *probe_resp; | ||
564 | }; | 571 | }; |
565 | 572 | ||
566 | /* antsel module specific state */ | 573 | /* antsel module specific state */ |
@@ -576,14 +583,17 @@ struct antsel_info { | |||
576 | struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */ | 583 | struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */ |
577 | }; | 584 | }; |
578 | 585 | ||
586 | enum brcms_bss_type { | ||
587 | BRCMS_TYPE_STATION, | ||
588 | BRCMS_TYPE_AP, | ||
589 | BRCMS_TYPE_ADHOC, | ||
590 | }; | ||
591 | |||
579 | /* | 592 | /* |
580 | * BSS configuration state | 593 | * BSS configuration state |
581 | * | 594 | * |
582 | * wlc: wlc to which this bsscfg belongs to. | 595 | * wlc: wlc to which this bsscfg belongs to. |
583 | * up: is this configuration up operational | 596 | * type: interface type |
584 | * enable: is this configuration enabled | ||
585 | * associated: is BSS in ASSOCIATED state | ||
586 | * BSS: infraustructure or adhoc | ||
587 | * SSID_len: the length of SSID | 597 | * SSID_len: the length of SSID |
588 | * SSID: SSID string | 598 | * SSID: SSID string |
589 | * | 599 | * |
@@ -599,14 +609,10 @@ struct antsel_info { | |||
599 | */ | 609 | */ |
600 | struct brcms_bss_cfg { | 610 | struct brcms_bss_cfg { |
601 | struct brcms_c_info *wlc; | 611 | struct brcms_c_info *wlc; |
602 | bool up; | 612 | enum brcms_bss_type type; |
603 | bool enable; | ||
604 | bool associated; | ||
605 | bool BSS; | ||
606 | u8 SSID_len; | 613 | u8 SSID_len; |
607 | u8 SSID[IEEE80211_MAX_SSID_LEN]; | 614 | u8 SSID[IEEE80211_MAX_SSID_LEN]; |
608 | u8 BSSID[ETH_ALEN]; | 615 | u8 BSSID[ETH_ALEN]; |
609 | u8 cur_etheraddr[ETH_ALEN]; | ||
610 | struct brcms_bss_info *current_bss; | 616 | struct brcms_bss_info *current_bss; |
611 | }; | 617 | }; |
612 | 618 | ||
@@ -631,7 +637,6 @@ extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, | |||
631 | extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, | 637 | extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, |
632 | struct ieee80211_sta *sta, | 638 | struct ieee80211_sta *sta, |
633 | void (*dma_callback_fn)); | 639 | void (*dma_callback_fn)); |
634 | extern void brcms_c_update_beacon(struct brcms_c_info *wlc); | ||
635 | extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend); | 640 | extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend); |
636 | extern int brcms_c_set_nmode(struct brcms_c_info *wlc); | 641 | extern int brcms_c_set_nmode(struct brcms_c_info *wlc); |
637 | extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, | 642 | extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c index 91937c5025ce..b0fd807f2b2b 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c | |||
@@ -198,8 +198,6 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr) | |||
198 | 198 | ||
199 | void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) | 199 | void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) |
200 | { | 200 | { |
201 | struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); | ||
202 | |||
203 | if ((D11REV_GE(pi->sh->corerev, 24)) || | 201 | if ((D11REV_GE(pi->sh->corerev, 24)) || |
204 | (D11REV_IS(pi->sh->corerev, 22) | 202 | (D11REV_IS(pi->sh->corerev, 22) |
205 | && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { | 203 | && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { |
@@ -211,7 +209,7 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) | |||
211 | bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val); | 209 | bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val); |
212 | } | 210 | } |
213 | 211 | ||
214 | if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) && | 212 | if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) && |
215 | (++pi->phy_wreg >= pi->phy_wreg_limit)) { | 213 | (++pi->phy_wreg >= pi->phy_wreg_limit)) { |
216 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); | 214 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
217 | pi->phy_wreg = 0; | 215 | pi->phy_wreg = 0; |
@@ -297,10 +295,8 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) | |||
297 | if (addr == 0x72) | 295 | if (addr == 0x72) |
298 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata)); | 296 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata)); |
299 | #else | 297 | #else |
300 | struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); | ||
301 | |||
302 | bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16)); | 298 | bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16)); |
303 | if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) && | 299 | if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) && |
304 | (++pi->phy_wreg >= pi->phy_wreg_limit)) { | 300 | (++pi->phy_wreg >= pi->phy_wreg_limit)) { |
305 | pi->phy_wreg = 0; | 301 | pi->phy_wreg = 0; |
306 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); | 302 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); |
@@ -374,7 +370,6 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp) | |||
374 | if (sh == NULL) | 370 | if (sh == NULL) |
375 | return NULL; | 371 | return NULL; |
376 | 372 | ||
377 | sh->sih = shp->sih; | ||
378 | sh->physhim = shp->physhim; | 373 | sh->physhim = shp->physhim; |
379 | sh->unit = shp->unit; | 374 | sh->unit = shp->unit; |
380 | sh->corerev = shp->corerev; | 375 | sh->corerev = shp->corerev; |
@@ -2911,29 +2906,24 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) | |||
2911 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); | 2906 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); |
2912 | 2907 | ||
2913 | } | 2908 | } |
2914 | ai_cc_reg(pi->sh->sih, | 2909 | |
2915 | offsetof(struct chipcregs, gpiocontrol), | 2910 | bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, |
2916 | ~0x0, 0x0); | 2911 | 0x0, 0x0); |
2917 | ai_cc_reg(pi->sh->sih, | 2912 | bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc, |
2918 | offsetof(struct chipcregs, gpioout), | 2913 | ~0x40, 0x40); |
2919 | 0x40, 0x40); | 2914 | bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc, |
2920 | ai_cc_reg(pi->sh->sih, | 2915 | ~0x40, 0x40); |
2921 | offsetof(struct chipcregs, gpioouten), | ||
2922 | 0x40, 0x40); | ||
2923 | } else { | 2916 | } else { |
2924 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); | 2917 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); |
2925 | 2918 | ||
2926 | mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); | 2919 | mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); |
2927 | 2920 | ||
2928 | ai_cc_reg(pi->sh->sih, | 2921 | bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc, |
2929 | offsetof(struct chipcregs, gpioout), | 2922 | ~0x40, 0x00); |
2930 | 0x40, 0x00); | 2923 | bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc, |
2931 | ai_cc_reg(pi->sh->sih, | 2924 | ~0x40, 0x00); |
2932 | offsetof(struct chipcregs, gpioouten), | 2925 | bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, |
2933 | 0x40, 0x0); | 2926 | 0x0, 0x40); |
2934 | ai_cc_reg(pi->sh->sih, | ||
2935 | offsetof(struct chipcregs, gpiocontrol), | ||
2936 | ~0x0, 0x40); | ||
2937 | } | 2927 | } |
2938 | } | 2928 | } |
2939 | } | 2929 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h index af00e2c2b266..1dc767c31653 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h | |||
@@ -488,7 +488,6 @@ struct lcnphy_cal_results { | |||
488 | struct shared_phy { | 488 | struct shared_phy { |
489 | struct brcms_phy *phy_head; | 489 | struct brcms_phy *phy_head; |
490 | uint unit; | 490 | uint unit; |
491 | struct si_pub *sih; | ||
492 | struct phy_shim_info *physhim; | 491 | struct phy_shim_info *physhim; |
493 | uint corerev; | 492 | uint corerev; |
494 | u32 machwcap; | 493 | u32 machwcap; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c index 21a824232478..3d6b16ce4687 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c | |||
@@ -1137,9 +1137,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, | |||
1137 | gain0_15 = ((biq1 & 0xf) << 12) | | 1137 | gain0_15 = ((biq1 & 0xf) << 12) | |
1138 | ((tia & 0xf) << 8) | | 1138 | ((tia & 0xf) << 8) | |
1139 | ((lna2 & 0x3) << 6) | | 1139 | ((lna2 & 0x3) << 6) | |
1140 | ((lna2 & 0x3) << 4) | | 1140 | ((lna2 & |
1141 | ((lna1 & 0x3) << 2) | | 1141 | 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0); |
1142 | ((lna1 & 0x3) << 0); | ||
1143 | 1142 | ||
1144 | mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); | 1143 | mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); |
1145 | mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); | 1144 | mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); |
@@ -1157,8 +1156,6 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, | |||
1157 | } | 1156 | } |
1158 | 1157 | ||
1159 | mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0); | 1158 | mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0); |
1160 | mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); | ||
1161 | mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3); | ||
1162 | 1159 | ||
1163 | } | 1160 | } |
1164 | 1161 | ||
@@ -1331,43 +1328,6 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples) | |||
1331 | return (iq_est.i_pwr + iq_est.q_pwr) / nsamples; | 1328 | return (iq_est.i_pwr + iq_est.q_pwr) / nsamples; |
1332 | } | 1329 | } |
1333 | 1330 | ||
1334 | static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain, | ||
1335 | u16 tia_gain, u16 lna2_gain) | ||
1336 | { | ||
1337 | u32 i_thresh_l, q_thresh_l; | ||
1338 | u32 i_thresh_h, q_thresh_h; | ||
1339 | struct lcnphy_iq_est iq_est_h, iq_est_l; | ||
1340 | |||
1341 | wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain, | ||
1342 | lna2_gain, 0); | ||
1343 | |||
1344 | wlc_lcnphy_rx_gain_override_enable(pi, true); | ||
1345 | wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0); | ||
1346 | udelay(500); | ||
1347 | write_radio_reg(pi, RADIO_2064_REG112, 0); | ||
1348 | if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l)) | ||
1349 | return false; | ||
1350 | |||
1351 | wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0); | ||
1352 | udelay(500); | ||
1353 | write_radio_reg(pi, RADIO_2064_REG112, 0); | ||
1354 | if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h)) | ||
1355 | return false; | ||
1356 | |||
1357 | i_thresh_l = (iq_est_l.i_pwr << 1); | ||
1358 | i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr; | ||
1359 | |||
1360 | q_thresh_l = (iq_est_l.q_pwr << 1); | ||
1361 | q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr; | ||
1362 | if ((iq_est_h.i_pwr > i_thresh_l) && | ||
1363 | (iq_est_h.i_pwr < i_thresh_h) && | ||
1364 | (iq_est_h.q_pwr > q_thresh_l) && | ||
1365 | (iq_est_h.q_pwr < q_thresh_h)) | ||
1366 | return true; | ||
1367 | |||
1368 | return false; | ||
1369 | } | ||
1370 | |||
1371 | static bool | 1331 | static bool |
1372 | wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, | 1332 | wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, |
1373 | const struct lcnphy_rx_iqcomp *iqcomp, | 1333 | const struct lcnphy_rx_iqcomp *iqcomp, |
@@ -1382,8 +1342,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, | |||
1382 | RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old, | 1342 | RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old, |
1383 | rfoverride3_old, rfoverride3val_old, rfoverride4_old, | 1343 | rfoverride3_old, rfoverride3val_old, rfoverride4_old, |
1384 | rfoverride4val_old, afectrlovr_old, afectrlovrval_old; | 1344 | rfoverride4val_old, afectrlovr_old, afectrlovrval_old; |
1385 | int tia_gain, lna2_gain, biq1_gain; | 1345 | int tia_gain; |
1386 | bool set_gain; | 1346 | u32 received_power, rx_pwr_threshold; |
1387 | u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl; | 1347 | u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl; |
1388 | u16 values_to_save[11]; | 1348 | u16 values_to_save[11]; |
1389 | s16 *ptr; | 1349 | s16 *ptr; |
@@ -1408,134 +1368,126 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, | |||
1408 | goto cal_done; | 1368 | goto cal_done; |
1409 | } | 1369 | } |
1410 | 1370 | ||
1411 | WARN_ON(module != 1); | 1371 | if (module == 1) { |
1412 | tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); | ||
1413 | wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); | ||
1414 | |||
1415 | for (i = 0; i < 11; i++) | ||
1416 | values_to_save[i] = | ||
1417 | read_radio_reg(pi, rxiq_cal_rf_reg[i]); | ||
1418 | Core1TxControl_old = read_phy_reg(pi, 0x631); | ||
1419 | |||
1420 | or_phy_reg(pi, 0x631, 0x0015); | ||
1421 | |||
1422 | RFOverride0_old = read_phy_reg(pi, 0x44c); | ||
1423 | RFOverrideVal0_old = read_phy_reg(pi, 0x44d); | ||
1424 | rfoverride2_old = read_phy_reg(pi, 0x4b0); | ||
1425 | rfoverride2val_old = read_phy_reg(pi, 0x4b1); | ||
1426 | rfoverride3_old = read_phy_reg(pi, 0x4f9); | ||
1427 | rfoverride3val_old = read_phy_reg(pi, 0x4fa); | ||
1428 | rfoverride4_old = read_phy_reg(pi, 0x938); | ||
1429 | rfoverride4val_old = read_phy_reg(pi, 0x939); | ||
1430 | afectrlovr_old = read_phy_reg(pi, 0x43b); | ||
1431 | afectrlovrval_old = read_phy_reg(pi, 0x43c); | ||
1432 | old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); | ||
1433 | old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); | ||
1434 | |||
1435 | tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); | ||
1436 | if (tx_gain_override_old) { | ||
1437 | wlc_lcnphy_get_tx_gain(pi, &old_gains); | ||
1438 | tx_gain_index_old = pi_lcn->lcnphy_current_index; | ||
1439 | } | ||
1440 | |||
1441 | wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); | ||
1442 | 1372 | ||
1443 | mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); | 1373 | tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); |
1444 | mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); | 1374 | wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); |
1445 | 1375 | ||
1446 | mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); | 1376 | for (i = 0; i < 11; i++) |
1447 | mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); | 1377 | values_to_save[i] = |
1378 | read_radio_reg(pi, rxiq_cal_rf_reg[i]); | ||
1379 | Core1TxControl_old = read_phy_reg(pi, 0x631); | ||
1380 | |||
1381 | or_phy_reg(pi, 0x631, 0x0015); | ||
1382 | |||
1383 | RFOverride0_old = read_phy_reg(pi, 0x44c); | ||
1384 | RFOverrideVal0_old = read_phy_reg(pi, 0x44d); | ||
1385 | rfoverride2_old = read_phy_reg(pi, 0x4b0); | ||
1386 | rfoverride2val_old = read_phy_reg(pi, 0x4b1); | ||
1387 | rfoverride3_old = read_phy_reg(pi, 0x4f9); | ||
1388 | rfoverride3val_old = read_phy_reg(pi, 0x4fa); | ||
1389 | rfoverride4_old = read_phy_reg(pi, 0x938); | ||
1390 | rfoverride4val_old = read_phy_reg(pi, 0x939); | ||
1391 | afectrlovr_old = read_phy_reg(pi, 0x43b); | ||
1392 | afectrlovrval_old = read_phy_reg(pi, 0x43c); | ||
1393 | old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); | ||
1394 | old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); | ||
1395 | |||
1396 | tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); | ||
1397 | if (tx_gain_override_old) { | ||
1398 | wlc_lcnphy_get_tx_gain(pi, &old_gains); | ||
1399 | tx_gain_index_old = pi_lcn->lcnphy_current_index; | ||
1400 | } | ||
1448 | 1401 | ||
1449 | write_radio_reg(pi, RADIO_2064_REG116, 0x06); | 1402 | wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); |
1450 | write_radio_reg(pi, RADIO_2064_REG12C, 0x07); | ||
1451 | write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); | ||
1452 | write_radio_reg(pi, RADIO_2064_REG098, 0x03); | ||
1453 | write_radio_reg(pi, RADIO_2064_REG00B, 0x7); | ||
1454 | mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); | ||
1455 | write_radio_reg(pi, RADIO_2064_REG01D, 0x01); | ||
1456 | write_radio_reg(pi, RADIO_2064_REG114, 0x01); | ||
1457 | write_radio_reg(pi, RADIO_2064_REG02E, 0x10); | ||
1458 | write_radio_reg(pi, RADIO_2064_REG12A, 0x08); | ||
1459 | |||
1460 | mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); | ||
1461 | mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); | ||
1462 | mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); | ||
1463 | mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); | ||
1464 | mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); | ||
1465 | mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); | ||
1466 | mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); | ||
1467 | mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); | ||
1468 | mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); | ||
1469 | mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); | ||
1470 | 1403 | ||
1471 | mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); | 1404 | mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); |
1472 | mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); | 1405 | mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); |
1473 | 1406 | ||
1474 | write_phy_reg(pi, 0x6da, 0xffff); | 1407 | mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); |
1475 | or_phy_reg(pi, 0x6db, 0x3); | 1408 | mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); |
1476 | 1409 | ||
1477 | wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); | 1410 | write_radio_reg(pi, RADIO_2064_REG116, 0x06); |
1478 | set_gain = false; | 1411 | write_radio_reg(pi, RADIO_2064_REG12C, 0x07); |
1479 | 1412 | write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); | |
1480 | lna2_gain = 3; | 1413 | write_radio_reg(pi, RADIO_2064_REG098, 0x03); |
1481 | while ((lna2_gain >= 0) && !set_gain) { | 1414 | write_radio_reg(pi, RADIO_2064_REG00B, 0x7); |
1482 | tia_gain = 4; | 1415 | mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); |
1483 | 1416 | write_radio_reg(pi, RADIO_2064_REG01D, 0x01); | |
1484 | while ((tia_gain >= 0) && !set_gain) { | 1417 | write_radio_reg(pi, RADIO_2064_REG114, 0x01); |
1485 | biq1_gain = 6; | 1418 | write_radio_reg(pi, RADIO_2064_REG02E, 0x10); |
1486 | 1419 | write_radio_reg(pi, RADIO_2064_REG12A, 0x08); | |
1487 | while ((biq1_gain >= 0) && !set_gain) { | 1420 | |
1488 | set_gain = wlc_lcnphy_rx_iq_cal_gain(pi, | 1421 | mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); |
1489 | (u16) | 1422 | mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); |
1490 | biq1_gain, | 1423 | mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); |
1491 | (u16) | 1424 | mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); |
1492 | tia_gain, | 1425 | mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); |
1493 | (u16) | 1426 | mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); |
1494 | lna2_gain); | 1427 | mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); |
1495 | biq1_gain -= 1; | 1428 | mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); |
1496 | } | 1429 | mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); |
1430 | mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); | ||
1431 | |||
1432 | mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); | ||
1433 | mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); | ||
1434 | |||
1435 | wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0); | ||
1436 | write_phy_reg(pi, 0x6da, 0xffff); | ||
1437 | or_phy_reg(pi, 0x6db, 0x3); | ||
1438 | wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); | ||
1439 | wlc_lcnphy_rx_gain_override_enable(pi, true); | ||
1440 | |||
1441 | tia_gain = 8; | ||
1442 | rx_pwr_threshold = 950; | ||
1443 | while (tia_gain > 0) { | ||
1497 | tia_gain -= 1; | 1444 | tia_gain -= 1; |
1445 | wlc_lcnphy_set_rx_gain_by_distribution(pi, | ||
1446 | 0, 0, 2, 2, | ||
1447 | (u16) | ||
1448 | tia_gain, 1, 0); | ||
1449 | udelay(500); | ||
1450 | |||
1451 | received_power = | ||
1452 | wlc_lcnphy_measure_digital_power(pi, 2000); | ||
1453 | if (received_power < rx_pwr_threshold) | ||
1454 | break; | ||
1498 | } | 1455 | } |
1499 | lna2_gain -= 1; | 1456 | result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff); |
1500 | } | ||
1501 | 1457 | ||
1502 | if (set_gain) | 1458 | wlc_lcnphy_stop_tx_tone(pi); |
1503 | result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024); | ||
1504 | else | ||
1505 | result = false; | ||
1506 | 1459 | ||
1507 | wlc_lcnphy_stop_tx_tone(pi); | 1460 | write_phy_reg(pi, 0x631, Core1TxControl_old); |
1508 | 1461 | ||
1509 | write_phy_reg(pi, 0x631, Core1TxControl_old); | 1462 | write_phy_reg(pi, 0x44c, RFOverrideVal0_old); |
1510 | 1463 | write_phy_reg(pi, 0x44d, RFOverrideVal0_old); | |
1511 | write_phy_reg(pi, 0x44c, RFOverrideVal0_old); | 1464 | write_phy_reg(pi, 0x4b0, rfoverride2_old); |
1512 | write_phy_reg(pi, 0x44d, RFOverrideVal0_old); | 1465 | write_phy_reg(pi, 0x4b1, rfoverride2val_old); |
1513 | write_phy_reg(pi, 0x4b0, rfoverride2_old); | 1466 | write_phy_reg(pi, 0x4f9, rfoverride3_old); |
1514 | write_phy_reg(pi, 0x4b1, rfoverride2val_old); | 1467 | write_phy_reg(pi, 0x4fa, rfoverride3val_old); |
1515 | write_phy_reg(pi, 0x4f9, rfoverride3_old); | 1468 | write_phy_reg(pi, 0x938, rfoverride4_old); |
1516 | write_phy_reg(pi, 0x4fa, rfoverride3val_old); | 1469 | write_phy_reg(pi, 0x939, rfoverride4val_old); |
1517 | write_phy_reg(pi, 0x938, rfoverride4_old); | 1470 | write_phy_reg(pi, 0x43b, afectrlovr_old); |
1518 | write_phy_reg(pi, 0x939, rfoverride4val_old); | 1471 | write_phy_reg(pi, 0x43c, afectrlovrval_old); |
1519 | write_phy_reg(pi, 0x43b, afectrlovr_old); | 1472 | write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); |
1520 | write_phy_reg(pi, 0x43c, afectrlovrval_old); | 1473 | write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); |
1521 | write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); | ||
1522 | write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); | ||
1523 | 1474 | ||
1524 | wlc_lcnphy_clear_trsw_override(pi); | 1475 | wlc_lcnphy_clear_trsw_override(pi); |
1525 | 1476 | ||
1526 | mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); | 1477 | mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); |
1527 | 1478 | ||
1528 | for (i = 0; i < 11; i++) | 1479 | for (i = 0; i < 11; i++) |
1529 | write_radio_reg(pi, rxiq_cal_rf_reg[i], | 1480 | write_radio_reg(pi, rxiq_cal_rf_reg[i], |
1530 | values_to_save[i]); | 1481 | values_to_save[i]); |
1531 | 1482 | ||
1532 | if (tx_gain_override_old) | 1483 | if (tx_gain_override_old) |
1533 | wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); | 1484 | wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); |
1534 | else | 1485 | else |
1535 | wlc_lcnphy_disable_tx_gain_override(pi); | 1486 | wlc_lcnphy_disable_tx_gain_override(pi); |
1536 | 1487 | ||
1537 | wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); | 1488 | wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); |
1538 | wlc_lcnphy_rx_gain_override_enable(pi, false); | 1489 | wlc_lcnphy_rx_gain_override_enable(pi, false); |
1490 | } | ||
1539 | 1491 | ||
1540 | cal_done: | 1492 | cal_done: |
1541 | kfree(ptr); | 1493 | kfree(ptr); |
@@ -1643,11 +1595,15 @@ wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec) | |||
1643 | if (channel == 1 || channel == 2 || channel == 3 || | 1595 | if (channel == 1 || channel == 2 || channel == 3 || |
1644 | channel == 4 || channel == 9 || | 1596 | channel == 4 || channel == 9 || |
1645 | channel == 10 || channel == 11 || channel == 12) { | 1597 | channel == 10 || channel == 11 || channel == 12) { |
1646 | si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04); | 1598 | bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2, |
1647 | si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0); | 1599 | 0x03000c04); |
1648 | si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0); | 1600 | bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3, |
1649 | 1601 | ~0x00ffffff, 0x0); | |
1650 | si_pmu_pllupd(pi->sh->sih); | 1602 | bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4, |
1603 | 0x200005c0); | ||
1604 | |||
1605 | bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL, | ||
1606 | BCMA_CC_PMU_CTL_PLL_UPD); | ||
1651 | write_phy_reg(pi, 0x942, 0); | 1607 | write_phy_reg(pi, 0x942, 0); |
1652 | wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); | 1608 | wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); |
1653 | pi_lcn->lcnphy_spurmod = false; | 1609 | pi_lcn->lcnphy_spurmod = false; |
@@ -1655,11 +1611,15 @@ wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec) | |||
1655 | 1611 | ||
1656 | write_phy_reg(pi, 0x425, 0x5907); | 1612 | write_phy_reg(pi, 0x425, 0x5907); |
1657 | } else { | 1613 | } else { |
1658 | si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04); | 1614 | bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2, |
1659 | si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333); | 1615 | 0x03140c04); |
1660 | si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820); | 1616 | bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3, |
1661 | 1617 | ~0x00ffffff, 0x333333); | |
1662 | si_pmu_pllupd(pi->sh->sih); | 1618 | bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4, |
1619 | 0x202c2820); | ||
1620 | |||
1621 | bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL, | ||
1622 | BCMA_CC_PMU_CTL_PLL_UPD); | ||
1663 | write_phy_reg(pi, 0x942, 0); | 1623 | write_phy_reg(pi, 0x942, 0); |
1664 | wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); | 1624 | wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); |
1665 | 1625 | ||
@@ -1829,17 +1789,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) | |||
1829 | write_radio_reg(pi, RADIO_2064_REG038, 3); | 1789 | write_radio_reg(pi, RADIO_2064_REG038, 3); |
1830 | write_radio_reg(pi, RADIO_2064_REG091, 7); | 1790 | write_radio_reg(pi, RADIO_2064_REG091, 7); |
1831 | } | 1791 | } |
1832 | |||
1833 | if (!(pi->sh->boardflags & BFL_FEM)) { | ||
1834 | u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc, | ||
1835 | 0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0}; | ||
1836 | |||
1837 | write_radio_reg(pi, RADIO_2064_REG02A, 0xf); | ||
1838 | write_radio_reg(pi, RADIO_2064_REG091, 0x3); | ||
1839 | write_radio_reg(pi, RADIO_2064_REG038, 0x3); | ||
1840 | |||
1841 | write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]); | ||
1842 | } | ||
1843 | } | 1792 | } |
1844 | 1793 | ||
1845 | static int | 1794 | static int |
@@ -2034,16 +1983,6 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos) | |||
2034 | } else { | 1983 | } else { |
2035 | mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1); | 1984 | mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1); |
2036 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); | 1985 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); |
2037 | mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0); | ||
2038 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2); | ||
2039 | mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0); | ||
2040 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4); | ||
2041 | mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0); | ||
2042 | mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77); | ||
2043 | mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1); | ||
2044 | mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7); | ||
2045 | mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1); | ||
2046 | mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4); | ||
2047 | } | 1986 | } |
2048 | } else { | 1987 | } else { |
2049 | mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2); | 1988 | mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2); |
@@ -2130,14 +2069,12 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi) | |||
2130 | (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); | 2069 | (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); |
2131 | 2070 | ||
2132 | mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5)); | 2071 | mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5)); |
2133 | mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0)); | ||
2134 | } | 2072 | } |
2135 | 2073 | ||
2136 | static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | 2074 | static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) |
2137 | { | 2075 | { |
2138 | struct phytbl_info tab; | 2076 | struct phytbl_info tab; |
2139 | u32 rfseq, ind; | 2077 | u32 rfseq, ind; |
2140 | u8 tssi_sel; | ||
2141 | 2078 | ||
2142 | tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; | 2079 | tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; |
2143 | tab.tbl_width = 32; | 2080 | tab.tbl_width = 32; |
@@ -2159,13 +2096,7 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | |||
2159 | 2096 | ||
2160 | mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4); | 2097 | mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4); |
2161 | 2098 | ||
2162 | if (pi->sh->boardflags & BFL_FEM) { | 2099 | wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); |
2163 | tssi_sel = 0x1; | ||
2164 | wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); | ||
2165 | } else { | ||
2166 | tssi_sel = 0xe; | ||
2167 | wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA); | ||
2168 | } | ||
2169 | mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); | 2100 | mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); |
2170 | 2101 | ||
2171 | mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15); | 2102 | mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15); |
@@ -2201,10 +2132,9 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | |||
2201 | mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0); | 2132 | mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0); |
2202 | 2133 | ||
2203 | if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { | 2134 | if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { |
2204 | mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel); | 2135 | mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe); |
2205 | mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); | 2136 | mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); |
2206 | } else { | 2137 | } else { |
2207 | mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1); | ||
2208 | mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); | 2138 | mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); |
2209 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3); | 2139 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3); |
2210 | } | 2140 | } |
@@ -2251,10 +2181,6 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | |||
2251 | 2181 | ||
2252 | mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8); | 2182 | mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8); |
2253 | 2183 | ||
2254 | mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0); | ||
2255 | mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0); | ||
2256 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); | ||
2257 | |||
2258 | wlc_lcnphy_pwrctrl_rssiparams(pi); | 2184 | wlc_lcnphy_pwrctrl_rssiparams(pi); |
2259 | } | 2185 | } |
2260 | 2186 | ||
@@ -2873,8 +2799,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) | |||
2873 | read_radio_reg(pi, RADIO_2064_REG007) & 1; | 2799 | read_radio_reg(pi, RADIO_2064_REG007) & 1; |
2874 | u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; | 2800 | u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; |
2875 | u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; | 2801 | u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; |
2876 | u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi); | ||
2877 | |||
2878 | idleTssi = read_phy_reg(pi, 0x4ab); | 2802 | idleTssi = read_phy_reg(pi, 0x4ab); |
2879 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & | 2803 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
2880 | MCTL_EN_MAC)); | 2804 | MCTL_EN_MAC)); |
@@ -2892,12 +2816,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) | |||
2892 | mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4); | 2816 | mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4); |
2893 | mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2); | 2817 | mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2); |
2894 | wlc_lcnphy_tssi_setup(pi); | 2818 | wlc_lcnphy_tssi_setup(pi); |
2895 | |||
2896 | mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0)); | ||
2897 | mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6)); | ||
2898 | |||
2899 | wlc_lcnphy_set_bbmult(pi, 0x0); | ||
2900 | |||
2901 | wlc_phy_do_dummy_tx(pi, true, OFF); | 2819 | wlc_phy_do_dummy_tx(pi, true, OFF); |
2902 | idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) | 2820 | idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) |
2903 | >> 0); | 2821 | >> 0); |
@@ -2919,7 +2837,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) | |||
2919 | 2837 | ||
2920 | mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12); | 2838 | mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12); |
2921 | 2839 | ||
2922 | wlc_lcnphy_set_bbmult(pi, SAVE_bbmult); | ||
2923 | wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old); | 2840 | wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old); |
2924 | wlc_lcnphy_set_tx_gain(pi, &old_gains); | 2841 | wlc_lcnphy_set_tx_gain(pi, &old_gains); |
2925 | wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); | 2842 | wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); |
@@ -3133,11 +3050,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) | |||
3133 | wlc_lcnphy_write_table(pi, &tab); | 3050 | wlc_lcnphy_write_table(pi, &tab); |
3134 | tab.tbl_offset++; | 3051 | tab.tbl_offset++; |
3135 | } | 3052 | } |
3136 | mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0); | ||
3137 | mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0); | ||
3138 | mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8); | ||
3139 | mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4); | ||
3140 | mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2); | ||
3141 | 3053 | ||
3142 | mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7); | 3054 | mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7); |
3143 | 3055 | ||
@@ -3939,6 +3851,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) | |||
3939 | target_gains.pad_gain = 21; | 3851 | target_gains.pad_gain = 21; |
3940 | target_gains.dac_gain = 0; | 3852 | target_gains.dac_gain = 0; |
3941 | wlc_lcnphy_set_tx_gain(pi, &target_gains); | 3853 | wlc_lcnphy_set_tx_gain(pi, &target_gains); |
3854 | wlc_lcnphy_set_tx_pwr_by_index(pi, 16); | ||
3942 | 3855 | ||
3943 | if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) { | 3856 | if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) { |
3944 | 3857 | ||
@@ -3949,7 +3862,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) | |||
3949 | lcnphy_recal ? LCNPHY_CAL_RECAL : | 3862 | lcnphy_recal ? LCNPHY_CAL_RECAL : |
3950 | LCNPHY_CAL_FULL), false); | 3863 | LCNPHY_CAL_FULL), false); |
3951 | } else { | 3864 | } else { |
3952 | wlc_lcnphy_set_tx_pwr_by_index(pi, 16); | ||
3953 | wlc_lcnphy_tx_iqlo_soft_cal_full(pi); | 3865 | wlc_lcnphy_tx_iqlo_soft_cal_full(pi); |
3954 | } | 3866 | } |
3955 | 3867 | ||
@@ -4374,22 +4286,17 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi, | |||
4374 | if (CHSPEC_IS5G(pi->radio_chanspec)) | 4286 | if (CHSPEC_IS5G(pi->radio_chanspec)) |
4375 | pa_gain = 0x70; | 4287 | pa_gain = 0x70; |
4376 | else | 4288 | else |
4377 | pa_gain = 0x60; | 4289 | pa_gain = 0x70; |
4378 | 4290 | ||
4379 | if (pi->sh->boardflags & BFL_FEM) | 4291 | if (pi->sh->boardflags & BFL_FEM) |
4380 | pa_gain = 0x10; | 4292 | pa_gain = 0x10; |
4381 | |||
4382 | tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; | 4293 | tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; |
4383 | tab.tbl_width = 32; | 4294 | tab.tbl_width = 32; |
4384 | tab.tbl_len = 1; | 4295 | tab.tbl_len = 1; |
4385 | tab.tbl_ptr = &val; | 4296 | tab.tbl_ptr = &val; |
4386 | 4297 | ||
4387 | for (j = 0; j < 128; j++) { | 4298 | for (j = 0; j < 128; j++) { |
4388 | if (pi->sh->boardflags & BFL_FEM) | 4299 | gm_gain = gain_table[j].gm; |
4389 | gm_gain = gain_table[j].gm; | ||
4390 | else | ||
4391 | gm_gain = 15; | ||
4392 | |||
4393 | val = (((u32) pa_gain << 24) | | 4300 | val = (((u32) pa_gain << 24) | |
4394 | (gain_table[j].pad << 16) | | 4301 | (gain_table[j].pad << 16) | |
4395 | (gain_table[j].pga << 8) | gm_gain); | 4302 | (gain_table[j].pga << 8) | gm_gain); |
@@ -4600,10 +4507,7 @@ static void wlc_radio_2064_init(struct brcms_phy *pi) | |||
4600 | 4507 | ||
4601 | write_phy_reg(pi, 0x4ea, 0x4688); | 4508 | write_phy_reg(pi, 0x4ea, 0x4688); |
4602 | 4509 | ||
4603 | if (pi->sh->boardflags & BFL_FEM) | 4510 | mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); |
4604 | mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); | ||
4605 | else | ||
4606 | mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0); | ||
4607 | 4511 | ||
4608 | mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6); | 4512 | mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6); |
4609 | 4513 | ||
@@ -4614,13 +4518,6 @@ static void wlc_radio_2064_init(struct brcms_phy *pi) | |||
4614 | wlc_lcnphy_rcal(pi); | 4518 | wlc_lcnphy_rcal(pi); |
4615 | 4519 | ||
4616 | wlc_lcnphy_rc_cal(pi); | 4520 | wlc_lcnphy_rc_cal(pi); |
4617 | |||
4618 | if (!(pi->sh->boardflags & BFL_FEM)) { | ||
4619 | write_radio_reg(pi, RADIO_2064_REG032, 0x6f); | ||
4620 | write_radio_reg(pi, RADIO_2064_REG033, 0x19); | ||
4621 | write_radio_reg(pi, RADIO_2064_REG039, 0xe); | ||
4622 | } | ||
4623 | |||
4624 | } | 4521 | } |
4625 | 4522 | ||
4626 | static void wlc_lcnphy_radio_init(struct brcms_phy *pi) | 4523 | static void wlc_lcnphy_radio_init(struct brcms_phy *pi) |
@@ -4650,20 +4547,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) | |||
4650 | wlc_lcnphy_write_table(pi, &tab); | 4547 | wlc_lcnphy_write_table(pi, &tab); |
4651 | } | 4548 | } |
4652 | 4549 | ||
4653 | if (!(pi->sh->boardflags & BFL_FEM)) { | 4550 | tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; |
4654 | tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; | 4551 | tab.tbl_width = 16; |
4655 | tab.tbl_width = 16; | 4552 | tab.tbl_ptr = &val; |
4656 | tab.tbl_ptr = &val; | 4553 | tab.tbl_len = 1; |
4657 | tab.tbl_len = 1; | ||
4658 | 4554 | ||
4659 | val = 150; | 4555 | val = 114; |
4660 | tab.tbl_offset = 0; | 4556 | tab.tbl_offset = 0; |
4661 | wlc_lcnphy_write_table(pi, &tab); | 4557 | wlc_lcnphy_write_table(pi, &tab); |
4662 | 4558 | ||
4663 | val = 220; | 4559 | val = 130; |
4664 | tab.tbl_offset = 1; | 4560 | tab.tbl_offset = 1; |
4665 | wlc_lcnphy_write_table(pi, &tab); | 4561 | wlc_lcnphy_write_table(pi, &tab); |
4666 | } | 4562 | |
4563 | val = 6; | ||
4564 | tab.tbl_offset = 8; | ||
4565 | wlc_lcnphy_write_table(pi, &tab); | ||
4667 | 4566 | ||
4668 | if (CHSPEC_IS2G(pi->radio_chanspec)) { | 4567 | if (CHSPEC_IS2G(pi->radio_chanspec)) { |
4669 | if (pi->sh->boardflags & BFL_FEM) | 4568 | if (pi->sh->boardflags & BFL_FEM) |
@@ -4864,9 +4763,10 @@ void wlc_phy_init_lcnphy(struct brcms_phy *pi) | |||
4864 | 4763 | ||
4865 | wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); | 4764 | wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); |
4866 | 4765 | ||
4867 | si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9); | 4766 | bcma_chipco_regctl_maskset(&pi->d11core->bus->drv_cc, 0, ~0xf, 0x9); |
4868 | 4767 | ||
4869 | si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD); | 4768 | bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 0, 0x0, |
4769 | 0x03CDDDDD); | ||
4870 | 4770 | ||
4871 | if ((pi->sh->boardflags & BFL_FEM) | 4771 | if ((pi->sh->boardflags & BFL_FEM) |
4872 | && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) | 4772 | && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) |
@@ -5055,7 +4955,6 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) | |||
5055 | wlc_lcnphy_load_tx_iir_filter(pi, true, 3); | 4955 | wlc_lcnphy_load_tx_iir_filter(pi, true, 3); |
5056 | 4956 | ||
5057 | mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); | 4957 | mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); |
5058 | wlc_lcnphy_tssi_setup(pi); | ||
5059 | } | 4958 | } |
5060 | 4959 | ||
5061 | void wlc_phy_detach_lcnphy(struct brcms_phy *pi) | 4960 | void wlc_phy_detach_lcnphy(struct brcms_phy *pi) |
@@ -5078,7 +4977,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) | |||
5078 | pi->hwpwrctrl_capable = true; | 4977 | pi->hwpwrctrl_capable = true; |
5079 | } | 4978 | } |
5080 | 4979 | ||
5081 | pi->xtalfreq = si_pmu_alp_clock(pi->sh->sih); | 4980 | pi->xtalfreq = bcma_chipco_get_alp_clock(&pi->d11core->bus->drv_cc); |
5082 | pi_lcn->lcnphy_papd_rxGnCtrl_init = 0; | 4981 | pi_lcn->lcnphy_papd_rxGnCtrl_init = 0; |
5083 | 4982 | ||
5084 | pi->pi_fptr.init = wlc_phy_init_lcnphy; | 4983 | pi->pi_fptr.init = wlc_phy_init_lcnphy; |
@@ -5094,7 +4993,8 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) | |||
5094 | if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) | 4993 | if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) |
5095 | return false; | 4994 | return false; |
5096 | 4995 | ||
5097 | if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { | 4996 | if ((pi->sh->boardflags & BFL_FEM) && |
4997 | (LCNREV_IS(pi->pubpi.phy_rev, 1))) { | ||
5098 | if (pi_lcn->lcnphy_tempsense_option == 3) { | 4998 | if (pi_lcn->lcnphy_tempsense_option == 3) { |
5099 | pi->hwpwrctrl = true; | 4999 | pi->hwpwrctrl = true; |
5100 | pi->hwpwrctrl_capable = true; | 5000 | pi->hwpwrctrl_capable = true; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index 65db9b7458dc..3e9f5b25be63 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c | |||
@@ -19321,14 +19321,13 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) | |||
19321 | (pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) { | 19321 | (pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) { |
19322 | if ((pi->sh->boardflags & BFL_EXTLNA) && | 19322 | if ((pi->sh->boardflags & BFL_EXTLNA) && |
19323 | (CHSPEC_IS2G(pi->radio_chanspec))) | 19323 | (CHSPEC_IS2G(pi->radio_chanspec))) |
19324 | ai_cc_reg(pi->sh->sih, | 19324 | bcma_cc_set32(&pi->d11core->bus->drv_cc, |
19325 | offsetof(struct chipcregs, chipcontrol), | 19325 | BCMA_CC_CHIPCTL, 0x40); |
19326 | 0x40, 0x40); | ||
19327 | } | 19326 | } |
19328 | 19327 | ||
19329 | if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357)) | 19328 | if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357)) |
19330 | si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA, | 19329 | bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 1, |
19331 | CCTRL5357_EXTPA); | 19330 | ~CCTRL5357_EXTPA, CCTRL5357_EXTPA); |
19332 | 19331 | ||
19333 | if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && | 19332 | if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && |
19334 | CHSPEC_IS40(pi->radio_chanspec)) { | 19333 | CHSPEC_IS40(pi->radio_chanspec)) { |
@@ -21133,7 +21132,6 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, | |||
21133 | const struct nphy_sfo_cfg *ci) | 21132 | const struct nphy_sfo_cfg *ci) |
21134 | { | 21133 | { |
21135 | u16 val; | 21134 | u16 val; |
21136 | struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); | ||
21137 | 21135 | ||
21138 | val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; | 21136 | val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; |
21139 | if (CHSPEC_IS5G(chanspec) && !val) { | 21137 | if (CHSPEC_IS5G(chanspec) && !val) { |
@@ -21221,11 +21219,11 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, | |||
21221 | 21219 | ||
21222 | if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || | 21220 | if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || |
21223 | (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) { | 21221 | (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) { |
21224 | bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc, | 21222 | bcma_pmu_spuravoid_pllupdate(&pi->d11core->bus->drv_cc, |
21225 | spuravoid); | 21223 | spuravoid); |
21226 | } else { | 21224 | } else { |
21227 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); | 21225 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); |
21228 | bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc, | 21226 | bcma_pmu_spuravoid_pllupdate(&pi->d11core->bus->drv_cc, |
21229 | spuravoid); | 21227 | spuravoid); |
21230 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); | 21228 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); |
21231 | } | 21229 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c index b7e95acc2084..622c01ca72c5 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c | |||
@@ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = { | |||
1992 | }; | 1992 | }; |
1993 | 1993 | ||
1994 | static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = { | 1994 | static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = { |
1995 | 0x0009, | ||
1996 | 0x000a, | 1995 | 0x000a, |
1997 | 0x0005, | ||
1998 | 0x0006, | ||
1999 | 0x0009, | 1996 | 0x0009, |
2000 | 0x000a, | ||
2001 | 0x0005, | ||
2002 | 0x0006, | 1997 | 0x0006, |
2003 | 0x0009, | ||
2004 | 0x000a, | ||
2005 | 0x0005, | 1998 | 0x0005, |
2006 | 0x0006, | ||
2007 | 0x0009, | ||
2008 | 0x000a, | 1999 | 0x000a, |
2009 | 0x0005, | ||
2010 | 0x0006, | ||
2011 | 0x0009, | 2000 | 0x0009, |
2012 | 0x000a, | ||
2013 | 0x0005, | ||
2014 | 0x0006, | 2001 | 0x0006, |
2015 | 0x0009, | ||
2016 | 0x000a, | ||
2017 | 0x0005, | 2002 | 0x0005, |
2018 | 0x0006, | ||
2019 | 0x0009, | ||
2020 | 0x000a, | 2003 | 0x000a, |
2021 | 0x0005, | ||
2022 | 0x0006, | ||
2023 | 0x0009, | 2004 | 0x0009, |
2024 | 0x000a, | ||
2025 | 0x0005, | ||
2026 | 0x0006, | 2005 | 0x0006, |
2027 | 0x0009, | ||
2028 | 0x000a, | ||
2029 | 0x0005, | 2006 | 0x0005, |
2030 | 0x0006, | ||
2031 | 0x0009, | ||
2032 | 0x000a, | 2007 | 0x000a, |
2033 | 0x0005, | ||
2034 | 0x0006, | ||
2035 | 0x0009, | 2008 | 0x0009, |
2036 | 0x000a, | ||
2037 | 0x0005, | ||
2038 | 0x0006, | 2009 | 0x0006, |
2039 | 0x0009, | ||
2040 | 0x000a, | ||
2041 | 0x0005, | 2010 | 0x0005, |
2042 | 0x0006, | 2011 | 0x000a, |
2043 | 0x0009, | 2012 | 0x0009, |
2013 | 0x0006, | ||
2014 | 0x0005, | ||
2044 | 0x000a, | 2015 | 0x000a, |
2016 | 0x0009, | ||
2017 | 0x0006, | ||
2045 | 0x0005, | 2018 | 0x0005, |
2019 | 0x000a, | ||
2020 | 0x0009, | ||
2046 | 0x0006, | 2021 | 0x0006, |
2022 | 0x0005, | ||
2023 | 0x000a, | ||
2047 | 0x0009, | 2024 | 0x0009, |
2025 | 0x0006, | ||
2026 | 0x0005, | ||
2048 | 0x000a, | 2027 | 0x000a, |
2028 | 0x0009, | ||
2029 | 0x0006, | ||
2049 | 0x0005, | 2030 | 0x0005, |
2031 | 0x000a, | ||
2032 | 0x0009, | ||
2050 | 0x0006, | 2033 | 0x0006, |
2034 | 0x0005, | ||
2035 | 0x000a, | ||
2051 | 0x0009, | 2036 | 0x0009, |
2037 | 0x0006, | ||
2038 | 0x0005, | ||
2052 | 0x000a, | 2039 | 0x000a, |
2040 | 0x0009, | ||
2041 | 0x0006, | ||
2053 | 0x0005, | 2042 | 0x0005, |
2043 | 0x000a, | ||
2044 | 0x0009, | ||
2054 | 0x0006, | 2045 | 0x0006, |
2046 | 0x0005, | ||
2047 | 0x000a, | ||
2055 | 0x0009, | 2048 | 0x0009, |
2049 | 0x0006, | ||
2050 | 0x0005, | ||
2056 | 0x000a, | 2051 | 0x000a, |
2052 | 0x0009, | ||
2053 | 0x0006, | ||
2057 | 0x0005, | 2054 | 0x0005, |
2055 | 0x000a, | ||
2056 | 0x0009, | ||
2058 | 0x0006, | 2057 | 0x0006, |
2058 | 0x0005, | ||
2059 | }; | 2059 | }; |
2060 | 2060 | ||
2061 | static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = { | 2061 | static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = { |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c index 7e9df566c733..71b80381f3ad 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c | |||
@@ -115,60 +115,6 @@ u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) | |||
115 | return (u16) delay; | 115 | return (u16) delay; |
116 | } | 116 | } |
117 | 117 | ||
118 | /* Read/write a chipcontrol reg */ | ||
119 | u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) | ||
120 | { | ||
121 | ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_addr), ~0, reg); | ||
122 | return ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_data), | ||
123 | mask, val); | ||
124 | } | ||
125 | |||
126 | /* Read/write a regcontrol reg */ | ||
127 | u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) | ||
128 | { | ||
129 | ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_addr), ~0, reg); | ||
130 | return ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_data), | ||
131 | mask, val); | ||
132 | } | ||
133 | |||
134 | /* Read/write a pllcontrol reg */ | ||
135 | u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) | ||
136 | { | ||
137 | ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_addr), ~0, reg); | ||
138 | return ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_data), | ||
139 | mask, val); | ||
140 | } | ||
141 | |||
142 | /* PMU PLL update */ | ||
143 | void si_pmu_pllupd(struct si_pub *sih) | ||
144 | { | ||
145 | ai_cc_reg(sih, offsetof(struct chipcregs, pmucontrol), | ||
146 | PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD); | ||
147 | } | ||
148 | |||
149 | /* query alp/xtal clock frequency */ | ||
150 | u32 si_pmu_alp_clock(struct si_pub *sih) | ||
151 | { | ||
152 | u32 clock = ALP_CLOCK; | ||
153 | |||
154 | /* bail out with default */ | ||
155 | if (!(ai_get_cccaps(sih) & CC_CAP_PMU)) | ||
156 | return clock; | ||
157 | |||
158 | switch (ai_get_chip_id(sih)) { | ||
159 | case BCMA_CHIP_ID_BCM43224: | ||
160 | case BCMA_CHIP_ID_BCM43225: | ||
161 | case BCMA_CHIP_ID_BCM4313: | ||
162 | /* always 20Mhz */ | ||
163 | clock = 20000 * 1000; | ||
164 | break; | ||
165 | default: | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | return clock; | ||
170 | } | ||
171 | |||
172 | u32 si_pmu_measure_alpclk(struct si_pub *sih) | 118 | u32 si_pmu_measure_alpclk(struct si_pub *sih) |
173 | { | 119 | { |
174 | struct si_info *sii = container_of(sih, struct si_info, pub); | 120 | struct si_info *sii = container_of(sih, struct si_info, pub); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h index f7cff873578b..20e2012d5a3a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h | |||
@@ -21,12 +21,6 @@ | |||
21 | #include "types.h" | 21 | #include "types.h" |
22 | 22 | ||
23 | extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih); | 23 | extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih); |
24 | extern void si_pmu_sprom_enable(struct si_pub *sih, bool enable); | ||
25 | extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); | ||
26 | extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); | ||
27 | extern u32 si_pmu_alp_clock(struct si_pub *sih); | ||
28 | extern void si_pmu_pllupd(struct si_pub *sih); | ||
29 | extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); | ||
30 | extern u32 si_pmu_measure_alpclk(struct si_pub *sih); | 24 | extern u32 si_pmu_measure_alpclk(struct si_pub *sih); |
31 | 25 | ||
32 | #endif /* _BRCM_PMU_H_ */ | 26 | #endif /* _BRCM_PMU_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index b0f14b7b8616..d36ea5e1cc49 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h | |||
@@ -164,8 +164,6 @@ struct brcms_pub { | |||
164 | 164 | ||
165 | u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */ | 165 | u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */ |
166 | 166 | ||
167 | int bcmerror; /* last bcm error */ | ||
168 | |||
169 | u32 radio_disabled; /* bit vector for radio disabled reasons */ | 167 | u32 radio_disabled; /* bit vector for radio disabled reasons */ |
170 | 168 | ||
171 | u16 boardrev; /* version # of particular board */ | 169 | u16 boardrev; /* version # of particular board */ |
@@ -326,10 +324,25 @@ extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, | |||
326 | s8 sslot_override); | 324 | s8 sslot_override); |
327 | extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, | 325 | extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, |
328 | u8 interval); | 326 | u8 interval); |
327 | extern u64 brcms_c_tsf_get(struct brcms_c_info *wlc); | ||
328 | extern void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf); | ||
329 | extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); | 329 | extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); |
330 | extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); | 330 | extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); |
331 | extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); | 331 | extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); |
332 | extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); | 332 | extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); |
333 | extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); | 333 | extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); |
334 | extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr); | ||
335 | extern void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, | ||
336 | const u8 *bssid, u8 *ssid, size_t ssid_len); | ||
337 | extern void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr); | ||
338 | extern void brcms_c_update_beacon(struct brcms_c_info *wlc); | ||
339 | extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc, | ||
340 | struct sk_buff *beacon, u16 tim_offset, | ||
341 | u16 dtim_period); | ||
342 | extern void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc, | ||
343 | struct sk_buff *probe_resp); | ||
344 | extern void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable); | ||
345 | extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, | ||
346 | size_t ssid_len); | ||
334 | 347 | ||
335 | #endif /* _BRCM_PUB_H_ */ | 348 | #endif /* _BRCM_PUB_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmutil/Makefile b/drivers/net/wireless/brcm80211/brcmutil/Makefile index 6281c416289e..8a928184016a 100644 --- a/drivers/net/wireless/brcm80211/brcmutil/Makefile +++ b/drivers/net/wireless/brcm80211/brcmutil/Makefile | |||
@@ -19,10 +19,5 @@ ccflags-y := \ | |||
19 | -Idrivers/net/wireless/brcm80211/brcmutil \ | 19 | -Idrivers/net/wireless/brcm80211/brcmutil \ |
20 | -Idrivers/net/wireless/brcm80211/include | 20 | -Idrivers/net/wireless/brcm80211/include |
21 | 21 | ||
22 | BRCMUTIL_OFILES := \ | 22 | obj-$(CONFIG_BRCMUTIL) += brcmutil.o |
23 | utils.o | 23 | brcmutil-objs = utils.o d11.o |
24 | |||
25 | MODULEPFX := brcmutil | ||
26 | |||
27 | obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o | ||
28 | $(MODULEPFX)-objs = $(BRCMUTIL_OFILES) | ||
diff --git a/drivers/net/wireless/brcm80211/brcmutil/d11.c b/drivers/net/wireless/brcm80211/brcmutil/d11.c new file mode 100644 index 000000000000..30e54e2c6c9b --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmutil/d11.c | |||
@@ -0,0 +1,162 @@ | |||
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 | /*********************channel spec common functions*********************/ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | |||
20 | #include <brcmu_utils.h> | ||
21 | #include <brcmu_wifi.h> | ||
22 | #include <brcmu_d11.h> | ||
23 | |||
24 | static void brcmu_d11n_encchspec(struct brcmu_chan *ch) | ||
25 | { | ||
26 | ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK; | ||
27 | |||
28 | switch (ch->bw) { | ||
29 | case BRCMU_CHAN_BW_20: | ||
30 | ch->chspec |= BRCMU_CHSPEC_D11N_BW_20 | BRCMU_CHSPEC_D11N_SB_N; | ||
31 | break; | ||
32 | case BRCMU_CHAN_BW_40: | ||
33 | default: | ||
34 | WARN_ON_ONCE(1); | ||
35 | break; | ||
36 | } | ||
37 | |||
38 | if (ch->chnum <= CH_MAX_2G_CHANNEL) | ||
39 | ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G; | ||
40 | else | ||
41 | ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G; | ||
42 | } | ||
43 | |||
44 | static void brcmu_d11ac_encchspec(struct brcmu_chan *ch) | ||
45 | { | ||
46 | ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK; | ||
47 | |||
48 | switch (ch->bw) { | ||
49 | case BRCMU_CHAN_BW_20: | ||
50 | ch->chspec |= BRCMU_CHSPEC_D11AC_BW_20; | ||
51 | break; | ||
52 | case BRCMU_CHAN_BW_40: | ||
53 | case BRCMU_CHAN_BW_80: | ||
54 | case BRCMU_CHAN_BW_80P80: | ||
55 | case BRCMU_CHAN_BW_160: | ||
56 | default: | ||
57 | WARN_ON_ONCE(1); | ||
58 | break; | ||
59 | } | ||
60 | |||
61 | if (ch->chnum <= CH_MAX_2G_CHANNEL) | ||
62 | ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G; | ||
63 | else | ||
64 | ch->chspec |= BRCMU_CHSPEC_D11AC_BND_5G; | ||
65 | } | ||
66 | |||
67 | static void brcmu_d11n_decchspec(struct brcmu_chan *ch) | ||
68 | { | ||
69 | u16 val; | ||
70 | |||
71 | ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK); | ||
72 | |||
73 | switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) { | ||
74 | case BRCMU_CHSPEC_D11N_BW_20: | ||
75 | ch->bw = BRCMU_CHAN_BW_20; | ||
76 | break; | ||
77 | case BRCMU_CHSPEC_D11N_BW_40: | ||
78 | ch->bw = BRCMU_CHAN_BW_40; | ||
79 | val = ch->chspec & BRCMU_CHSPEC_D11N_SB_MASK; | ||
80 | if (val == BRCMU_CHSPEC_D11N_SB_L) { | ||
81 | ch->sb = BRCMU_CHAN_SB_L; | ||
82 | ch->chnum -= CH_10MHZ_APART; | ||
83 | } else { | ||
84 | ch->sb = BRCMU_CHAN_SB_U; | ||
85 | ch->chnum += CH_10MHZ_APART; | ||
86 | } | ||
87 | break; | ||
88 | default: | ||
89 | WARN_ON_ONCE(1); | ||
90 | break; | ||
91 | } | ||
92 | |||
93 | switch (ch->chspec & BRCMU_CHSPEC_D11N_BND_MASK) { | ||
94 | case BRCMU_CHSPEC_D11N_BND_5G: | ||
95 | ch->band = BRCMU_CHAN_BAND_5G; | ||
96 | break; | ||
97 | case BRCMU_CHSPEC_D11N_BND_2G: | ||
98 | ch->band = BRCMU_CHAN_BAND_2G; | ||
99 | break; | ||
100 | default: | ||
101 | WARN_ON_ONCE(1); | ||
102 | break; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | static void brcmu_d11ac_decchspec(struct brcmu_chan *ch) | ||
107 | { | ||
108 | u16 val; | ||
109 | |||
110 | ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK); | ||
111 | |||
112 | switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) { | ||
113 | case BRCMU_CHSPEC_D11AC_BW_20: | ||
114 | ch->bw = BRCMU_CHAN_BW_20; | ||
115 | break; | ||
116 | case BRCMU_CHSPEC_D11AC_BW_40: | ||
117 | ch->bw = BRCMU_CHAN_BW_40; | ||
118 | val = ch->chspec & BRCMU_CHSPEC_D11AC_SB_MASK; | ||
119 | if (val == BRCMU_CHSPEC_D11AC_SB_L) { | ||
120 | ch->sb = BRCMU_CHAN_SB_L; | ||
121 | ch->chnum -= CH_10MHZ_APART; | ||
122 | } else if (val == BRCMU_CHSPEC_D11AC_SB_U) { | ||
123 | ch->sb = BRCMU_CHAN_SB_U; | ||
124 | ch->chnum += CH_10MHZ_APART; | ||
125 | } else { | ||
126 | WARN_ON_ONCE(1); | ||
127 | } | ||
128 | break; | ||
129 | case BRCMU_CHSPEC_D11AC_BW_80: | ||
130 | ch->bw = BRCMU_CHAN_BW_80; | ||
131 | break; | ||
132 | case BRCMU_CHSPEC_D11AC_BW_8080: | ||
133 | case BRCMU_CHSPEC_D11AC_BW_160: | ||
134 | default: | ||
135 | WARN_ON_ONCE(1); | ||
136 | break; | ||
137 | } | ||
138 | |||
139 | switch (ch->chspec & BRCMU_CHSPEC_D11AC_BND_MASK) { | ||
140 | case BRCMU_CHSPEC_D11AC_BND_5G: | ||
141 | ch->band = BRCMU_CHAN_BAND_5G; | ||
142 | break; | ||
143 | case BRCMU_CHSPEC_D11AC_BND_2G: | ||
144 | ch->band = BRCMU_CHAN_BAND_2G; | ||
145 | break; | ||
146 | default: | ||
147 | WARN_ON_ONCE(1); | ||
148 | break; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | void brcmu_d11_attach(struct brcmu_d11inf *d11inf) | ||
153 | { | ||
154 | if (d11inf->io_type == BRCMU_D11N_IOTYPE) { | ||
155 | d11inf->encchspec = brcmu_d11n_encchspec; | ||
156 | d11inf->decchspec = brcmu_d11n_decchspec; | ||
157 | } else { | ||
158 | d11inf->encchspec = brcmu_d11ac_encchspec; | ||
159 | d11inf->decchspec = brcmu_d11ac_decchspec; | ||
160 | } | ||
161 | } | ||
162 | EXPORT_SYMBOL(brcmu_d11_attach); | ||
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/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index e8682855b73a..c1fe245bb07e 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | /* Chipcommon Core Chip IDs */ | 30 | /* Chipcommon Core Chip IDs */ |
31 | #define BCM4313_CHIP_ID 0x4313 | 31 | #define BCM4313_CHIP_ID 0x4313 |
32 | #define BCM43143_CHIP_ID 43143 | ||
32 | #define BCM43224_CHIP_ID 43224 | 33 | #define BCM43224_CHIP_ID 43224 |
33 | #define BCM43225_CHIP_ID 43225 | 34 | #define BCM43225_CHIP_ID 43225 |
34 | #define BCM43235_CHIP_ID 43235 | 35 | #define BCM43235_CHIP_ID 43235 |
@@ -39,5 +40,6 @@ | |||
39 | #define BCM4330_CHIP_ID 0x4330 | 40 | #define BCM4330_CHIP_ID 0x4330 |
40 | #define BCM4331_CHIP_ID 0x4331 | 41 | #define BCM4331_CHIP_ID 0x4331 |
41 | #define BCM4334_CHIP_ID 0x4334 | 42 | #define BCM4334_CHIP_ID 0x4334 |
43 | #define BCM4335_CHIP_ID 0x4335 | ||
42 | 44 | ||
43 | #endif /* _BRCM_HW_IDS_H_ */ | 45 | #endif /* _BRCM_HW_IDS_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_d11.h b/drivers/net/wireless/brcm80211/include/brcmu_d11.h new file mode 100644 index 000000000000..92623f02b1c0 --- /dev/null +++ b/drivers/net/wireless/brcm80211/include/brcmu_d11.h | |||
@@ -0,0 +1,145 @@ | |||
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 | |||
17 | #ifndef _BRCMU_D11_H_ | ||
18 | #define _BRCMU_D11_H_ | ||
19 | |||
20 | /* d11 io type */ | ||
21 | #define BRCMU_D11N_IOTYPE 1 | ||
22 | #define BRCMU_D11AC_IOTYPE 2 | ||
23 | |||
24 | /* A chanspec (channel specification) holds the channel number, band, | ||
25 | * bandwidth and control sideband | ||
26 | */ | ||
27 | |||
28 | /* chanspec binary format */ | ||
29 | |||
30 | #define BRCMU_CHSPEC_INVALID 255 | ||
31 | /* bit 0~7 channel number | ||
32 | * for 80+80 channels: bit 0~3 low channel id, bit 4~7 high channel id | ||
33 | */ | ||
34 | #define BRCMU_CHSPEC_CH_MASK 0x00ff | ||
35 | #define BRCMU_CHSPEC_CH_SHIFT 0 | ||
36 | #define BRCMU_CHSPEC_CHL_MASK 0x000f | ||
37 | #define BRCMU_CHSPEC_CHL_SHIFT 0 | ||
38 | #define BRCMU_CHSPEC_CHH_MASK 0x00f0 | ||
39 | #define BRCMU_CHSPEC_CHH_SHIFT 4 | ||
40 | |||
41 | /* bit 8~16 for dot 11n IO types | ||
42 | * bit 8~9 sideband | ||
43 | * bit 10~11 bandwidth | ||
44 | * bit 12~13 spectral band | ||
45 | * bit 14~15 not used | ||
46 | */ | ||
47 | #define BRCMU_CHSPEC_D11N_SB_MASK 0x0300 | ||
48 | #define BRCMU_CHSPEC_D11N_SB_SHIFT 8 | ||
49 | #define BRCMU_CHSPEC_D11N_SB_L 0x0100 /* control lower */ | ||
50 | #define BRCMU_CHSPEC_D11N_SB_U 0x0200 /* control upper */ | ||
51 | #define BRCMU_CHSPEC_D11N_SB_N 0x0300 /* none */ | ||
52 | #define BRCMU_CHSPEC_D11N_BW_MASK 0x0c00 | ||
53 | #define BRCMU_CHSPEC_D11N_BW_SHIFT 10 | ||
54 | #define BRCMU_CHSPEC_D11N_BW_10 0x0400 | ||
55 | #define BRCMU_CHSPEC_D11N_BW_20 0x0800 | ||
56 | #define BRCMU_CHSPEC_D11N_BW_40 0x0c00 | ||
57 | #define BRCMU_CHSPEC_D11N_BND_MASK 0x3000 | ||
58 | #define BRCMU_CHSPEC_D11N_BND_SHIFT 12 | ||
59 | #define BRCMU_CHSPEC_D11N_BND_5G 0x1000 | ||
60 | #define BRCMU_CHSPEC_D11N_BND_2G 0x2000 | ||
61 | |||
62 | /* bit 8~16 for dot 11ac IO types | ||
63 | * bit 8~10 sideband | ||
64 | * bit 11~13 bandwidth | ||
65 | * bit 14~15 spectral band | ||
66 | */ | ||
67 | #define BRCMU_CHSPEC_D11AC_SB_MASK 0x0700 | ||
68 | #define BRCMU_CHSPEC_D11AC_SB_SHIFT 8 | ||
69 | #define BRCMU_CHSPEC_D11AC_SB_LLL 0x0000 | ||
70 | #define BRCMU_CHSPEC_D11AC_SB_LLU 0x0100 | ||
71 | #define BRCMU_CHSPEC_D11AC_SB_LUL 0x0200 | ||
72 | #define BRCMU_CHSPEC_D11AC_SB_LUU 0x0300 | ||
73 | #define BRCMU_CHSPEC_D11AC_SB_ULL 0x0400 | ||
74 | #define BRCMU_CHSPEC_D11AC_SB_ULU 0x0500 | ||
75 | #define BRCMU_CHSPEC_D11AC_SB_UUL 0x0600 | ||
76 | #define BRCMU_CHSPEC_D11AC_SB_UUU 0x0700 | ||
77 | #define BRCMU_CHSPEC_D11AC_SB_LL BRCMU_CHSPEC_D11AC_SB_LLL | ||
78 | #define BRCMU_CHSPEC_D11AC_SB_LU BRCMU_CHSPEC_D11AC_SB_LLU | ||
79 | #define BRCMU_CHSPEC_D11AC_SB_UL BRCMU_CHSPEC_D11AC_SB_LUL | ||
80 | #define BRCMU_CHSPEC_D11AC_SB_UU BRCMU_CHSPEC_D11AC_SB_LUU | ||
81 | #define BRCMU_CHSPEC_D11AC_SB_L BRCMU_CHSPEC_D11AC_SB_LLL | ||
82 | #define BRCMU_CHSPEC_D11AC_SB_U BRCMU_CHSPEC_D11AC_SB_LLU | ||
83 | #define BRCMU_CHSPEC_D11AC_BW_MASK 0x3800 | ||
84 | #define BRCMU_CHSPEC_D11AC_BW_SHIFT 11 | ||
85 | #define BRCMU_CHSPEC_D11AC_BW_5 0x0000 | ||
86 | #define BRCMU_CHSPEC_D11AC_BW_10 0x0800 | ||
87 | #define BRCMU_CHSPEC_D11AC_BW_20 0x1000 | ||
88 | #define BRCMU_CHSPEC_D11AC_BW_40 0x1800 | ||
89 | #define BRCMU_CHSPEC_D11AC_BW_80 0x2000 | ||
90 | #define BRCMU_CHSPEC_D11AC_BW_160 0x2800 | ||
91 | #define BRCMU_CHSPEC_D11AC_BW_8080 0x3000 | ||
92 | #define BRCMU_CHSPEC_D11AC_BND_MASK 0xc000 | ||
93 | #define BRCMU_CHSPEC_D11AC_BND_SHIFT 14 | ||
94 | #define BRCMU_CHSPEC_D11AC_BND_2G 0x0000 | ||
95 | #define BRCMU_CHSPEC_D11AC_BND_3G 0x4000 | ||
96 | #define BRCMU_CHSPEC_D11AC_BND_4G 0x8000 | ||
97 | #define BRCMU_CHSPEC_D11AC_BND_5G 0xc000 | ||
98 | |||
99 | #define BRCMU_CHAN_BAND_2G 0 | ||
100 | #define BRCMU_CHAN_BAND_5G 1 | ||
101 | |||
102 | enum brcmu_chan_bw { | ||
103 | BRCMU_CHAN_BW_20, | ||
104 | BRCMU_CHAN_BW_40, | ||
105 | BRCMU_CHAN_BW_80, | ||
106 | BRCMU_CHAN_BW_80P80, | ||
107 | BRCMU_CHAN_BW_160, | ||
108 | }; | ||
109 | |||
110 | enum brcmu_chan_sb { | ||
111 | BRCMU_CHAN_SB_NONE = 0, | ||
112 | BRCMU_CHAN_SB_L, | ||
113 | BRCMU_CHAN_SB_U, | ||
114 | BRCMU_CHAN_SB_LL, | ||
115 | BRCMU_CHAN_SB_LU, | ||
116 | BRCMU_CHAN_SB_UL, | ||
117 | BRCMU_CHAN_SB_UU, | ||
118 | BRCMU_CHAN_SB_LLL, | ||
119 | BRCMU_CHAN_SB_LLU, | ||
120 | BRCMU_CHAN_SB_LUL, | ||
121 | BRCMU_CHAN_SB_LUU, | ||
122 | BRCMU_CHAN_SB_ULL, | ||
123 | BRCMU_CHAN_SB_ULU, | ||
124 | BRCMU_CHAN_SB_UUL, | ||
125 | BRCMU_CHAN_SB_UUU, | ||
126 | }; | ||
127 | |||
128 | struct brcmu_chan { | ||
129 | u16 chspec; | ||
130 | u8 chnum; | ||
131 | u8 band; | ||
132 | enum brcmu_chan_bw bw; | ||
133 | enum brcmu_chan_sb sb; | ||
134 | }; | ||
135 | |||
136 | struct brcmu_d11inf { | ||
137 | u8 io_type; | ||
138 | |||
139 | void (*encchspec)(struct brcmu_chan *ch); | ||
140 | void (*decchspec)(struct brcmu_chan *ch); | ||
141 | }; | ||
142 | |||
143 | extern void brcmu_d11_attach(struct brcmu_d11inf *d11inf); | ||
144 | |||
145 | #endif /* _BRCMU_CHANNELS_H_ */ | ||
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/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h index c11a290a1edf..0505cc065e0d 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h | |||
@@ -32,8 +32,9 @@ | |||
32 | #define CH_20MHZ_APART 4 | 32 | #define CH_20MHZ_APART 4 |
33 | #define CH_10MHZ_APART 2 | 33 | #define CH_10MHZ_APART 2 |
34 | #define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ | 34 | #define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ |
35 | #define CH_MIN_2G_CHANNEL 1 | ||
35 | #define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ | 36 | #define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ |
36 | #define BRCM_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL /* legacy define */ | 37 | #define CH_MIN_5G_CHANNEL 34 |
37 | 38 | ||
38 | /* bandstate array indices */ | 39 | /* bandstate array indices */ |
39 | #define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */ | 40 | #define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */ |
@@ -60,6 +61,7 @@ | |||
60 | #define WL_CHANSPEC_BW_10 0x0400 | 61 | #define WL_CHANSPEC_BW_10 0x0400 |
61 | #define WL_CHANSPEC_BW_20 0x0800 | 62 | #define WL_CHANSPEC_BW_20 0x0800 |
62 | #define WL_CHANSPEC_BW_40 0x0C00 | 63 | #define WL_CHANSPEC_BW_40 0x0C00 |
64 | #define WL_CHANSPEC_BW_80 0x2000 | ||
63 | 65 | ||
64 | #define WL_CHANSPEC_BAND_MASK 0xf000 | 66 | #define WL_CHANSPEC_BAND_MASK 0xf000 |
65 | #define WL_CHANSPEC_BAND_SHIFT 12 | 67 | #define WL_CHANSPEC_BAND_SHIFT 12 |
@@ -67,6 +69,25 @@ | |||
67 | #define WL_CHANSPEC_BAND_2G 0x2000 | 69 | #define WL_CHANSPEC_BAND_2G 0x2000 |
68 | #define INVCHANSPEC 255 | 70 | #define INVCHANSPEC 255 |
69 | 71 | ||
72 | #define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */ | ||
73 | #define WL_CHAN_VALID_SW (1 << 1) /* valid with country sett. */ | ||
74 | #define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */ | ||
75 | #define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */ | ||
76 | #define WL_CHAN_INACTIVE (1 << 4) /* inactive due to radar */ | ||
77 | #define WL_CHAN_PASSIVE (1 << 5) /* channel in passive mode */ | ||
78 | #define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */ | ||
79 | |||
80 | /* values for band specific 40MHz capabilities */ | ||
81 | #define WLC_N_BW_20ALL 0 | ||
82 | #define WLC_N_BW_40ALL 1 | ||
83 | #define WLC_N_BW_20IN2G_40IN5G 2 | ||
84 | |||
85 | /* band types */ | ||
86 | #define WLC_BAND_AUTO 0 /* auto-select */ | ||
87 | #define WLC_BAND_5G 1 /* 5 Ghz */ | ||
88 | #define WLC_BAND_2G 2 /* 2.4 Ghz */ | ||
89 | #define WLC_BAND_ALL 3 /* all bands */ | ||
90 | |||
70 | #define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK)) | 91 | #define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK)) |
71 | #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) | 92 | #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) |
72 | 93 | ||
@@ -79,10 +100,11 @@ | |||
79 | #define CHSPEC_IS20(chspec) \ | 100 | #define CHSPEC_IS20(chspec) \ |
80 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) | 101 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) |
81 | 102 | ||
82 | #ifndef CHSPEC_IS40 | ||
83 | #define CHSPEC_IS40(chspec) \ | 103 | #define CHSPEC_IS40(chspec) \ |
84 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) | 104 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) |
85 | #endif | 105 | |
106 | #define CHSPEC_IS80(chspec) \ | ||
107 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) | ||
86 | 108 | ||
87 | #define CHSPEC_IS5G(chspec) \ | 109 | #define CHSPEC_IS5G(chspec) \ |
88 | (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) | 110 | (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) |
diff --git a/drivers/net/wireless/brcm80211/include/chipcommon.h b/drivers/net/wireless/brcm80211/include/chipcommon.h index f96834a7c055..d242333b7559 100644 --- a/drivers/net/wireless/brcm80211/include/chipcommon.h +++ b/drivers/net/wireless/brcm80211/include/chipcommon.h | |||
@@ -205,7 +205,7 @@ struct chipcregs { | |||
205 | u32 res_req_timer_sel; | 205 | u32 res_req_timer_sel; |
206 | u32 res_req_timer; | 206 | u32 res_req_timer; |
207 | u32 res_req_mask; | 207 | u32 res_req_mask; |
208 | u32 PAD; | 208 | u32 pmucapabilities_ext; /* 0x64c, pmurev >=15 */ |
209 | u32 chipcontrol_addr; /* 0x650 */ | 209 | u32 chipcontrol_addr; /* 0x650 */ |
210 | u32 chipcontrol_data; /* 0x654 */ | 210 | u32 chipcontrol_data; /* 0x654 */ |
211 | u32 regcontrol_addr; | 211 | u32 regcontrol_addr; |
@@ -214,7 +214,11 @@ struct chipcregs { | |||
214 | u32 pllcontrol_data; | 214 | u32 pllcontrol_data; |
215 | u32 pmustrapopt; /* 0x668, corerev >= 28 */ | 215 | u32 pmustrapopt; /* 0x668, corerev >= 28 */ |
216 | u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ | 216 | u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ |
217 | u32 PAD[100]; | 217 | u32 retention_ctl; /* 0x670, pmurev >= 15 */ |
218 | u32 PAD[3]; | ||
219 | u32 retention_grpidx; /* 0x680 */ | ||
220 | u32 retention_grpctl; /* 0x684 */ | ||
221 | u32 PAD[94]; | ||
218 | u16 sromotp[768]; | 222 | u16 sromotp[768]; |
219 | }; | 223 | }; |
220 | 224 | ||
@@ -276,6 +280,12 @@ struct chipcregs { | |||
276 | #define PCAP5_VC_SHIFT 22 | 280 | #define PCAP5_VC_SHIFT 22 |
277 | #define PCAP5_CC_MASK 0xf8000000 | 281 | #define PCAP5_CC_MASK 0xf8000000 |
278 | #define PCAP5_CC_SHIFT 27 | 282 | #define PCAP5_CC_SHIFT 27 |
283 | /* pmucapabilites_ext PMU rev >= 15 */ | ||
284 | #define PCAPEXT_SR_SUPPORTED_MASK (1 << 1) | ||
285 | /* retention_ctl PMU rev >= 15 */ | ||
286 | #define PMU_RCTL_MACPHY_DISABLE_MASK (1 << 26) | ||
287 | #define PMU_RCTL_LOGIC_DISABLE_MASK (1 << 27) | ||
288 | |||
279 | 289 | ||
280 | /* | 290 | /* |
281 | * Maximum delay for the PMU state transition in us. | 291 | * Maximum delay for the PMU state transition in us. |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index cb066f62879d..15920aaa5dd6 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -4167,17 +4167,11 @@ static ssize_t show_debug_level(struct device_driver *d, char *buf) | |||
4167 | static ssize_t store_debug_level(struct device_driver *d, | 4167 | static ssize_t store_debug_level(struct device_driver *d, |
4168 | const char *buf, size_t count) | 4168 | const char *buf, size_t count) |
4169 | { | 4169 | { |
4170 | char *p = (char *)buf; | ||
4171 | u32 val; | 4170 | u32 val; |
4171 | int ret; | ||
4172 | 4172 | ||
4173 | if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { | 4173 | ret = kstrtou32(buf, 0, &val); |
4174 | p++; | 4174 | if (ret) |
4175 | if (p[0] == 'x' || p[0] == 'X') | ||
4176 | p++; | ||
4177 | val = simple_strtoul(p, &p, 16); | ||
4178 | } else | ||
4179 | val = simple_strtoul(p, &p, 10); | ||
4180 | if (p == buf) | ||
4181 | IPW_DEBUG_INFO(": %s is not in hex or decimal form.\n", buf); | 4175 | IPW_DEBUG_INFO(": %s is not in hex or decimal form.\n", buf); |
4182 | else | 4176 | else |
4183 | ipw2100_debug_level = val; | 4177 | ipw2100_debug_level = val; |
@@ -4238,27 +4232,15 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, | |||
4238 | { | 4232 | { |
4239 | struct ipw2100_priv *priv = dev_get_drvdata(d); | 4233 | struct ipw2100_priv *priv = dev_get_drvdata(d); |
4240 | struct net_device *dev = priv->net_dev; | 4234 | struct net_device *dev = priv->net_dev; |
4241 | char buffer[] = "00000000"; | ||
4242 | unsigned long len = | ||
4243 | (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; | ||
4244 | unsigned long val; | 4235 | unsigned long val; |
4245 | char *p = buffer; | 4236 | int ret; |
4246 | 4237 | ||
4247 | (void)dev; /* kill unused-var warning for debug-only code */ | 4238 | (void)dev; /* kill unused-var warning for debug-only code */ |
4248 | 4239 | ||
4249 | IPW_DEBUG_INFO("enter\n"); | 4240 | IPW_DEBUG_INFO("enter\n"); |
4250 | 4241 | ||
4251 | strncpy(buffer, buf, len); | 4242 | ret = kstrtoul(buf, 0, &val); |
4252 | buffer[len] = 0; | 4243 | if (ret) { |
4253 | |||
4254 | if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { | ||
4255 | p++; | ||
4256 | if (p[0] == 'x' || p[0] == 'X') | ||
4257 | p++; | ||
4258 | val = simple_strtoul(p, &p, 16); | ||
4259 | } else | ||
4260 | val = simple_strtoul(p, &p, 10); | ||
4261 | if (p == buffer) { | ||
4262 | IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name); | 4244 | IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name); |
4263 | } else { | 4245 | } else { |
4264 | priv->ieee->scan_age = val; | 4246 | priv->ieee->scan_age = val; |
@@ -4266,7 +4248,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, | |||
4266 | } | 4248 | } |
4267 | 4249 | ||
4268 | IPW_DEBUG_INFO("exit\n"); | 4250 | IPW_DEBUG_INFO("exit\n"); |
4269 | return len; | 4251 | return strnlen(buf, count); |
4270 | } | 4252 | } |
4271 | 4253 | ||
4272 | static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age); | 4254 | static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age); |
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 3630a41df50d..b37a582ccbe7 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
@@ -475,6 +475,7 @@ il3945_tx_skb(struct il_priv *il, | |||
475 | dma_addr_t txcmd_phys; | 475 | dma_addr_t txcmd_phys; |
476 | int txq_id = skb_get_queue_mapping(skb); | 476 | int txq_id = skb_get_queue_mapping(skb); |
477 | u16 len, idx, hdr_len; | 477 | u16 len, idx, hdr_len; |
478 | u16 firstlen, secondlen; | ||
478 | u8 id; | 479 | u8 id; |
479 | u8 unicast; | 480 | u8 unicast; |
480 | u8 sta_id; | 481 | u8 sta_id; |
@@ -589,21 +590,22 @@ il3945_tx_skb(struct il_priv *il, | |||
589 | len = | 590 | len = |
590 | sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) + | 591 | sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) + |
591 | hdr_len; | 592 | hdr_len; |
592 | len = (len + 3) & ~3; | 593 | firstlen = (len + 3) & ~3; |
593 | 594 | ||
594 | /* Physical address of this Tx command's header (not MAC header!), | 595 | /* Physical address of this Tx command's header (not MAC header!), |
595 | * within command buffer array. */ | 596 | * within command buffer array. */ |
596 | txcmd_phys = | 597 | txcmd_phys = |
597 | pci_map_single(il->pci_dev, &out_cmd->hdr, len, PCI_DMA_TODEVICE); | 598 | pci_map_single(il->pci_dev, &out_cmd->hdr, firstlen, |
599 | PCI_DMA_TODEVICE); | ||
598 | if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys))) | 600 | if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys))) |
599 | goto drop_unlock; | 601 | goto drop_unlock; |
600 | 602 | ||
601 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | 603 | /* Set up TFD's 2nd entry to point directly to remainder of skb, |
602 | * if any (802.11 null frames have no payload). */ | 604 | * if any (802.11 null frames have no payload). */ |
603 | len = skb->len - hdr_len; | 605 | secondlen = skb->len - hdr_len; |
604 | if (len) { | 606 | if (secondlen > 0) { |
605 | phys_addr = | 607 | phys_addr = |
606 | pci_map_single(il->pci_dev, skb->data + hdr_len, len, | 608 | pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen, |
607 | PCI_DMA_TODEVICE); | 609 | PCI_DMA_TODEVICE); |
608 | if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr))) | 610 | if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr))) |
609 | goto drop_unlock; | 611 | goto drop_unlock; |
@@ -611,12 +613,12 @@ il3945_tx_skb(struct il_priv *il, | |||
611 | 613 | ||
612 | /* Add buffer containing Tx command and MAC(!) header to TFD's | 614 | /* Add buffer containing Tx command and MAC(!) header to TFD's |
613 | * first entry */ | 615 | * first entry */ |
614 | il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0); | 616 | il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0); |
615 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | 617 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); |
616 | dma_unmap_len_set(out_meta, len, len); | 618 | dma_unmap_len_set(out_meta, len, firstlen); |
617 | if (len) | 619 | if (secondlen > 0) |
618 | il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0, | 620 | il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, secondlen, 0, |
619 | U32_PAD(len)); | 621 | U32_PAD(secondlen)); |
620 | 622 | ||
621 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 623 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
622 | txq->need_update = 1; | 624 | txq->need_update = 1; |
@@ -3475,7 +3477,7 @@ static struct attribute_group il3945_attribute_group = { | |||
3475 | .attrs = il3945_sysfs_entries, | 3477 | .attrs = il3945_sysfs_entries, |
3476 | }; | 3478 | }; |
3477 | 3479 | ||
3478 | struct ieee80211_ops il3945_mac_ops = { | 3480 | static struct ieee80211_ops il3945_mac_ops __read_mostly = { |
3479 | .tx = il3945_mac_tx, | 3481 | .tx = il3945_mac_tx, |
3480 | .start = il3945_mac_start, | 3482 | .start = il3945_mac_start, |
3481 | .stop = il3945_mac_stop, | 3483 | .stop = il3945_mac_stop, |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index cb5882ea5f3a..431ae6cc5f8f 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; |
@@ -2896,7 +2896,7 @@ il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags, | |||
2896 | * Handles block-acknowledge notification from device, which reports success | 2896 | * Handles block-acknowledge notification from device, which reports success |
2897 | * of frames sent via aggregation. | 2897 | * of frames sent via aggregation. |
2898 | */ | 2898 | */ |
2899 | void | 2899 | static void |
2900 | 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) |
2901 | { | 2901 | { |
2902 | struct il_rx_pkt *pkt = rxb_addr(rxb); | 2902 | struct il_rx_pkt *pkt = rxb_addr(rxb); |
@@ -6315,7 +6315,7 @@ il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq, | |||
6315 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); | 6315 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); |
6316 | } | 6316 | } |
6317 | 6317 | ||
6318 | const struct ieee80211_ops il4965_mac_ops = { | 6318 | static const struct ieee80211_ops il4965_mac_ops = { |
6319 | .tx = il4965_mac_tx, | 6319 | .tx = il4965_mac_tx, |
6320 | .start = il4965_mac_start, | 6320 | .start = il4965_mac_start, |
6321 | .stop = il4965_mac_stop, | 6321 | .stop = il4965_mac_stop, |
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c index 1d92a59a85ad..1fc0b227e120 100644 --- a/drivers/net/wireless/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/iwlegacy/4965-rs.c | |||
@@ -2152,7 +2152,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf, | |||
2152 | int rate_idx; | 2152 | int rate_idx; |
2153 | int i; | 2153 | int i; |
2154 | u32 rate; | 2154 | u32 rate; |
2155 | u8 use_green = il4965_rs_use_green(il, sta); | 2155 | u8 use_green; |
2156 | u8 active_tbl = 0; | 2156 | u8 active_tbl = 0; |
2157 | u8 valid_tx_ant; | 2157 | u8 valid_tx_ant; |
2158 | struct il_station_priv *sta_priv; | 2158 | struct il_station_priv *sta_priv; |
@@ -2160,6 +2160,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf, | |||
2160 | if (!sta || !lq_sta) | 2160 | if (!sta || !lq_sta) |
2161 | return; | 2161 | return; |
2162 | 2162 | ||
2163 | use_green = il4965_rs_use_green(il, sta); | ||
2163 | sta_priv = (void *)sta->drv_priv; | 2164 | sta_priv = (void *)sta->drv_priv; |
2164 | 2165 | ||
2165 | i = lq_sta->last_txrate_idx; | 2166 | i = lq_sta->last_txrate_idx; |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 025d8b0eeafe..65becfe57a7d 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/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index ba319cba3f1e..56c2040a955b 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -6,7 +6,6 @@ config IWLWIFI | |||
6 | select LEDS_CLASS | 6 | select LEDS_CLASS |
7 | select LEDS_TRIGGERS | 7 | select LEDS_TRIGGERS |
8 | select MAC80211_LEDS | 8 | select MAC80211_LEDS |
9 | select IWLDVM | ||
10 | ---help--- | 9 | ---help--- |
11 | Select to build the driver supporting the: | 10 | Select to build the driver supporting the: |
12 | 11 | ||
@@ -45,6 +44,7 @@ config IWLWIFI | |||
45 | config IWLDVM | 44 | config IWLDVM |
46 | tristate "Intel Wireless WiFi DVM Firmware support" | 45 | tristate "Intel Wireless WiFi DVM Firmware support" |
47 | depends on IWLWIFI | 46 | depends on IWLWIFI |
47 | default IWLWIFI | ||
48 | help | 48 | help |
49 | This is the driver supporting the DVM firmware which is | 49 | This is the driver supporting the DVM firmware which is |
50 | currently the only firmware available for existing devices. | 50 | currently the only firmware available for existing devices. |
@@ -58,6 +58,15 @@ config IWLMVM | |||
58 | 58 | ||
59 | Say yes if you have such a device. | 59 | Say yes if you have such a device. |
60 | 60 | ||
61 | # don't call it _MODULE -- will confuse Kconfig/fixdep/... | ||
62 | config IWLWIFI_OPMODE_MODULAR | ||
63 | bool | ||
64 | default y if IWLDVM=m | ||
65 | default y if IWLMVM=m | ||
66 | |||
67 | comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM" | ||
68 | depends on IWLWIFI && IWLDVM=n && IWLMVM=n | ||
69 | |||
61 | menu "Debugging Options" | 70 | menu "Debugging Options" |
62 | depends on IWLWIFI | 71 | depends on IWLWIFI |
63 | 72 | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 6c7800044a04..3b5613ea458b 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -7,8 +7,7 @@ iwlwifi-objs += iwl-notif-wait.o | |||
7 | iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o | 7 | iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o |
8 | iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o | 8 | iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o |
9 | iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o | 9 | iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o |
10 | iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o | 10 | iwlwifi-objs += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o iwl-7000.o |
11 | iwlwifi-objs += pcie/7000.o | ||
12 | 11 | ||
13 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 12 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
14 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o | 13 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o |
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 41ec27cb6efe..e575b9b0cda8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -73,6 +73,8 @@ | |||
73 | /* AUX (TX during scan dwell) queue */ | 73 | /* AUX (TX during scan dwell) queue */ |
74 | #define IWL_AUX_QUEUE 10 | 74 | #define IWL_AUX_QUEUE 10 |
75 | 75 | ||
76 | #define IWL_INVALID_STATION 255 | ||
77 | |||
76 | /* device operations */ | 78 | /* device operations */ |
77 | extern struct iwl_lib_ops iwl1000_lib; | 79 | extern struct iwl_lib_ops iwl1000_lib; |
78 | extern struct iwl_lib_ops iwl2000_lib; | 80 | extern struct iwl_lib_ops iwl2000_lib; |
@@ -176,7 +178,7 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr); | |||
176 | /* lib */ | 178 | /* lib */ |
177 | int iwlagn_send_tx_power(struct iwl_priv *priv); | 179 | int iwlagn_send_tx_power(struct iwl_priv *priv); |
178 | void iwlagn_temperature(struct iwl_priv *priv); | 180 | void iwlagn_temperature(struct iwl_priv *priv); |
179 | int iwlagn_txfifo_flush(struct iwl_priv *priv); | 181 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk); |
180 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv); | 182 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv); |
181 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); | 183 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); |
182 | int iwl_send_statistics_request(struct iwl_priv *priv, | 184 | int iwl_send_statistics_request(struct iwl_priv *priv, |
@@ -210,6 +212,8 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
210 | struct ieee80211_sta *sta, u16 tid, u8 buf_size); | 212 | struct ieee80211_sta *sta, u16 tid, u8 buf_size); |
211 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | 213 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, |
212 | struct ieee80211_sta *sta, u16 tid); | 214 | struct ieee80211_sta *sta, u16 tid); |
215 | int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
216 | struct ieee80211_sta *sta, u16 tid); | ||
213 | int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | 217 | int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, |
214 | struct iwl_rx_cmd_buffer *rxb, | 218 | struct iwl_rx_cmd_buffer *rxb, |
215 | struct iwl_device_cmd *cmd); | 219 | struct iwl_device_cmd *cmd); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index 6468de8634b0..d6c4cf2ad7c5 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.h b/drivers/net/wireless/iwlwifi/dvm/calib.h index 65e920cab2b7..cfddde194940 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.h +++ b/drivers/net/wireless/iwlwifi/dvm/calib.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index 84e2c0fcfef6..95ca026ecc9d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -1526,6 +1526,7 @@ struct iwl_compressed_ba_resp { | |||
1526 | __le16 scd_ssn; | 1526 | __le16 scd_ssn; |
1527 | u8 txed; /* number of frames sent */ | 1527 | u8 txed; /* number of frames sent */ |
1528 | u8 txed_2_done; /* number of frames acked */ | 1528 | u8 txed_2_done; /* number of frames acked */ |
1529 | __le16 reserved1; | ||
1529 | } __packed; | 1530 | } __packed; |
1530 | 1531 | ||
1531 | /* | 1532 | /* |
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index 20806cae11b7..7b8178be119f 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * USA | 19 | * USA |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. | 22 | * in the file called COPYING. |
23 | * | 23 | * |
24 | * Contact Information: | 24 | * Contact Information: |
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -2324,6 +2324,28 @@ static ssize_t iwl_dbgfs_calib_disabled_write(struct file *file, | |||
2324 | return count; | 2324 | return count; |
2325 | } | 2325 | } |
2326 | 2326 | ||
2327 | static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | ||
2328 | const char __user *user_buf, | ||
2329 | size_t count, loff_t *ppos) | ||
2330 | { | ||
2331 | struct iwl_priv *priv = file->private_data; | ||
2332 | bool restart_fw = iwlwifi_mod_params.restart_fw; | ||
2333 | int ret; | ||
2334 | |||
2335 | iwlwifi_mod_params.restart_fw = true; | ||
2336 | |||
2337 | mutex_lock(&priv->mutex); | ||
2338 | |||
2339 | /* take the return value to make compiler happy - it will fail anyway */ | ||
2340 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, CMD_SYNC, 0, NULL); | ||
2341 | |||
2342 | mutex_unlock(&priv->mutex); | ||
2343 | |||
2344 | iwlwifi_mod_params.restart_fw = restart_fw; | ||
2345 | |||
2346 | return count; | ||
2347 | } | ||
2348 | |||
2327 | DEBUGFS_READ_FILE_OPS(ucode_rx_stats); | 2349 | DEBUGFS_READ_FILE_OPS(ucode_rx_stats); |
2328 | DEBUGFS_READ_FILE_OPS(ucode_tx_stats); | 2350 | DEBUGFS_READ_FILE_OPS(ucode_tx_stats); |
2329 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); | 2351 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); |
@@ -2343,6 +2365,7 @@ DEBUGFS_READ_FILE_OPS(bt_traffic); | |||
2343 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); | 2365 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); |
2344 | DEBUGFS_READ_FILE_OPS(reply_tx_error); | 2366 | DEBUGFS_READ_FILE_OPS(reply_tx_error); |
2345 | DEBUGFS_WRITE_FILE_OPS(echo_test); | 2367 | DEBUGFS_WRITE_FILE_OPS(echo_test); |
2368 | DEBUGFS_WRITE_FILE_OPS(fw_restart); | ||
2346 | #ifdef CONFIG_IWLWIFI_DEBUG | 2369 | #ifdef CONFIG_IWLWIFI_DEBUG |
2347 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); | 2370 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); |
2348 | #endif | 2371 | #endif |
@@ -2400,6 +2423,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir) | |||
2400 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | 2423 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); |
2401 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | 2424 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); |
2402 | DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR); | 2425 | DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR); |
2426 | DEBUGFS_ADD_FILE(fw_restart, dir_debug, S_IWUSR); | ||
2403 | #ifdef CONFIG_IWLWIFI_DEBUG | 2427 | #ifdef CONFIG_IWLWIFI_DEBUG |
2404 | DEBUGFS_ADD_FILE(log_event, dir_debug, S_IWUSR | S_IRUSR); | 2428 | DEBUGFS_ADD_FILE(log_event, dir_debug, S_IWUSR | S_IRUSR); |
2405 | #endif | 2429 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 86ea5f4c3939..54f553380aa8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * USA | 19 | * USA |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. | 22 | * in the file called COPYING. |
23 | * | 23 | * |
24 | * Contact Information: | 24 | * Contact Information: |
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -136,7 +136,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
136 | * 1. acquire mutex before calling | 136 | * 1. acquire mutex before calling |
137 | * 2. make sure rf is on and not in exit state | 137 | * 2. make sure rf is on and not in exit state |
138 | */ | 138 | */ |
139 | int iwlagn_txfifo_flush(struct iwl_priv *priv) | 139 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk) |
140 | { | 140 | { |
141 | struct iwl_txfifo_flush_cmd flush_cmd; | 141 | struct iwl_txfifo_flush_cmd flush_cmd; |
142 | struct iwl_host_cmd cmd = { | 142 | struct iwl_host_cmd cmd = { |
@@ -162,6 +162,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv) | |||
162 | if (priv->nvm_data->sku_cap_11n_enable) | 162 | if (priv->nvm_data->sku_cap_11n_enable) |
163 | flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK; | 163 | flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK; |
164 | 164 | ||
165 | if (scd_q_msk) | ||
166 | flush_cmd.queue_control = cpu_to_le32(scd_q_msk); | ||
167 | |||
165 | IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", | 168 | IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", |
166 | flush_cmd.queue_control); | 169 | flush_cmd.queue_control); |
167 | flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL); | 170 | flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL); |
@@ -173,7 +176,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv) | |||
173 | { | 176 | { |
174 | mutex_lock(&priv->mutex); | 177 | mutex_lock(&priv->mutex); |
175 | ieee80211_stop_queues(priv->hw); | 178 | ieee80211_stop_queues(priv->hw); |
176 | if (iwlagn_txfifo_flush(priv)) { | 179 | if (iwlagn_txfifo_flush(priv, 0)) { |
177 | IWL_ERR(priv, "flush request fail\n"); | 180 | IWL_ERR(priv, "flush request fail\n"); |
178 | goto done; | 181 | goto done; |
179 | } | 182 | } |
@@ -1084,7 +1087,14 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) | |||
1084 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 1087 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
1085 | struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd; | 1088 | struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd; |
1086 | struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {}; | 1089 | struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {}; |
1087 | struct iwlagn_d3_config_cmd d3_cfg_cmd = {}; | 1090 | struct iwlagn_d3_config_cmd d3_cfg_cmd = { |
1091 | /* | ||
1092 | * Program the minimum sleep time to 10 seconds, as many | ||
1093 | * platforms have issues processing a wakeup signal while | ||
1094 | * still being in the process of suspending. | ||
1095 | */ | ||
1096 | .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), | ||
1097 | }; | ||
1088 | struct wowlan_key_data key_data = { | 1098 | struct wowlan_key_data key_data = { |
1089 | .ctx = ctx, | 1099 | .ctx = ctx, |
1090 | .bssid = ctx->active.bssid_addr, | 1100 | .bssid = ctx->active.bssid_addr, |
@@ -1262,6 +1272,15 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1262 | } | 1272 | } |
1263 | 1273 | ||
1264 | /* | 1274 | /* |
1275 | * This can happen upon FW ASSERT: we clear the STATUS_FW_ERROR flag | ||
1276 | * in iwl_down but cancel the workers only later. | ||
1277 | */ | ||
1278 | if (!priv->ucode_loaded) { | ||
1279 | IWL_ERR(priv, "Fw not loaded - dropping CMD: %x\n", cmd->id); | ||
1280 | return -EIO; | ||
1281 | } | ||
1282 | |||
1283 | /* | ||
1265 | * Synchronous commands from this op-mode must hold | 1284 | * Synchronous commands from this op-mode must hold |
1266 | * the mutex, this ensures we don't try to send two | 1285 | * the mutex, this ensures we don't try to send two |
1267 | * (or more) synchronous commands at a time. | 1286 | * (or more) synchronous commands at a time. |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 2dc101fe0d24..cab23af0be9e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -777,9 +777,12 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
777 | IWL_DEBUG_HT(priv, "start Tx\n"); | 777 | IWL_DEBUG_HT(priv, "start Tx\n"); |
778 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); | 778 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); |
779 | break; | 779 | break; |
780 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
781 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | 780 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
782 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | 781 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
782 | IWL_DEBUG_HT(priv, "Flush Tx\n"); | ||
783 | ret = iwlagn_tx_agg_flush(priv, vif, sta, tid); | ||
784 | break; | ||
785 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
783 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 786 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
784 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); | 787 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); |
785 | if ((ret == 0) && (priv->agg_tids_count > 0)) { | 788 | if ((ret == 0) && (priv->agg_tids_count > 0)) { |
@@ -1132,7 +1135,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
1132 | */ | 1135 | */ |
1133 | if (drop) { | 1136 | if (drop) { |
1134 | IWL_DEBUG_MAC80211(priv, "send flush command\n"); | 1137 | IWL_DEBUG_MAC80211(priv, "send flush command\n"); |
1135 | if (iwlagn_txfifo_flush(priv)) { | 1138 | if (iwlagn_txfifo_flush(priv, 0)) { |
1136 | IWL_ERR(priv, "flush request fail\n"); | 1139 | IWL_ERR(priv, "flush request fail\n"); |
1137 | goto done; | 1140 | goto done; |
1138 | } | 1141 | } |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c index acbb50b5f1e8..707446fa00bd 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rxon.c +++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c | |||
@@ -1420,6 +1420,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, | |||
1420 | 1420 | ||
1421 | mutex_lock(&priv->mutex); | 1421 | mutex_lock(&priv->mutex); |
1422 | 1422 | ||
1423 | if (changes & BSS_CHANGED_IDLE && bss_conf->idle) { | ||
1424 | /* | ||
1425 | * If we go idle, then clearly no "passive-no-rx" | ||
1426 | * workaround is needed any more, this is a reset. | ||
1427 | */ | ||
1428 | iwlagn_lift_passive_no_rx(priv); | ||
1429 | } | ||
1430 | |||
1423 | if (unlikely(!iwl_is_ready(priv))) { | 1431 | if (unlikely(!iwl_is_ready(priv))) { |
1424 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | 1432 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); |
1425 | mutex_unlock(&priv->mutex); | 1433 | mutex_unlock(&priv->mutex); |
@@ -1451,16 +1459,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, | |||
1451 | priv->timestamp = bss_conf->sync_tsf; | 1459 | priv->timestamp = bss_conf->sync_tsf; |
1452 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | 1460 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
1453 | } else { | 1461 | } else { |
1454 | /* | ||
1455 | * If we disassociate while there are pending | ||
1456 | * frames, just wake up the queues and let the | ||
1457 | * frames "escape" ... This shouldn't really | ||
1458 | * be happening to start with, but we should | ||
1459 | * not get stuck in this case either since it | ||
1460 | * can happen if userspace gets confused. | ||
1461 | */ | ||
1462 | iwlagn_lift_passive_no_rx(priv); | ||
1463 | |||
1464 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 1462 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
1465 | 1463 | ||
1466 | if (ctx->ctxid == IWL_RXON_CTX_BSS) | 1464 | if (ctx->ctxid == IWL_RXON_CTX_BSS) |
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index 3a4aa5239c45..d69b55866714 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * USA | 19 | * USA |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. | 22 | * in the file called COPYING. |
23 | * | 23 | * |
24 | * Contact Information: | 24 | * Contact Information: |
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c index 94ef33838bc6..b775769f8322 100644 --- a/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/iwlwifi/dvm/sta.c | |||
@@ -151,7 +151,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
151 | sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); | 151 | sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); |
152 | 152 | ||
153 | if (!(flags & CMD_ASYNC)) { | 153 | if (!(flags & CMD_ASYNC)) { |
154 | cmd.flags |= CMD_WANT_SKB | CMD_WANT_HCMD; | 154 | cmd.flags |= CMD_WANT_SKB; |
155 | might_sleep(); | 155 | might_sleep(); |
156 | } | 156 | } |
157 | 157 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/testmode.c b/drivers/net/wireless/iwlwifi/dvm/testmode.c index dc6f965a123a..b89b9d9b9969 100644 --- a/drivers/net/wireless/iwlwifi/dvm/testmode.c +++ b/drivers/net/wireless/iwlwifi/dvm/testmode.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index d499a0366fa6..a900aaf47790 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * USA | 19 | * USA |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. | 22 | * in the file called COPYING. |
23 | * | 23 | * |
24 | * Contact Information: | 24 | * Contact Information: |
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -674,6 +674,51 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
674 | return ret; | 674 | return ret; |
675 | } | 675 | } |
676 | 676 | ||
677 | int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
678 | struct ieee80211_sta *sta, u16 tid) | ||
679 | { | ||
680 | struct iwl_tid_data *tid_data; | ||
681 | enum iwl_agg_state agg_state; | ||
682 | int sta_id, txq_id; | ||
683 | sta_id = iwl_sta_id(sta); | ||
684 | |||
685 | /* | ||
686 | * First set the agg state to OFF to avoid calling | ||
687 | * ieee80211_stop_tx_ba_cb in iwlagn_check_ratid_empty. | ||
688 | */ | ||
689 | spin_lock_bh(&priv->sta_lock); | ||
690 | |||
691 | tid_data = &priv->tid_data[sta_id][tid]; | ||
692 | txq_id = tid_data->agg.txq_id; | ||
693 | agg_state = tid_data->agg.state; | ||
694 | IWL_DEBUG_TX_QUEUES(priv, "Flush AGG: sta %d tid %d q %d state %d\n", | ||
695 | sta_id, tid, txq_id, tid_data->agg.state); | ||
696 | |||
697 | tid_data->agg.state = IWL_AGG_OFF; | ||
698 | |||
699 | spin_unlock_bh(&priv->sta_lock); | ||
700 | |||
701 | if (iwlagn_txfifo_flush(priv, BIT(txq_id))) | ||
702 | IWL_ERR(priv, "Couldn't flush the AGG queue\n"); | ||
703 | |||
704 | if (test_bit(txq_id, priv->agg_q_alloc)) { | ||
705 | /* | ||
706 | * If the transport didn't know that we wanted to start | ||
707 | * agreggation, don't tell it that we want to stop them. | ||
708 | * This can happen when we don't get the addBA response on | ||
709 | * time, or we hadn't time to drain the AC queues. | ||
710 | */ | ||
711 | if (agg_state == IWL_AGG_ON) | ||
712 | iwl_trans_txq_disable(priv->trans, txq_id); | ||
713 | else | ||
714 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | ||
715 | agg_state); | ||
716 | iwlagn_dealloc_agg_txq(priv, txq_id); | ||
717 | } | ||
718 | |||
719 | return 0; | ||
720 | } | ||
721 | |||
677 | int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | 722 | int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, |
678 | struct ieee80211_sta *sta, u16 tid, u8 buf_size) | 723 | struct ieee80211_sta *sta, u16 tid, u8 buf_size) |
679 | { | 724 | { |
@@ -1193,7 +1238,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1193 | memset(&info->status, 0, sizeof(info->status)); | 1238 | memset(&info->status, 0, sizeof(info->status)); |
1194 | 1239 | ||
1195 | if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && | 1240 | if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && |
1196 | iwl_is_associated_ctx(ctx) && ctx->vif && | 1241 | ctx->vif && |
1197 | ctx->vif->type == NL80211_IFTYPE_STATION) { | 1242 | ctx->vif->type == NL80211_IFTYPE_STATION) { |
1198 | /* block and stop all queues */ | 1243 | /* block and stop all queues */ |
1199 | priv->passive_no_rx = true; | 1244 | priv->passive_no_rx = true; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 736fe9bb140e..0a1cdc5e856b 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * USA | 19 | * USA |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. | 22 | * in the file called COPYING. |
23 | * | 23 | * |
24 | * Contact Information: | 24 | * Contact Information: |
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -367,6 +367,8 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
367 | return -EIO; | 367 | return -EIO; |
368 | } | 368 | } |
369 | 369 | ||
370 | priv->ucode_loaded = true; | ||
371 | |||
370 | if (ucode_type != IWL_UCODE_WOWLAN) { | 372 | if (ucode_type != IWL_UCODE_WOWLAN) { |
371 | /* delay a bit to give rfkill time to run */ | 373 | /* delay a bit to give rfkill time to run */ |
372 | msleep(5); | 374 | msleep(5); |
@@ -380,8 +382,6 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
380 | return ret; | 382 | return ret; |
381 | } | 383 | } |
382 | 384 | ||
383 | priv->ucode_loaded = true; | ||
384 | |||
385 | return 0; | 385 | return 0; |
386 | } | 386 | } |
387 | 387 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index ff3389757281..c080ae3070b2 100644 --- a/drivers/net/wireless/iwlwifi/pcie/1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-csr.h" | 30 | #include "iwl-csr.h" |
31 | #include "iwl-agn-hw.h" | 31 | #include "iwl-agn-hw.h" |
32 | #include "cfg.h" | ||
33 | 32 | ||
34 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
35 | #define IWL1000_UCODE_API_MAX 5 | 34 | #define IWL1000_UCODE_API_MAX 5 |
diff --git a/drivers/net/wireless/iwlwifi/pcie/2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index e7de33128b16..a6ddd2f9fba0 100644 --- a/drivers/net/wireless/iwlwifi/pcie/2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
31 | #include "cfg.h" | ||
32 | #include "dvm/commands.h" /* needed for BT for now */ | 31 | #include "dvm/commands.h" /* needed for BT for now */ |
33 | 32 | ||
34 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 5096f7c96ab6..403f3f224bf6 100644 --- a/drivers/net/wireless/iwlwifi/pcie/5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
31 | #include "iwl-csr.h" | 31 | #include "iwl-csr.h" |
32 | #include "cfg.h" | ||
33 | 32 | ||
34 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
35 | #define IWL5000_UCODE_API_MAX 5 | 34 | #define IWL5000_UCODE_API_MAX 5 |
diff --git a/drivers/net/wireless/iwlwifi/pcie/6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 801ff49796dd..b5ab8d1bcac0 100644 --- a/drivers/net/wireless/iwlwifi/pcie/6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
31 | #include "cfg.h" | ||
32 | #include "dvm/commands.h" /* needed for BT for now */ | 31 | #include "dvm/commands.h" /* needed for BT for now */ |
33 | 32 | ||
34 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 6e35b2b72332..50263e87fe15 100644 --- a/drivers/net/wireless/iwlwifi/pcie/7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
@@ -1,34 +1,70 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 3 | * This file is provided under a dual BSD/GPLv2 license. When using or |
4 | * redistributing this file, you may do so under either license. | ||
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 6 | * GPL LICENSE SUMMARY |
6 | * under the terms of version 2 of the GNU General Public License as | 7 | * |
8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
8 | * | 13 | * |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | 14 | * This program is distributed in the hope that it will be useful, but |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * more details. | 17 | * General Public License for more details. |
13 | * | 18 | * |
14 | * You should have received a copy of the GNU General Public License along with | 19 | * You should have received a copy of the GNU General Public License |
15 | * this program; if not, write to the Free Software Foundation, Inc., | 20 | * along with this program; if not, write to the Free Software |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, |
22 | * USA | ||
17 | * | 23 | * |
18 | * The full GNU General Public License is included in this distribution in the | 24 | * The full GNU General Public License is included in this distribution |
19 | * file called LICENSE. | 25 | * in the file called COPYING. |
20 | * | 26 | * |
21 | * Contact Information: | 27 | * Contact Information: |
22 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
24 | * | 30 | * |
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
25 | *****************************************************************************/ | 62 | *****************************************************************************/ |
26 | 63 | ||
27 | #include <linux/module.h> | 64 | #include <linux/module.h> |
28 | #include <linux/stringify.h> | 65 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 66 | #include "iwl-config.h" |
30 | #include "iwl-agn-hw.h" | 67 | #include "iwl-agn-hw.h" |
31 | #include "cfg.h" | ||
32 | 68 | ||
33 | /* Highest firmware API version supported */ | 69 | /* Highest firmware API version supported */ |
34 | #define IWL7260_UCODE_API_MAX 6 | 70 | #define IWL7260_UCODE_API_MAX 6 |
@@ -70,7 +106,6 @@ static const struct iwl_base_params iwl7000_base_params = { | |||
70 | }; | 106 | }; |
71 | 107 | ||
72 | static const struct iwl_ht_params iwl7000_ht_params = { | 108 | static const struct iwl_ht_params iwl7000_ht_params = { |
73 | .ht_greenfield_support = true, | ||
74 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | 109 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
75 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | 110 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), |
76 | }; | 111 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index e9975c54c276..6d73f943cefa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 743b48343358..c38aa8f77554 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -275,4 +275,51 @@ struct iwl_cfg { | |||
275 | const bool temp_offset_v2; | 275 | const bool temp_offset_v2; |
276 | }; | 276 | }; |
277 | 277 | ||
278 | /* | ||
279 | * This list declares the config structures for all devices. | ||
280 | */ | ||
281 | extern const struct iwl_cfg iwl5300_agn_cfg; | ||
282 | extern const struct iwl_cfg iwl5100_agn_cfg; | ||
283 | extern const struct iwl_cfg iwl5350_agn_cfg; | ||
284 | extern const struct iwl_cfg iwl5100_bgn_cfg; | ||
285 | extern const struct iwl_cfg iwl5100_abg_cfg; | ||
286 | extern const struct iwl_cfg iwl5150_agn_cfg; | ||
287 | extern const struct iwl_cfg iwl5150_abg_cfg; | ||
288 | extern const struct iwl_cfg iwl6005_2agn_cfg; | ||
289 | extern const struct iwl_cfg iwl6005_2abg_cfg; | ||
290 | extern const struct iwl_cfg iwl6005_2bg_cfg; | ||
291 | extern const struct iwl_cfg iwl6005_2agn_sff_cfg; | ||
292 | extern const struct iwl_cfg iwl6005_2agn_d_cfg; | ||
293 | extern const struct iwl_cfg iwl6005_2agn_mow1_cfg; | ||
294 | extern const struct iwl_cfg iwl6005_2agn_mow2_cfg; | ||
295 | extern const struct iwl_cfg iwl1030_bgn_cfg; | ||
296 | extern const struct iwl_cfg iwl1030_bg_cfg; | ||
297 | extern const struct iwl_cfg iwl6030_2agn_cfg; | ||
298 | extern const struct iwl_cfg iwl6030_2abg_cfg; | ||
299 | extern const struct iwl_cfg iwl6030_2bgn_cfg; | ||
300 | extern const struct iwl_cfg iwl6030_2bg_cfg; | ||
301 | extern const struct iwl_cfg iwl6000i_2agn_cfg; | ||
302 | extern const struct iwl_cfg iwl6000i_2abg_cfg; | ||
303 | extern const struct iwl_cfg iwl6000i_2bg_cfg; | ||
304 | extern const struct iwl_cfg iwl6000_3agn_cfg; | ||
305 | extern const struct iwl_cfg iwl6050_2agn_cfg; | ||
306 | extern const struct iwl_cfg iwl6050_2abg_cfg; | ||
307 | extern const struct iwl_cfg iwl6150_bgn_cfg; | ||
308 | extern const struct iwl_cfg iwl6150_bg_cfg; | ||
309 | extern const struct iwl_cfg iwl1000_bgn_cfg; | ||
310 | extern const struct iwl_cfg iwl1000_bg_cfg; | ||
311 | extern const struct iwl_cfg iwl100_bgn_cfg; | ||
312 | extern const struct iwl_cfg iwl100_bg_cfg; | ||
313 | extern const struct iwl_cfg iwl130_bgn_cfg; | ||
314 | extern const struct iwl_cfg iwl130_bg_cfg; | ||
315 | extern const struct iwl_cfg iwl2000_2bgn_cfg; | ||
316 | extern const struct iwl_cfg iwl2000_2bgn_d_cfg; | ||
317 | extern const struct iwl_cfg iwl2030_2bgn_cfg; | ||
318 | extern const struct iwl_cfg iwl6035_2agn_cfg; | ||
319 | extern const struct iwl_cfg iwl105_bgn_cfg; | ||
320 | extern const struct iwl_cfg iwl105_bgn_d_cfg; | ||
321 | extern const struct iwl_cfg iwl135_bgn_cfg; | ||
322 | extern const struct iwl_cfg iwl7260_2ac_cfg; | ||
323 | extern const struct iwl_cfg iwl3160_ac_cfg; | ||
324 | |||
278 | #endif /* __IWL_CONFIG_H__ */ | 325 | #endif /* __IWL_CONFIG_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index df3463a38704..20e845d4da04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c index 87535a67de76..8a44f594528d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.c +++ b/drivers/net/wireless/iwlwifi/iwl-debug.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/device.h> | 66 | #include <linux/device.h> |
67 | #include <linux/interrupt.h> | 67 | #include <linux/interrupt.h> |
68 | #include <linux/export.h> | 68 | #include <linux/export.h> |
69 | #include "iwl-drv.h" | ||
69 | #include "iwl-debug.h" | 70 | #include "iwl-debug.h" |
70 | #include "iwl-devtrace.h" | 71 | #include "iwl-devtrace.h" |
71 | 72 | ||
@@ -85,11 +86,11 @@ void __iwl_ ##fn(struct device *dev, const char *fmt, ...) \ | |||
85 | } | 86 | } |
86 | 87 | ||
87 | __iwl_fn(warn) | 88 | __iwl_fn(warn) |
88 | EXPORT_SYMBOL_GPL(__iwl_warn); | 89 | IWL_EXPORT_SYMBOL(__iwl_warn); |
89 | __iwl_fn(info) | 90 | __iwl_fn(info) |
90 | EXPORT_SYMBOL_GPL(__iwl_info); | 91 | IWL_EXPORT_SYMBOL(__iwl_info); |
91 | __iwl_fn(crit) | 92 | __iwl_fn(crit) |
92 | EXPORT_SYMBOL_GPL(__iwl_crit); | 93 | IWL_EXPORT_SYMBOL(__iwl_crit); |
93 | 94 | ||
94 | void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, | 95 | void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, |
95 | const char *fmt, ...) | 96 | const char *fmt, ...) |
@@ -110,7 +111,7 @@ void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, | |||
110 | trace_iwlwifi_err(&vaf); | 111 | trace_iwlwifi_err(&vaf); |
111 | va_end(args); | 112 | va_end(args); |
112 | } | 113 | } |
113 | EXPORT_SYMBOL_GPL(__iwl_err); | 114 | IWL_EXPORT_SYMBOL(__iwl_err); |
114 | 115 | ||
115 | #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) | 116 | #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) |
116 | void __iwl_dbg(struct device *dev, | 117 | void __iwl_dbg(struct device *dev, |
@@ -133,5 +134,5 @@ void __iwl_dbg(struct device *dev, | |||
133 | trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf); | 134 | trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf); |
134 | va_end(args); | 135 | va_end(args); |
135 | } | 136 | } |
136 | EXPORT_SYMBOL_GPL(__iwl_dbg); | 137 | IWL_EXPORT_SYMBOL(__iwl_dbg); |
137 | #endif | 138 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 9a0f45ec9e01..4491c1c72cc7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -298,7 +298,7 @@ TRACE_EVENT(iwlwifi_dbg, | |||
298 | MAX_MSG_LEN, vaf->fmt, | 298 | MAX_MSG_LEN, vaf->fmt, |
299 | *vaf->va) >= MAX_MSG_LEN); | 299 | *vaf->va) >= MAX_MSG_LEN); |
300 | ), | 300 | ), |
301 | TP_printk("%s", (char *)__get_dynamic_array(msg)) | 301 | TP_printk("%s", __get_str(msg)) |
302 | ); | 302 | ); |
303 | 303 | ||
304 | #undef TRACE_SYSTEM | 304 | #undef TRACE_SYSTEM |
@@ -349,25 +349,23 @@ TRACE_EVENT(iwlwifi_dev_rx_data, | |||
349 | TRACE_EVENT(iwlwifi_dev_hcmd, | 349 | TRACE_EVENT(iwlwifi_dev_hcmd, |
350 | TP_PROTO(const struct device *dev, | 350 | TP_PROTO(const struct device *dev, |
351 | struct iwl_host_cmd *cmd, u16 total_size, | 351 | struct iwl_host_cmd *cmd, u16 total_size, |
352 | const void *hdr, size_t hdr_len), | 352 | struct iwl_cmd_header *hdr), |
353 | TP_ARGS(dev, cmd, total_size, hdr, hdr_len), | 353 | TP_ARGS(dev, cmd, total_size, hdr), |
354 | TP_STRUCT__entry( | 354 | TP_STRUCT__entry( |
355 | DEV_ENTRY | 355 | DEV_ENTRY |
356 | __dynamic_array(u8, hcmd, total_size) | 356 | __dynamic_array(u8, hcmd, total_size) |
357 | __field(u32, flags) | 357 | __field(u32, flags) |
358 | ), | 358 | ), |
359 | TP_fast_assign( | 359 | TP_fast_assign( |
360 | int i, offset = hdr_len; | 360 | int i, offset = sizeof(*hdr); |
361 | 361 | ||
362 | DEV_ASSIGN; | 362 | DEV_ASSIGN; |
363 | __entry->flags = cmd->flags; | 363 | __entry->flags = cmd->flags; |
364 | memcpy(__get_dynamic_array(hcmd), hdr, hdr_len); | 364 | memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr)); |
365 | 365 | ||
366 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 366 | for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { |
367 | if (!cmd->len[i]) | 367 | if (!cmd->len[i]) |
368 | continue; | 368 | continue; |
369 | if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) | ||
370 | continue; | ||
371 | memcpy((u8 *)__get_dynamic_array(hcmd) + offset, | 369 | memcpy((u8 *)__get_dynamic_array(hcmd) + offset, |
372 | cmd->data[i], cmd->len[i]); | 370 | cmd->data[i], cmd->len[i]); |
373 | offset += cmd->len[i]; | 371 | offset += cmd->len[i]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 6f228bb2b844..39aad9893e0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -912,8 +912,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
912 | } | 912 | } |
913 | } | 913 | } |
914 | 914 | ||
915 | IWL_INFO(drv, "loaded firmware version %s", drv->fw.fw_version); | ||
916 | |||
917 | /* | 915 | /* |
918 | * In mvm uCode there is no difference between data and instructions | 916 | * In mvm uCode there is no difference between data and instructions |
919 | * sections. | 917 | * sections. |
@@ -970,6 +968,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
970 | else | 968 | else |
971 | op = &iwlwifi_opmode_table[DVM_OP_MODE]; | 969 | op = &iwlwifi_opmode_table[DVM_OP_MODE]; |
972 | 970 | ||
971 | IWL_INFO(drv, "loaded firmware version %s op_mode %s\n", | ||
972 | drv->fw.fw_version, op->name); | ||
973 | |||
973 | /* add this device to the list of devices using this op_mode */ | 974 | /* add this device to the list of devices using this op_mode */ |
974 | list_add_tail(&drv->list, &op->drv); | 975 | list_add_tail(&drv->list, &op->drv); |
975 | 976 | ||
@@ -997,8 +998,13 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
997 | * else from proceeding if the module fails to load | 998 | * else from proceeding if the module fails to load |
998 | * or hangs loading. | 999 | * or hangs loading. |
999 | */ | 1000 | */ |
1000 | if (load_module) | 1001 | if (load_module) { |
1001 | request_module("%s", op->name); | 1002 | err = request_module("%s", op->name); |
1003 | if (err) | ||
1004 | IWL_ERR(drv, | ||
1005 | "failed to load module %s (error %d), is dynamic loading enabled?\n", | ||
1006 | op->name, err); | ||
1007 | } | ||
1002 | return; | 1008 | return; |
1003 | 1009 | ||
1004 | try_again: | 1010 | try_again: |
@@ -1102,8 +1108,7 @@ void iwl_drv_stop(struct iwl_drv *drv) | |||
1102 | 1108 | ||
1103 | /* shared module parameters */ | 1109 | /* shared module parameters */ |
1104 | struct iwl_mod_params iwlwifi_mod_params = { | 1110 | struct iwl_mod_params iwlwifi_mod_params = { |
1105 | .amsdu_size_8K = 1, | 1111 | .restart_fw = true, |
1106 | .restart_fw = 1, | ||
1107 | .plcp_check = true, | 1112 | .plcp_check = true, |
1108 | .bt_coex_active = true, | 1113 | .bt_coex_active = true, |
1109 | .power_level = IWL_POWER_INDEX_1, | 1114 | .power_level = IWL_POWER_INDEX_1, |
@@ -1112,7 +1117,7 @@ struct iwl_mod_params iwlwifi_mod_params = { | |||
1112 | .wd_disable = true, | 1117 | .wd_disable = true, |
1113 | /* the rest are 0 by default */ | 1118 | /* the rest are 0 by default */ |
1114 | }; | 1119 | }; |
1115 | EXPORT_SYMBOL_GPL(iwlwifi_mod_params); | 1120 | IWL_EXPORT_SYMBOL(iwlwifi_mod_params); |
1116 | 1121 | ||
1117 | int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) | 1122 | int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) |
1118 | { | 1123 | { |
@@ -1136,7 +1141,7 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) | |||
1136 | mutex_unlock(&iwlwifi_opmode_table_mtx); | 1141 | mutex_unlock(&iwlwifi_opmode_table_mtx); |
1137 | return -EIO; | 1142 | return -EIO; |
1138 | } | 1143 | } |
1139 | EXPORT_SYMBOL_GPL(iwl_opmode_register); | 1144 | IWL_EXPORT_SYMBOL(iwl_opmode_register); |
1140 | 1145 | ||
1141 | void iwl_opmode_deregister(const char *name) | 1146 | void iwl_opmode_deregister(const char *name) |
1142 | { | 1147 | { |
@@ -1158,7 +1163,7 @@ void iwl_opmode_deregister(const char *name) | |||
1158 | } | 1163 | } |
1159 | mutex_unlock(&iwlwifi_opmode_table_mtx); | 1164 | mutex_unlock(&iwlwifi_opmode_table_mtx); |
1160 | } | 1165 | } |
1161 | EXPORT_SYMBOL_GPL(iwl_opmode_deregister); | 1166 | IWL_EXPORT_SYMBOL(iwl_opmode_deregister); |
1162 | 1167 | ||
1163 | static int __init iwl_drv_init(void) | 1168 | static int __init iwl_drv_init(void) |
1164 | { | 1169 | { |
@@ -1207,9 +1212,9 @@ MODULE_PARM_DESC(11n_disable, | |||
1207 | "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX"); | 1212 | "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX"); |
1208 | module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K, | 1213 | module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K, |
1209 | int, S_IRUGO); | 1214 | int, S_IRUGO); |
1210 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | 1215 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)"); |
1211 | module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, int, S_IRUGO); | 1216 | module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, bool, S_IRUGO); |
1212 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); | 1217 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)"); |
1213 | 1218 | ||
1214 | module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling, | 1219 | module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling, |
1215 | int, S_IRUGO); | 1220 | int, S_IRUGO); |
@@ -1267,7 +1272,3 @@ module_param_named(auto_agg, iwlwifi_mod_params.auto_agg, | |||
1267 | bool, S_IRUGO); | 1272 | bool, S_IRUGO); |
1268 | MODULE_PARM_DESC(auto_agg, | 1273 | MODULE_PARM_DESC(auto_agg, |
1269 | "enable agg w/o check traffic load (default: enable)"); | 1274 | "enable agg w/o check traffic load (default: enable)"); |
1270 | |||
1271 | module_param_named(5ghz_disable, iwlwifi_mod_params.disable_5ghz, | ||
1272 | bool, S_IRUGO); | ||
1273 | MODULE_PARM_DESC(5ghz_disable, "disable 5GHz band (default: 0 [enabled])"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h index 594a5c71b272..7d1450916308 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/iwlwifi/iwl-drv.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -63,6 +63,8 @@ | |||
63 | #ifndef __iwl_drv_h__ | 63 | #ifndef __iwl_drv_h__ |
64 | #define __iwl_drv_h__ | 64 | #define __iwl_drv_h__ |
65 | 65 | ||
66 | #include <linux/module.h> | ||
67 | |||
66 | /* for all modules */ | 68 | /* for all modules */ |
67 | #define DRV_NAME "iwlwifi" | 69 | #define DRV_NAME "iwlwifi" |
68 | #define IWLWIFI_VERSION "in-tree:" | 70 | #define IWLWIFI_VERSION "in-tree:" |
@@ -123,4 +125,17 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans, | |||
123 | */ | 125 | */ |
124 | void iwl_drv_stop(struct iwl_drv *drv); | 126 | void iwl_drv_stop(struct iwl_drv *drv); |
125 | 127 | ||
128 | /* | ||
129 | * exported symbol management | ||
130 | * | ||
131 | * The driver can be split into multiple modules, in which case some symbols | ||
132 | * must be exported for the sub-modules. However, if it's not split and | ||
133 | * everything is built-in, then we can avoid that. | ||
134 | */ | ||
135 | #ifdef CONFIG_IWLWIFI_OPMODE_MODULAR | ||
136 | #define IWL_EXPORT_SYMBOL(sym) EXPORT_SYMBOL_GPL(sym) | ||
137 | #else | ||
138 | #define IWL_EXPORT_SYMBOL(sym) | ||
139 | #endif | ||
140 | |||
126 | #endif /* __iwl_drv_h__ */ | 141 | #endif /* __iwl_drv_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c index 034f2ff4f43d..600c9fdd7f71 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -62,6 +62,7 @@ | |||
62 | #include <linux/types.h> | 62 | #include <linux/types.h> |
63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
65 | #include "iwl-drv.h" | ||
65 | #include "iwl-modparams.h" | 66 | #include "iwl-modparams.h" |
66 | #include "iwl-eeprom-parse.h" | 67 | #include "iwl-eeprom-parse.h" |
67 | 68 | ||
@@ -749,7 +750,7 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, | |||
749 | } | 750 | } |
750 | 751 | ||
751 | ht_info->ht_supported = true; | 752 | ht_info->ht_supported = true; |
752 | ht_info->cap = 0; | 753 | ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40; |
753 | 754 | ||
754 | if (iwlwifi_mod_params.amsdu_size_8K) | 755 | if (iwlwifi_mod_params.amsdu_size_8K) |
755 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | 756 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; |
@@ -909,7 +910,7 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | |||
909 | kfree(data); | 910 | kfree(data); |
910 | return NULL; | 911 | return NULL; |
911 | } | 912 | } |
912 | EXPORT_SYMBOL_GPL(iwl_parse_eeprom_data); | 913 | IWL_EXPORT_SYMBOL(iwl_parse_eeprom_data); |
913 | 914 | ||
914 | /* helper functions */ | 915 | /* helper functions */ |
915 | int iwl_nvm_check_version(struct iwl_nvm_data *data, | 916 | int iwl_nvm_check_version(struct iwl_nvm_data *data, |
@@ -928,4 +929,4 @@ int iwl_nvm_check_version(struct iwl_nvm_data *data, | |||
928 | data->calib_version, trans->cfg->nvm_calib_ver); | 929 | data->calib_version, trans->cfg->nvm_calib_ver); |
929 | return -EINVAL; | 930 | return -EINVAL; |
930 | } | 931 | } |
931 | EXPORT_SYMBOL_GPL(iwl_nvm_check_version); | 932 | IWL_EXPORT_SYMBOL(iwl_nvm_check_version); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h index 683fe6a8c58f..37f115390b19 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c index ef4806f27cf8..e5f2e362ab0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -63,6 +63,7 @@ | |||
63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
65 | 65 | ||
66 | #include "iwl-drv.h" | ||
66 | #include "iwl-debug.h" | 67 | #include "iwl-debug.h" |
67 | #include "iwl-eeprom-read.h" | 68 | #include "iwl-eeprom-read.h" |
68 | #include "iwl-io.h" | 69 | #include "iwl-io.h" |
@@ -460,4 +461,4 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) | |||
460 | 461 | ||
461 | return ret; | 462 | return ret; |
462 | } | 463 | } |
463 | EXPORT_SYMBOL_GPL(iwl_read_eeprom); | 464 | IWL_EXPORT_SYMBOL(iwl_read_eeprom); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h index b2588c5cbf93..8e941f8bd7d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index f5592fb3b1ed..484d318245fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 90873eca35f7..8b6c6fd95ed0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index b545178e46e3..c4c446d41eb0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -73,12 +73,14 @@ | |||
73 | * treats good CRC threshold as a boolean | 73 | * treats good CRC threshold as a boolean |
74 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). | 74 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). |
75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. | 75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. |
76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS | ||
76 | */ | 77 | */ |
77 | enum iwl_ucode_tlv_flag { | 78 | enum iwl_ucode_tlv_flag { |
78 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), | 79 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), |
79 | IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), | 80 | IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), |
80 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), | 81 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), |
81 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), | 82 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), |
83 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), | ||
82 | }; | 84 | }; |
83 | 85 | ||
84 | /* The default calibrate table size if not specified by firmware file */ | 86 | /* The default calibrate table size if not specified by firmware file */ |
@@ -152,6 +154,19 @@ struct iwl_tlv_calib_ctrl { | |||
152 | __le32 event_trigger; | 154 | __le32 event_trigger; |
153 | } __packed; | 155 | } __packed; |
154 | 156 | ||
157 | enum iwl_fw_phy_cfg { | ||
158 | FW_PHY_CFG_RADIO_TYPE_POS = 0, | ||
159 | FW_PHY_CFG_RADIO_TYPE = 0x3 << FW_PHY_CFG_RADIO_TYPE_POS, | ||
160 | FW_PHY_CFG_RADIO_STEP_POS = 2, | ||
161 | FW_PHY_CFG_RADIO_STEP = 0x3 << FW_PHY_CFG_RADIO_STEP_POS, | ||
162 | FW_PHY_CFG_RADIO_DASH_POS = 4, | ||
163 | FW_PHY_CFG_RADIO_DASH = 0x3 << FW_PHY_CFG_RADIO_DASH_POS, | ||
164 | FW_PHY_CFG_TX_CHAIN_POS = 16, | ||
165 | FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS, | ||
166 | FW_PHY_CFG_RX_CHAIN_POS = 20, | ||
167 | FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS, | ||
168 | }; | ||
169 | |||
155 | /** | 170 | /** |
156 | * struct iwl_fw - variables associated with the firmware | 171 | * struct iwl_fw - variables associated with the firmware |
157 | * | 172 | * |
@@ -188,4 +203,16 @@ struct iwl_fw { | |||
188 | bool mvm_fw; | 203 | bool mvm_fw; |
189 | }; | 204 | }; |
190 | 205 | ||
206 | static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw) | ||
207 | { | ||
208 | return (fw->phy_config & FW_PHY_CFG_TX_CHAIN) >> | ||
209 | FW_PHY_CFG_TX_CHAIN_POS; | ||
210 | } | ||
211 | |||
212 | static inline u8 iwl_fw_valid_rx_ant(const struct iwl_fw *fw) | ||
213 | { | ||
214 | return (fw->phy_config & FW_PHY_CFG_RX_CHAIN) >> | ||
215 | FW_PHY_CFG_RX_CHAIN_POS; | ||
216 | } | ||
217 | |||
191 | #endif /* __iwl_fw_h__ */ | 218 | #endif /* __iwl_fw_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 276410d82de4..305c81f2c2b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/device.h> | 29 | #include <linux/device.h> |
30 | #include <linux/export.h> | 30 | #include <linux/export.h> |
31 | 31 | ||
32 | #include "iwl-drv.h" | ||
32 | #include "iwl-io.h" | 33 | #include "iwl-io.h" |
33 | #include "iwl-csr.h" | 34 | #include "iwl-csr.h" |
34 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
@@ -49,7 +50,7 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | |||
49 | 50 | ||
50 | return -ETIMEDOUT; | 51 | return -ETIMEDOUT; |
51 | } | 52 | } |
52 | EXPORT_SYMBOL_GPL(iwl_poll_bit); | 53 | IWL_EXPORT_SYMBOL(iwl_poll_bit); |
53 | 54 | ||
54 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) | 55 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) |
55 | { | 56 | { |
@@ -62,7 +63,7 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) | |||
62 | 63 | ||
63 | return value; | 64 | return value; |
64 | } | 65 | } |
65 | EXPORT_SYMBOL_GPL(iwl_read_direct32); | 66 | IWL_EXPORT_SYMBOL(iwl_read_direct32); |
66 | 67 | ||
67 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) | 68 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) |
68 | { | 69 | { |
@@ -73,7 +74,7 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) | |||
73 | iwl_trans_release_nic_access(trans, &flags); | 74 | iwl_trans_release_nic_access(trans, &flags); |
74 | } | 75 | } |
75 | } | 76 | } |
76 | EXPORT_SYMBOL_GPL(iwl_write_direct32); | 77 | IWL_EXPORT_SYMBOL(iwl_write_direct32); |
77 | 78 | ||
78 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | 79 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, |
79 | int timeout) | 80 | int timeout) |
@@ -89,7 +90,7 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | |||
89 | 90 | ||
90 | return -ETIMEDOUT; | 91 | return -ETIMEDOUT; |
91 | } | 92 | } |
92 | EXPORT_SYMBOL_GPL(iwl_poll_direct_bit); | 93 | IWL_EXPORT_SYMBOL(iwl_poll_direct_bit); |
93 | 94 | ||
94 | static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs) | 95 | static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs) |
95 | { | 96 | { |
@@ -115,7 +116,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) | |||
115 | } | 116 | } |
116 | return val; | 117 | return val; |
117 | } | 118 | } |
118 | EXPORT_SYMBOL_GPL(iwl_read_prph); | 119 | IWL_EXPORT_SYMBOL(iwl_read_prph); |
119 | 120 | ||
120 | void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) | 121 | void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) |
121 | { | 122 | { |
@@ -126,7 +127,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) | |||
126 | iwl_trans_release_nic_access(trans, &flags); | 127 | iwl_trans_release_nic_access(trans, &flags); |
127 | } | 128 | } |
128 | } | 129 | } |
129 | EXPORT_SYMBOL_GPL(iwl_write_prph); | 130 | IWL_EXPORT_SYMBOL(iwl_write_prph); |
130 | 131 | ||
131 | void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | 132 | void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) |
132 | { | 133 | { |
@@ -138,7 +139,7 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | |||
138 | iwl_trans_release_nic_access(trans, &flags); | 139 | iwl_trans_release_nic_access(trans, &flags); |
139 | } | 140 | } |
140 | } | 141 | } |
141 | EXPORT_SYMBOL_GPL(iwl_set_bits_prph); | 142 | IWL_EXPORT_SYMBOL(iwl_set_bits_prph); |
142 | 143 | ||
143 | void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, | 144 | void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, |
144 | u32 bits, u32 mask) | 145 | u32 bits, u32 mask) |
@@ -151,7 +152,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, | |||
151 | iwl_trans_release_nic_access(trans, &flags); | 152 | iwl_trans_release_nic_access(trans, &flags); |
152 | } | 153 | } |
153 | } | 154 | } |
154 | EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph); | 155 | IWL_EXPORT_SYMBOL(iwl_set_bits_mask_prph); |
155 | 156 | ||
156 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | 157 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) |
157 | { | 158 | { |
@@ -164,4 +165,4 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | |||
164 | iwl_trans_release_nic_access(trans, &flags); | 165 | iwl_trans_release_nic_access(trans, &flags); |
165 | } | 166 | } |
166 | } | 167 | } |
167 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); | 168 | IWL_EXPORT_SYMBOL(iwl_clear_bits_prph); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index e5e3a79eae2f..d6f6c37c09fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -91,7 +91,7 @@ enum iwl_power_level { | |||
91 | * @sw_crypto: using hardware encryption, default = 0 | 91 | * @sw_crypto: using hardware encryption, default = 0 |
92 | * @disable_11n: disable 11n capabilities, default = 0, | 92 | * @disable_11n: disable 11n capabilities, default = 0, |
93 | * use IWL_DISABLE_HT_* constants | 93 | * use IWL_DISABLE_HT_* constants |
94 | * @amsdu_size_8K: enable 8K amsdu size, default = 1 | 94 | * @amsdu_size_8K: enable 8K amsdu size, default = 0 |
95 | * @restart_fw: restart firmware, default = 1 | 95 | * @restart_fw: restart firmware, default = 1 |
96 | * @plcp_check: enable plcp health check, default = true | 96 | * @plcp_check: enable plcp health check, default = true |
97 | * @wd_disable: enable stuck queue check, default = 0 | 97 | * @wd_disable: enable stuck queue check, default = 0 |
@@ -103,13 +103,12 @@ enum iwl_power_level { | |||
103 | * @ant_coupling: antenna coupling in dB, default = 0 | 103 | * @ant_coupling: antenna coupling in dB, default = 0 |
104 | * @bt_ch_announce: BT channel inhibition, default = enable | 104 | * @bt_ch_announce: BT channel inhibition, default = enable |
105 | * @auto_agg: enable agg. without check, default = true | 105 | * @auto_agg: enable agg. without check, default = true |
106 | * @disable_5ghz: disable 5GHz capability, default = false | ||
107 | */ | 106 | */ |
108 | struct iwl_mod_params { | 107 | struct iwl_mod_params { |
109 | int sw_crypto; | 108 | int sw_crypto; |
110 | unsigned int disable_11n; | 109 | unsigned int disable_11n; |
111 | int amsdu_size_8K; | 110 | int amsdu_size_8K; |
112 | int restart_fw; | 111 | bool restart_fw; |
113 | bool plcp_check; | 112 | bool plcp_check; |
114 | int wd_disable; | 113 | int wd_disable; |
115 | bool bt_coex_active; | 114 | bool bt_coex_active; |
@@ -120,7 +119,6 @@ struct iwl_mod_params { | |||
120 | int ant_coupling; | 119 | int ant_coupling; |
121 | bool bt_ch_announce; | 120 | bool bt_ch_announce; |
122 | bool auto_agg; | 121 | bool auto_agg; |
123 | bool disable_5ghz; | ||
124 | }; | 122 | }; |
125 | 123 | ||
126 | #endif /* #__iwl_modparams_h__ */ | 124 | #endif /* #__iwl_modparams_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c index c3affbc62cdf..940b8a9d5285 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -63,6 +63,7 @@ | |||
63 | #include <linux/sched.h> | 63 | #include <linux/sched.h> |
64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
65 | 65 | ||
66 | #include "iwl-drv.h" | ||
66 | #include "iwl-notif-wait.h" | 67 | #include "iwl-notif-wait.h" |
67 | 68 | ||
68 | 69 | ||
@@ -72,7 +73,7 @@ void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait) | |||
72 | INIT_LIST_HEAD(¬if_wait->notif_waits); | 73 | INIT_LIST_HEAD(¬if_wait->notif_waits); |
73 | init_waitqueue_head(¬if_wait->notif_waitq); | 74 | init_waitqueue_head(¬if_wait->notif_waitq); |
74 | } | 75 | } |
75 | EXPORT_SYMBOL_GPL(iwl_notification_wait_init); | 76 | IWL_EXPORT_SYMBOL(iwl_notification_wait_init); |
76 | 77 | ||
77 | void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, | 78 | void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, |
78 | struct iwl_rx_packet *pkt) | 79 | struct iwl_rx_packet *pkt) |
@@ -117,7 +118,7 @@ void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, | |||
117 | if (triggered) | 118 | if (triggered) |
118 | wake_up_all(¬if_wait->notif_waitq); | 119 | wake_up_all(¬if_wait->notif_waitq); |
119 | } | 120 | } |
120 | EXPORT_SYMBOL_GPL(iwl_notification_wait_notify); | 121 | IWL_EXPORT_SYMBOL(iwl_notification_wait_notify); |
121 | 122 | ||
122 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) | 123 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) |
123 | { | 124 | { |
@@ -130,7 +131,7 @@ void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) | |||
130 | 131 | ||
131 | wake_up_all(¬if_wait->notif_waitq); | 132 | wake_up_all(¬if_wait->notif_waitq); |
132 | } | 133 | } |
133 | EXPORT_SYMBOL_GPL(iwl_abort_notification_waits); | 134 | IWL_EXPORT_SYMBOL(iwl_abort_notification_waits); |
134 | 135 | ||
135 | void | 136 | void |
136 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, | 137 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, |
@@ -154,7 +155,7 @@ iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, | |||
154 | list_add(&wait_entry->list, ¬if_wait->notif_waits); | 155 | list_add(&wait_entry->list, ¬if_wait->notif_waits); |
155 | spin_unlock_bh(¬if_wait->notif_wait_lock); | 156 | spin_unlock_bh(¬if_wait->notif_wait_lock); |
156 | } | 157 | } |
157 | EXPORT_SYMBOL_GPL(iwl_init_notification_wait); | 158 | IWL_EXPORT_SYMBOL(iwl_init_notification_wait); |
158 | 159 | ||
159 | int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, | 160 | int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, |
160 | struct iwl_notification_wait *wait_entry, | 161 | struct iwl_notification_wait *wait_entry, |
@@ -178,7 +179,7 @@ int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, | |||
178 | return -ETIMEDOUT; | 179 | return -ETIMEDOUT; |
179 | return 0; | 180 | return 0; |
180 | } | 181 | } |
181 | EXPORT_SYMBOL_GPL(iwl_wait_notification); | 182 | IWL_EXPORT_SYMBOL(iwl_wait_notification); |
182 | 183 | ||
183 | void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait, | 184 | void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait, |
184 | struct iwl_notification_wait *wait_entry) | 185 | struct iwl_notification_wait *wait_entry) |
@@ -187,4 +188,4 @@ void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait, | |||
187 | list_del(&wait_entry->list); | 188 | list_del(&wait_entry->list); |
188 | spin_unlock_bh(¬if_wait->notif_wait_lock); | 189 | spin_unlock_bh(¬if_wait->notif_wait_lock); |
189 | } | 190 | } |
190 | EXPORT_SYMBOL_GPL(iwl_remove_notification); | 191 | IWL_EXPORT_SYMBOL(iwl_remove_notification); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h index c2ce764463a3..2e2f1c8c99f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index a70213bdb83c..6199a0a597a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -62,6 +62,7 @@ | |||
62 | #include <linux/types.h> | 62 | #include <linux/types.h> |
63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
65 | #include "iwl-drv.h" | ||
65 | #include "iwl-modparams.h" | 66 | #include "iwl-modparams.h" |
66 | #include "iwl-nvm-parse.h" | 67 | #include "iwl-nvm-parse.h" |
67 | 68 | ||
@@ -149,6 +150,8 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = { | |||
149 | * @NVM_CHANNEL_DFS: dynamic freq selection candidate | 150 | * @NVM_CHANNEL_DFS: dynamic freq selection candidate |
150 | * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?) | 151 | * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?) |
151 | * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?) | 152 | * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?) |
153 | * @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?) | ||
154 | * @NVM_CHANNEL_160MHZ: 160 MHz channel okay (?) | ||
152 | */ | 155 | */ |
153 | enum iwl_nvm_channel_flags { | 156 | enum iwl_nvm_channel_flags { |
154 | NVM_CHANNEL_VALID = BIT(0), | 157 | NVM_CHANNEL_VALID = BIT(0), |
@@ -158,6 +161,8 @@ enum iwl_nvm_channel_flags { | |||
158 | NVM_CHANNEL_DFS = BIT(7), | 161 | NVM_CHANNEL_DFS = BIT(7), |
159 | NVM_CHANNEL_WIDE = BIT(8), | 162 | NVM_CHANNEL_WIDE = BIT(8), |
160 | NVM_CHANNEL_40MHZ = BIT(9), | 163 | NVM_CHANNEL_40MHZ = BIT(9), |
164 | NVM_CHANNEL_80MHZ = BIT(10), | ||
165 | NVM_CHANNEL_160MHZ = BIT(11), | ||
161 | }; | 166 | }; |
162 | 167 | ||
163 | #define CHECK_AND_PRINT_I(x) \ | 168 | #define CHECK_AND_PRINT_I(x) \ |
@@ -210,6 +215,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
210 | else | 215 | else |
211 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | 216 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; |
212 | } | 217 | } |
218 | if (!(ch_flags & NVM_CHANNEL_80MHZ)) | ||
219 | channel->flags |= IEEE80211_CHAN_NO_80MHZ; | ||
220 | if (!(ch_flags & NVM_CHANNEL_160MHZ)) | ||
221 | channel->flags |= IEEE80211_CHAN_NO_160MHZ; | ||
213 | 222 | ||
214 | if (!(ch_flags & NVM_CHANNEL_IBSS)) | 223 | if (!(ch_flags & NVM_CHANNEL_IBSS)) |
215 | channel->flags |= IEEE80211_CHAN_NO_IBSS; | 224 | channel->flags |= IEEE80211_CHAN_NO_IBSS; |
@@ -245,6 +254,43 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
245 | return n_channels; | 254 | return n_channels; |
246 | } | 255 | } |
247 | 256 | ||
257 | static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | ||
258 | struct iwl_nvm_data *data, | ||
259 | struct ieee80211_sta_vht_cap *vht_cap) | ||
260 | { | ||
261 | /* For now, assume new devices with NVM are VHT capable */ | ||
262 | |||
263 | vht_cap->vht_supported = true; | ||
264 | |||
265 | vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
266 | IEEE80211_VHT_CAP_RXSTBC_1 | | ||
267 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | | ||
268 | 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | ||
269 | |||
270 | if (iwlwifi_mod_params.amsdu_size_8K) | ||
271 | vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; | ||
272 | |||
273 | vht_cap->vht_mcs.rx_mcs_map = | ||
274 | cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | | ||
275 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | | ||
276 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | | ||
277 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | | ||
278 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | | ||
279 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | | ||
280 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | | ||
281 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); | ||
282 | |||
283 | if (data->valid_rx_ant == 1 || cfg->rx_with_siso_diversity) { | ||
284 | vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | | ||
285 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; | ||
286 | /* this works because NOT_SUPPORTED == 3 */ | ||
287 | vht_cap->vht_mcs.rx_mcs_map |= | ||
288 | cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2); | ||
289 | } | ||
290 | |||
291 | vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; | ||
292 | } | ||
293 | |||
248 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | 294 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, |
249 | struct iwl_nvm_data *data, const __le16 *nvm_sw) | 295 | struct iwl_nvm_data *data, const __le16 *nvm_sw) |
250 | { | 296 | { |
@@ -268,6 +314,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
268 | n_used += iwl_init_sband_channels(data, sband, n_channels, | 314 | n_used += iwl_init_sband_channels(data, sband, n_channels, |
269 | IEEE80211_BAND_5GHZ); | 315 | IEEE80211_BAND_5GHZ); |
270 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); | 316 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); |
317 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap); | ||
271 | 318 | ||
272 | if (n_channels != n_used) | 319 | if (n_channels != n_used) |
273 | IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", | 320 | IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", |
@@ -343,4 +390,4 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | |||
343 | 390 | ||
344 | return data; | 391 | return data; |
345 | } | 392 | } |
346 | EXPORT_SYMBOL_GPL(iwl_parse_nvm_data); | 393 | IWL_EXPORT_SYMBOL(iwl_parse_nvm_data); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h index b2692bd287fa..e57fb989661e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index 4a680019e117..98c7aa7346da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c index 14fc8d39fc28..25745daa0d5d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -65,6 +65,7 @@ | |||
65 | #include <linux/string.h> | 65 | #include <linux/string.h> |
66 | #include <linux/export.h> | 66 | #include <linux/export.h> |
67 | 67 | ||
68 | #include "iwl-drv.h" | ||
68 | #include "iwl-phy-db.h" | 69 | #include "iwl-phy-db.h" |
69 | #include "iwl-debug.h" | 70 | #include "iwl-debug.h" |
70 | #include "iwl-op-mode.h" | 71 | #include "iwl-op-mode.h" |
@@ -136,12 +137,6 @@ struct iwl_calib_res_notif_phy_db { | |||
136 | u8 data[]; | 137 | u8 data[]; |
137 | } __packed; | 138 | } __packed; |
138 | 139 | ||
139 | #define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587) | ||
140 | static inline void iwl_phy_db_test_pic(__le32 pic) | ||
141 | { | ||
142 | WARN_ON(IWL_PHY_DB_STATIC_PIC != pic); | ||
143 | } | ||
144 | |||
145 | struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) | 140 | struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) |
146 | { | 141 | { |
147 | struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db), | 142 | struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db), |
@@ -155,7 +150,7 @@ struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) | |||
155 | /* TODO: add default values of the phy db. */ | 150 | /* TODO: add default values of the phy db. */ |
156 | return phy_db; | 151 | return phy_db; |
157 | } | 152 | } |
158 | EXPORT_SYMBOL(iwl_phy_db_init); | 153 | IWL_EXPORT_SYMBOL(iwl_phy_db_init); |
159 | 154 | ||
160 | /* | 155 | /* |
161 | * get phy db section: returns a pointer to a phy db section specified by | 156 | * get phy db section: returns a pointer to a phy db section specified by |
@@ -221,7 +216,7 @@ void iwl_phy_db_free(struct iwl_phy_db *phy_db) | |||
221 | 216 | ||
222 | kfree(phy_db); | 217 | kfree(phy_db); |
223 | } | 218 | } |
224 | EXPORT_SYMBOL(iwl_phy_db_free); | 219 | IWL_EXPORT_SYMBOL(iwl_phy_db_free); |
225 | 220 | ||
226 | int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, | 221 | int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, |
227 | gfp_t alloc_ctx) | 222 | gfp_t alloc_ctx) |
@@ -260,18 +255,13 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, | |||
260 | (size - CHANNEL_NUM_SIZE) / phy_db->channel_num; | 255 | (size - CHANNEL_NUM_SIZE) / phy_db->channel_num; |
261 | } | 256 | } |
262 | 257 | ||
263 | /* Test PIC */ | ||
264 | if (type != IWL_PHY_DB_CFG) | ||
265 | iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) + | ||
266 | (size / sizeof(__le32)) - 1)); | ||
267 | |||
268 | IWL_DEBUG_INFO(phy_db->trans, | 258 | IWL_DEBUG_INFO(phy_db->trans, |
269 | "%s(%d): [PHYDB]SET: Type %d , Size: %d\n", | 259 | "%s(%d): [PHYDB]SET: Type %d , Size: %d\n", |
270 | __func__, __LINE__, type, size); | 260 | __func__, __LINE__, type, size); |
271 | 261 | ||
272 | return 0; | 262 | return 0; |
273 | } | 263 | } |
274 | EXPORT_SYMBOL(iwl_phy_db_set_section); | 264 | IWL_EXPORT_SYMBOL(iwl_phy_db_set_section); |
275 | 265 | ||
276 | static int is_valid_channel(u16 ch_id) | 266 | static int is_valid_channel(u16 ch_id) |
277 | { | 267 | { |
@@ -372,11 +362,6 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, | |||
372 | *size = entry->size; | 362 | *size = entry->size; |
373 | } | 363 | } |
374 | 364 | ||
375 | /* Test PIC */ | ||
376 | if (type != IWL_PHY_DB_CFG) | ||
377 | iwl_phy_db_test_pic(*(((__le32 *)*data) + | ||
378 | (*size / sizeof(__le32)) - 1)); | ||
379 | |||
380 | IWL_DEBUG_INFO(phy_db->trans, | 365 | IWL_DEBUG_INFO(phy_db->trans, |
381 | "%s(%d): [PHYDB] GET: Type %d , Size: %d\n", | 366 | "%s(%d): [PHYDB] GET: Type %d , Size: %d\n", |
382 | __func__, __LINE__, type, *size); | 367 | __func__, __LINE__, type, *size); |
@@ -511,4 +496,4 @@ int iwl_send_phy_db_data(struct iwl_phy_db *phy_db) | |||
511 | "Finished sending phy db non channel data\n"); | 496 | "Finished sending phy db non channel data\n"); |
512 | return 0; | 497 | return 0; |
513 | } | 498 | } |
514 | EXPORT_SYMBOL(iwl_send_phy_db_data); | 499 | IWL_EXPORT_SYMBOL(iwl_send_phy_db_data); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.h b/drivers/net/wireless/iwlwifi/iwl-phy-db.h index d0e43d96ab38..ce983af79644 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.h +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index f76e9cad7757..386f2a7c87cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.c b/drivers/net/wireless/iwlwifi/iwl-test.c index ce0c67b425ee..5cfd55b86ed3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-test.c +++ b/drivers/net/wireless/iwlwifi/iwl-test.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
65 | #include <net/netlink.h> | 65 | #include <net/netlink.h> |
66 | 66 | ||
67 | #include "iwl-drv.h" | ||
67 | #include "iwl-io.h" | 68 | #include "iwl-io.h" |
68 | #include "iwl-fh.h" | 69 | #include "iwl-fh.h" |
69 | #include "iwl-prph.h" | 70 | #include "iwl-prph.h" |
@@ -271,7 +272,7 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb) | |||
271 | 272 | ||
272 | reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 273 | reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
273 | skb = iwl_test_alloc_reply(tst, reply_len + 20); | 274 | skb = iwl_test_alloc_reply(tst, reply_len + 20); |
274 | reply_buf = kmalloc(reply_len, GFP_KERNEL); | 275 | reply_buf = kmemdup(&pkt->hdr, reply_len, GFP_KERNEL); |
275 | if (!skb || !reply_buf) { | 276 | if (!skb || !reply_buf) { |
276 | kfree_skb(skb); | 277 | kfree_skb(skb); |
277 | kfree(reply_buf); | 278 | kfree(reply_buf); |
@@ -279,7 +280,6 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb) | |||
279 | } | 280 | } |
280 | 281 | ||
281 | /* The reply is in a page, that we cannot send to user space. */ | 282 | /* The reply is in a page, that we cannot send to user space. */ |
282 | memcpy(reply_buf, &(pkt->hdr), reply_len); | ||
283 | iwl_free_resp(&cmd); | 283 | iwl_free_resp(&cmd); |
284 | 284 | ||
285 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | 285 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, |
@@ -653,7 +653,7 @@ int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb, | |||
653 | } | 653 | } |
654 | return 0; | 654 | return 0; |
655 | } | 655 | } |
656 | EXPORT_SYMBOL_GPL(iwl_test_parse); | 656 | IWL_EXPORT_SYMBOL(iwl_test_parse); |
657 | 657 | ||
658 | /* | 658 | /* |
659 | * Handle test commands. | 659 | * Handle test commands. |
@@ -715,7 +715,7 @@ int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb) | |||
715 | } | 715 | } |
716 | return result; | 716 | return result; |
717 | } | 717 | } |
718 | EXPORT_SYMBOL_GPL(iwl_test_handle_cmd); | 718 | IWL_EXPORT_SYMBOL(iwl_test_handle_cmd); |
719 | 719 | ||
720 | static int iwl_test_trace_dump(struct iwl_test *tst, struct sk_buff *skb, | 720 | static int iwl_test_trace_dump(struct iwl_test *tst, struct sk_buff *skb, |
721 | struct netlink_callback *cb) | 721 | struct netlink_callback *cb) |
@@ -803,7 +803,7 @@ int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb, | |||
803 | } | 803 | } |
804 | return result; | 804 | return result; |
805 | } | 805 | } |
806 | EXPORT_SYMBOL_GPL(iwl_test_dump); | 806 | IWL_EXPORT_SYMBOL(iwl_test_dump); |
807 | 807 | ||
808 | /* | 808 | /* |
809 | * Multicast a spontaneous messages from the device to the user space. | 809 | * Multicast a spontaneous messages from the device to the user space. |
@@ -849,4 +849,4 @@ void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb) | |||
849 | if (tst->notify) | 849 | if (tst->notify) |
850 | iwl_test_send_rx(tst, rxb); | 850 | iwl_test_send_rx(tst, rxb); |
851 | } | 851 | } |
852 | EXPORT_SYMBOL_GPL(iwl_test_rx); | 852 | IWL_EXPORT_SYMBOL(iwl_test_rx); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.h b/drivers/net/wireless/iwlwifi/iwl-test.h index 7fbf4d717caa..8fbd21704840 100644 --- a/drivers/net/wireless/iwlwifi/iwl-test.h +++ b/drivers/net/wireless/iwlwifi/iwl-test.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index a963f45c6849..98f48a9afc98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 00bdc5b00af3..7a13790b5bfe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -183,19 +183,13 @@ struct iwl_rx_packet { | |||
183 | * @CMD_ASYNC: Return right away and don't want for the response | 183 | * @CMD_ASYNC: Return right away and don't want for the response |
184 | * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the | 184 | * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the |
185 | * response. The caller needs to call iwl_free_resp when done. | 185 | * response. The caller needs to call iwl_free_resp when done. |
186 | * @CMD_WANT_HCMD: The caller needs to get the HCMD that was sent in the | ||
187 | * response handler. Chunks flagged by %IWL_HCMD_DFL_NOCOPY won't be | ||
188 | * copied. The pointer passed to the response handler is in the transport | ||
189 | * ownership and don't need to be freed by the op_mode. This also means | ||
190 | * that the pointer is invalidated after the op_mode's handler returns. | ||
191 | * @CMD_ON_DEMAND: This command is sent by the test mode pipe. | 186 | * @CMD_ON_DEMAND: This command is sent by the test mode pipe. |
192 | */ | 187 | */ |
193 | enum CMD_MODE { | 188 | enum CMD_MODE { |
194 | CMD_SYNC = 0, | 189 | CMD_SYNC = 0, |
195 | CMD_ASYNC = BIT(0), | 190 | CMD_ASYNC = BIT(0), |
196 | CMD_WANT_SKB = BIT(1), | 191 | CMD_WANT_SKB = BIT(1), |
197 | CMD_WANT_HCMD = BIT(2), | 192 | CMD_ON_DEMAND = BIT(2), |
198 | CMD_ON_DEMAND = BIT(3), | ||
199 | }; | 193 | }; |
200 | 194 | ||
201 | #define DEF_CMD_PAYLOAD_SIZE 320 | 195 | #define DEF_CMD_PAYLOAD_SIZE 320 |
@@ -214,7 +208,11 @@ struct iwl_device_cmd { | |||
214 | 208 | ||
215 | #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) | 209 | #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) |
216 | 210 | ||
217 | #define IWL_MAX_CMD_TFDS 2 | 211 | /* |
212 | * number of transfer buffers (fragments) per transmit frame descriptor; | ||
213 | * this is just the driver's idea, the hardware supports 20 | ||
214 | */ | ||
215 | #define IWL_MAX_CMD_TBS_PER_TFD 2 | ||
218 | 216 | ||
219 | /** | 217 | /** |
220 | * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command | 218 | * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command |
@@ -251,15 +249,15 @@ enum iwl_hcmd_dataflag { | |||
251 | * @id: id of the host command | 249 | * @id: id of the host command |
252 | */ | 250 | */ |
253 | struct iwl_host_cmd { | 251 | struct iwl_host_cmd { |
254 | const void *data[IWL_MAX_CMD_TFDS]; | 252 | const void *data[IWL_MAX_CMD_TBS_PER_TFD]; |
255 | struct iwl_rx_packet *resp_pkt; | 253 | struct iwl_rx_packet *resp_pkt; |
256 | unsigned long _rx_page_addr; | 254 | unsigned long _rx_page_addr; |
257 | u32 _rx_page_order; | 255 | u32 _rx_page_order; |
258 | int handler_status; | 256 | int handler_status; |
259 | 257 | ||
260 | u32 flags; | 258 | u32 flags; |
261 | u16 len[IWL_MAX_CMD_TFDS]; | 259 | u16 len[IWL_MAX_CMD_TBS_PER_TFD]; |
262 | u8 dataflags[IWL_MAX_CMD_TFDS]; | 260 | u8 dataflags[IWL_MAX_CMD_TBS_PER_TFD]; |
263 | u8 id; | 261 | u8 id; |
264 | }; | 262 | }; |
265 | 263 | ||
@@ -307,7 +305,6 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r) | |||
307 | * currently supports | 305 | * currently supports |
308 | */ | 306 | */ |
309 | #define IWL_MAX_HW_QUEUES 32 | 307 | #define IWL_MAX_HW_QUEUES 32 |
310 | #define IWL_INVALID_STATION 255 | ||
311 | #define IWL_MAX_TID_COUNT 8 | 308 | #define IWL_MAX_TID_COUNT 8 |
312 | #define IWL_FRAME_LIMIT 64 | 309 | #define IWL_FRAME_LIMIT 64 |
313 | 310 | ||
@@ -684,7 +681,7 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | |||
684 | static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, | 681 | static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, |
685 | int fifo) | 682 | int fifo) |
686 | { | 683 | { |
687 | iwl_trans_txq_enable(trans, queue, fifo, IWL_INVALID_STATION, | 684 | iwl_trans_txq_enable(trans, queue, fifo, -1, |
688 | IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0); | 685 | IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0); |
689 | } | 686 | } |
690 | 687 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile index 807b250ec396..2acc44b40986 100644 --- a/drivers/net/wireless/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/iwlwifi/mvm/Makefile | |||
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o | |||
2 | iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o | 2 | iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o |
3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o | 3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o |
4 | iwlmvm-y += scan.o time-event.o rs.o | 4 | iwlmvm-y += scan.o time-event.o rs.o |
5 | iwlmvm-y += power.o | 5 | iwlmvm-y += power.o bt-coex.o |
6 | iwlmvm-y += led.o | 6 | iwlmvm-y += led.o |
7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o | 7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o |
8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o | 8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o |
diff --git a/drivers/net/wireless/iwlwifi/mvm/binding.c b/drivers/net/wireless/iwlwifi/mvm/binding.c index 73d24aacb90a..93fd1457954b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/binding.c +++ b/drivers/net/wireless/iwlwifi/mvm/binding.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c new file mode 100644 index 000000000000..810bfa5f6de0 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c | |||
@@ -0,0 +1,589 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called COPYING. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #include <net/mac80211.h> | ||
65 | |||
66 | #include "fw-api-bt-coex.h" | ||
67 | #include "iwl-modparams.h" | ||
68 | #include "mvm.h" | ||
69 | #include "iwl-debug.h" | ||
70 | |||
71 | #define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant) \ | ||
72 | [(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) | \ | ||
73 | ((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS)) | ||
74 | |||
75 | static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | ||
76 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1, | ||
77 | BT_COEX_PRIO_TBL_PRIO_BYPASS, 0), | ||
78 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2, | ||
79 | BT_COEX_PRIO_TBL_PRIO_BYPASS, 1), | ||
80 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1, | ||
81 | BT_COEX_PRIO_TBL_PRIO_LOW, 0), | ||
82 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2, | ||
83 | BT_COEX_PRIO_TBL_PRIO_LOW, 1), | ||
84 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1, | ||
85 | BT_COEX_PRIO_TBL_PRIO_HIGH, 0), | ||
86 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2, | ||
87 | BT_COEX_PRIO_TBL_PRIO_HIGH, 1), | ||
88 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM, | ||
89 | BT_COEX_PRIO_TBL_DISABLED, 0), | ||
90 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52, | ||
91 | BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0), | ||
92 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24, | ||
93 | BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0), | ||
94 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE, | ||
95 | BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0), | ||
96 | 0, 0, 0, 0, 0, 0, | ||
97 | }; | ||
98 | |||
99 | #undef EVENT_PRIO_ANT | ||
100 | |||
101 | /* BT Antenna Coupling Threshold (dB) */ | ||
102 | #define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) | ||
103 | #define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3) | ||
104 | |||
105 | #define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62) | ||
106 | #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65) | ||
107 | #define BT_REDUCED_TX_POWER_BIT BIT(7) | ||
108 | |||
109 | static inline bool is_loose_coex(void) | ||
110 | { | ||
111 | return iwlwifi_mod_params.ant_coupling > | ||
112 | IWL_BT_ANTENNA_COUPLING_THRESHOLD; | ||
113 | } | ||
114 | |||
115 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) | ||
116 | { | ||
117 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, | ||
118 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), | ||
119 | &iwl_bt_prio_tbl); | ||
120 | } | ||
121 | |||
122 | static int iwl_send_bt_env(struct iwl_mvm *mvm, u8 action, u8 type) | ||
123 | { | ||
124 | struct iwl_bt_coex_prot_env_cmd env_cmd; | ||
125 | int ret; | ||
126 | |||
127 | env_cmd.action = action; | ||
128 | env_cmd.type = type; | ||
129 | ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PROT_ENV, CMD_SYNC, | ||
130 | sizeof(env_cmd), &env_cmd); | ||
131 | if (ret) | ||
132 | IWL_ERR(mvm, "failed to send BT env command\n"); | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | enum iwl_bt_kill_msk { | ||
137 | BT_KILL_MSK_DEFAULT, | ||
138 | BT_KILL_MSK_SCO_HID_A2DP, | ||
139 | BT_KILL_MSK_REDUCED_TXPOW, | ||
140 | BT_KILL_MSK_MAX, | ||
141 | }; | ||
142 | |||
143 | static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { | ||
144 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, | ||
145 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, | ||
146 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, | ||
147 | }; | ||
148 | |||
149 | static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { | ||
150 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, | ||
151 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, | ||
152 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, | ||
153 | }; | ||
154 | |||
155 | #define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0) | ||
156 | |||
157 | /* Tight Coex */ | ||
158 | static const __le32 iwl_tight_lookup[BT_COEX_LUT_SIZE] = { | ||
159 | cpu_to_le32(0xaaaaaaaa), | ||
160 | cpu_to_le32(0xaaaaaaaa), | ||
161 | cpu_to_le32(0xaeaaaaaa), | ||
162 | cpu_to_le32(0xaaaaaaaa), | ||
163 | cpu_to_le32(0xcc00ff28), | ||
164 | cpu_to_le32(0x0000aaaa), | ||
165 | cpu_to_le32(0xcc00aaaa), | ||
166 | cpu_to_le32(0x0000aaaa), | ||
167 | cpu_to_le32(0xc0004000), | ||
168 | cpu_to_le32(0x00000000), | ||
169 | cpu_to_le32(0xf0005000), | ||
170 | cpu_to_le32(0xf0005000), | ||
171 | }; | ||
172 | |||
173 | /* Loose Coex */ | ||
174 | static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = { | ||
175 | cpu_to_le32(0xaaaaaaaa), | ||
176 | cpu_to_le32(0xaaaaaaaa), | ||
177 | cpu_to_le32(0xaeaaaaaa), | ||
178 | cpu_to_le32(0xaaaaaaaa), | ||
179 | cpu_to_le32(0xcc00ff28), | ||
180 | cpu_to_le32(0x0000aaaa), | ||
181 | cpu_to_le32(0xcc00aaaa), | ||
182 | cpu_to_le32(0x0000aaaa), | ||
183 | cpu_to_le32(0x00000000), | ||
184 | cpu_to_le32(0x00000000), | ||
185 | cpu_to_le32(0xf0005000), | ||
186 | cpu_to_le32(0xf0005000), | ||
187 | }; | ||
188 | |||
189 | /* Full concurrency */ | ||
190 | static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = { | ||
191 | cpu_to_le32(0xaaaaaaaa), | ||
192 | cpu_to_le32(0xaaaaaaaa), | ||
193 | cpu_to_le32(0xaaaaaaaa), | ||
194 | cpu_to_le32(0xaaaaaaaa), | ||
195 | cpu_to_le32(0xaaaaaaaa), | ||
196 | cpu_to_le32(0xaaaaaaaa), | ||
197 | cpu_to_le32(0xaaaaaaaa), | ||
198 | cpu_to_le32(0xaaaaaaaa), | ||
199 | cpu_to_le32(0x00000000), | ||
200 | cpu_to_le32(0x00000000), | ||
201 | cpu_to_le32(0x00000000), | ||
202 | cpu_to_le32(0x00000000), | ||
203 | }; | ||
204 | |||
205 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | ||
206 | { | ||
207 | struct iwl_bt_coex_cmd cmd = { | ||
208 | .max_kill = 5, | ||
209 | .bt3_time_t7_value = 1, | ||
210 | .bt3_prio_sample_time = 2, | ||
211 | .bt3_timer_t2_value = 0xc, | ||
212 | }; | ||
213 | int ret; | ||
214 | |||
215 | cmd.flags = iwlwifi_mod_params.bt_coex_active ? | ||
216 | BT_COEX_NW : BT_COEX_DISABLE; | ||
217 | cmd.flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE; | ||
218 | |||
219 | cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | | ||
220 | BT_VALID_BT_PRIO_BOOST | | ||
221 | BT_VALID_MAX_KILL | | ||
222 | BT_VALID_3W_TMRS | | ||
223 | BT_VALID_KILL_ACK | | ||
224 | BT_VALID_KILL_CTS | | ||
225 | BT_VALID_REDUCED_TX_POWER | | ||
226 | BT_VALID_LUT); | ||
227 | |||
228 | if (is_loose_coex()) | ||
229 | memcpy(&cmd.decision_lut, iwl_loose_lookup, | ||
230 | sizeof(iwl_tight_lookup)); | ||
231 | else | ||
232 | memcpy(&cmd.decision_lut, iwl_tight_lookup, | ||
233 | sizeof(iwl_tight_lookup)); | ||
234 | |||
235 | cmd.bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST); | ||
236 | cmd.kill_ack_msk = | ||
237 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); | ||
238 | cmd.kill_cts_msk = | ||
239 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); | ||
240 | |||
241 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | ||
242 | |||
243 | /* go to CALIB state in internal BT-Coex state machine */ | ||
244 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN, | ||
245 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
246 | if (ret) | ||
247 | return ret; | ||
248 | |||
249 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE, | ||
250 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
251 | if (ret) | ||
252 | return ret; | ||
253 | |||
254 | return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, | ||
255 | sizeof(cmd), &cmd); | ||
256 | } | ||
257 | |||
258 | static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | ||
259 | bool reduced_tx_power) | ||
260 | { | ||
261 | enum iwl_bt_kill_msk bt_kill_msk; | ||
262 | struct iwl_bt_coex_cmd cmd = {}; | ||
263 | struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; | ||
264 | |||
265 | lockdep_assert_held(&mvm->mutex); | ||
266 | |||
267 | if (reduced_tx_power) { | ||
268 | /* Reduced Tx power has precedence on the type of the profile */ | ||
269 | bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW; | ||
270 | } else { | ||
271 | /* Low latency BT profile is active: give higher prio to BT */ | ||
272 | if (BT_MBOX_MSG(notif, 3, SCO_STATE) || | ||
273 | BT_MBOX_MSG(notif, 3, A2DP_STATE) || | ||
274 | BT_MBOX_MSG(notif, 3, SNIFF_STATE)) | ||
275 | bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP; | ||
276 | else | ||
277 | bt_kill_msk = BT_KILL_MSK_DEFAULT; | ||
278 | } | ||
279 | |||
280 | IWL_DEBUG_COEX(mvm, | ||
281 | "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n", | ||
282 | bt_kill_msk, | ||
283 | BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in", | ||
284 | BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in", | ||
285 | BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in"); | ||
286 | |||
287 | /* Don't send HCMD if there is no update */ | ||
288 | if (bt_kill_msk == mvm->bt_kill_msk) | ||
289 | return 0; | ||
290 | |||
291 | mvm->bt_kill_msk = bt_kill_msk; | ||
292 | cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); | ||
293 | cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); | ||
294 | cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS); | ||
295 | |||
296 | IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk); | ||
297 | return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, | ||
298 | sizeof(cmd), &cmd); | ||
299 | } | ||
300 | |||
301 | static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | ||
302 | bool enable) | ||
303 | { | ||
304 | struct iwl_bt_coex_cmd cmd = { | ||
305 | .valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER), | ||
306 | .bt_reduced_tx_power = sta_id, | ||
307 | }; | ||
308 | struct ieee80211_sta *sta; | ||
309 | struct iwl_mvm_sta *mvmsta; | ||
310 | |||
311 | /* This can happen if the station has been removed right now */ | ||
312 | if (sta_id == IWL_MVM_STATION_COUNT) | ||
313 | return 0; | ||
314 | |||
315 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], | ||
316 | lockdep_is_held(&mvm->mutex)); | ||
317 | mvmsta = (void *)sta->drv_priv; | ||
318 | |||
319 | /* nothing to do */ | ||
320 | if (mvmsta->bt_reduced_txpower == enable) | ||
321 | return 0; | ||
322 | |||
323 | if (enable) | ||
324 | cmd.bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT; | ||
325 | |||
326 | IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n", | ||
327 | enable ? "en" : "dis", sta_id); | ||
328 | |||
329 | mvmsta->bt_reduced_txpower = enable; | ||
330 | |||
331 | /* Send ASYNC since this can be sent from an atomic context */ | ||
332 | return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_ASYNC, | ||
333 | sizeof(cmd), &cmd); | ||
334 | } | ||
335 | |||
336 | struct iwl_bt_iterator_data { | ||
337 | struct iwl_bt_coex_profile_notif *notif; | ||
338 | struct iwl_mvm *mvm; | ||
339 | u32 num_bss_ifaces; | ||
340 | bool reduced_tx_power; | ||
341 | }; | ||
342 | |||
343 | static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | ||
344 | struct ieee80211_vif *vif) | ||
345 | { | ||
346 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
347 | struct iwl_bt_iterator_data *data = _data; | ||
348 | struct iwl_mvm *mvm = data->mvm; | ||
349 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
350 | enum ieee80211_smps_mode smps_mode; | ||
351 | enum ieee80211_band band; | ||
352 | int ave_rssi; | ||
353 | |||
354 | if (vif->type != NL80211_IFTYPE_STATION) | ||
355 | return; | ||
356 | |||
357 | rcu_read_lock(); | ||
358 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
359 | if (chanctx_conf && chanctx_conf->def.chan) | ||
360 | band = chanctx_conf->def.chan->band; | ||
361 | else | ||
362 | band = -1; | ||
363 | rcu_read_unlock(); | ||
364 | |||
365 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | ||
366 | |||
367 | if (band != IEEE80211_BAND_2GHZ) { | ||
368 | ieee80211_request_smps(vif, smps_mode); | ||
369 | return; | ||
370 | } | ||
371 | |||
372 | if (data->notif->bt_status) | ||
373 | smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
374 | |||
375 | if (data->notif->bt_traffic_load >= IWL_BT_LOAD_FORCE_SISO_THRESHOLD) | ||
376 | smps_mode = IEEE80211_SMPS_STATIC; | ||
377 | |||
378 | IWL_DEBUG_COEX(data->mvm, | ||
379 | "mac %d: bt_status %d traffic_load %d smps_req %d\n", | ||
380 | mvmvif->id, data->notif->bt_status, | ||
381 | data->notif->bt_traffic_load, smps_mode); | ||
382 | |||
383 | ieee80211_request_smps(vif, smps_mode); | ||
384 | |||
385 | /* don't reduce the Tx power if in loose scheme */ | ||
386 | if (is_loose_coex()) | ||
387 | return; | ||
388 | |||
389 | data->num_bss_ifaces++; | ||
390 | |||
391 | /* reduced Txpower only if there are open BT connections, so ...*/ | ||
392 | if (!BT_MBOX_MSG(data->notif, 3, OPEN_CON_2)) { | ||
393 | /* ... cancel reduced Tx power ... */ | ||
394 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) | ||
395 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | ||
396 | data->reduced_tx_power = false; | ||
397 | |||
398 | /* ... and there is no need to get reports on RSSI any more. */ | ||
399 | ieee80211_disable_rssi_reports(vif); | ||
400 | return; | ||
401 | } | ||
402 | |||
403 | ave_rssi = ieee80211_ave_rssi(vif); | ||
404 | |||
405 | /* if the RSSI isn't valid, fake it is very low */ | ||
406 | if (!ave_rssi) | ||
407 | ave_rssi = -100; | ||
408 | if (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) { | ||
409 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) | ||
410 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | ||
411 | |||
412 | /* | ||
413 | * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the | ||
414 | * BSS / P2P clients have rssi above threshold. | ||
415 | * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before | ||
416 | * the iteration, if one interface's rssi isn't good enough, | ||
417 | * bt_kill_msk will be set to default values. | ||
418 | */ | ||
419 | } else if (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) { | ||
420 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) | ||
421 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | ||
422 | |||
423 | /* | ||
424 | * One interface hasn't rssi above threshold, bt_kill_msk must | ||
425 | * be set to default values. | ||
426 | */ | ||
427 | data->reduced_tx_power = false; | ||
428 | } | ||
429 | |||
430 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ | ||
431 | ieee80211_enable_rssi_reports(vif, BT_DISABLE_REDUCED_TXPOWER_THRESHOLD, | ||
432 | BT_ENABLE_REDUCED_TXPOWER_THRESHOLD); | ||
433 | } | ||
434 | |||
435 | static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | ||
436 | { | ||
437 | struct iwl_bt_iterator_data data = { | ||
438 | .mvm = mvm, | ||
439 | .notif = &mvm->last_bt_notif, | ||
440 | .reduced_tx_power = true, | ||
441 | }; | ||
442 | |||
443 | ieee80211_iterate_active_interfaces_atomic( | ||
444 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
445 | iwl_mvm_bt_notif_iterator, &data); | ||
446 | |||
447 | /* | ||
448 | * If there are no BSS / P2P client interfaces, reduced Tx Power is | ||
449 | * irrelevant since it is based on the RSSI coming from the beacon. | ||
450 | * Use BT_KILL_MSK_DEFAULT in that case. | ||
451 | */ | ||
452 | data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces; | ||
453 | |||
454 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power)) | ||
455 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | ||
456 | } | ||
457 | |||
458 | /* upon association, the fw will send in BT Coex notification */ | ||
459 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | ||
460 | struct iwl_rx_cmd_buffer *rxb, | ||
461 | struct iwl_device_cmd *dev_cmd) | ||
462 | { | ||
463 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
464 | struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data; | ||
465 | |||
466 | |||
467 | IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); | ||
468 | IWL_DEBUG_COEX(mvm, "\tBT %salive\n", notif->bt_status ? "" : "not "); | ||
469 | IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn); | ||
470 | IWL_DEBUG_COEX(mvm, "\tBT traffic load %d\n", notif->bt_traffic_load); | ||
471 | IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n", | ||
472 | notif->bt_agg_traffic_load); | ||
473 | IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); | ||
474 | |||
475 | /* remember this notification for future use: rssi fluctuations */ | ||
476 | memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); | ||
477 | |||
478 | iwl_mvm_bt_coex_notif_handle(mvm); | ||
479 | |||
480 | /* | ||
481 | * This is an async handler for a notification, returning anything other | ||
482 | * than 0 doesn't make sense even if HCMD failed. | ||
483 | */ | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, | ||
488 | struct ieee80211_vif *vif) | ||
489 | { | ||
490 | struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; | ||
491 | struct iwl_bt_iterator_data *data = _data; | ||
492 | struct iwl_mvm *mvm = data->mvm; | ||
493 | |||
494 | struct ieee80211_sta *sta; | ||
495 | struct iwl_mvm_sta *mvmsta; | ||
496 | |||
497 | if (vif->type != NL80211_IFTYPE_STATION || | ||
498 | mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) | ||
499 | return; | ||
500 | |||
501 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], | ||
502 | lockdep_is_held(&mvm->mutex)); | ||
503 | mvmsta = (void *)sta->drv_priv; | ||
504 | |||
505 | /* | ||
506 | * This interface doesn't support reduced Tx power (because of low | ||
507 | * RSSI probably), then set bt_kill_msk to default values. | ||
508 | */ | ||
509 | if (!mvmsta->bt_reduced_txpower) | ||
510 | data->reduced_tx_power = false; | ||
511 | /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */ | ||
512 | } | ||
513 | |||
514 | void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
515 | enum ieee80211_rssi_event rssi_event) | ||
516 | { | ||
517 | struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; | ||
518 | struct iwl_bt_iterator_data data = { | ||
519 | .mvm = mvm, | ||
520 | .reduced_tx_power = true, | ||
521 | }; | ||
522 | int ret; | ||
523 | |||
524 | mutex_lock(&mvm->mutex); | ||
525 | |||
526 | /* Rssi update while not associated ?! */ | ||
527 | if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)) | ||
528 | goto out_unlock; | ||
529 | |||
530 | /* No open connection - reports should be disabled */ | ||
531 | if (!BT_MBOX_MSG(&mvm->last_bt_notif, 3, OPEN_CON_2)) | ||
532 | goto out_unlock; | ||
533 | |||
534 | IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid, | ||
535 | rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW"); | ||
536 | |||
537 | /* | ||
538 | * Check if rssi is good enough for reduced Tx power, but not in loose | ||
539 | * scheme. | ||
540 | */ | ||
541 | if (rssi_event == RSSI_EVENT_LOW || is_loose_coex()) | ||
542 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, | ||
543 | false); | ||
544 | else | ||
545 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true); | ||
546 | |||
547 | if (ret) | ||
548 | IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n"); | ||
549 | |||
550 | ieee80211_iterate_active_interfaces_atomic( | ||
551 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
552 | iwl_mvm_bt_rssi_iterator, &data); | ||
553 | |||
554 | /* | ||
555 | * If there are no BSS / P2P client interfaces, reduced Tx Power is | ||
556 | * irrelevant since it is based on the RSSI coming from the beacon. | ||
557 | * Use BT_KILL_MSK_DEFAULT in that case. | ||
558 | */ | ||
559 | data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces; | ||
560 | |||
561 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power)) | ||
562 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | ||
563 | |||
564 | out_unlock: | ||
565 | mutex_unlock(&mvm->mutex); | ||
566 | } | ||
567 | |||
568 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
569 | { | ||
570 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
571 | enum ieee80211_band band; | ||
572 | |||
573 | rcu_read_lock(); | ||
574 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
575 | if (chanctx_conf && chanctx_conf->def.chan) | ||
576 | band = chanctx_conf->def.chan->band; | ||
577 | else | ||
578 | band = -1; | ||
579 | rcu_read_unlock(); | ||
580 | |||
581 | /* if we are in 2GHz we will get a notification from the fw */ | ||
582 | if (band == IEEE80211_BAND_2GHZ) | ||
583 | return; | ||
584 | |||
585 | /* else, we can remove all the constraints */ | ||
586 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | ||
587 | |||
588 | iwl_mvm_bt_coex_notif_handle(mvm); | ||
589 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index c64d864799cd..16bbdcc8627a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -61,8 +61,11 @@ | |||
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | 63 | ||
64 | #include <linux/etherdevice.h> | ||
65 | #include <linux/ip.h> | ||
64 | #include <net/cfg80211.h> | 66 | #include <net/cfg80211.h> |
65 | #include <net/ipv6.h> | 67 | #include <net/ipv6.h> |
68 | #include <net/tcp.h> | ||
66 | #include "iwl-modparams.h" | 69 | #include "iwl-modparams.h" |
67 | #include "fw-api.h" | 70 | #include "fw-api.h" |
68 | #include "mvm.h" | 71 | #include "mvm.h" |
@@ -192,6 +195,11 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, | |||
192 | sizeof(wkc), &wkc); | 195 | sizeof(wkc), &wkc); |
193 | data->error = ret != 0; | 196 | data->error = ret != 0; |
194 | 197 | ||
198 | mvm->ptk_ivlen = key->iv_len; | ||
199 | mvm->ptk_icvlen = key->icv_len; | ||
200 | mvm->gtk_ivlen = key->iv_len; | ||
201 | mvm->gtk_icvlen = key->icv_len; | ||
202 | |||
195 | /* don't upload key again */ | 203 | /* don't upload key again */ |
196 | goto out_unlock; | 204 | goto out_unlock; |
197 | } | 205 | } |
@@ -304,9 +312,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, | |||
304 | */ | 312 | */ |
305 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { | 313 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { |
306 | key->hw_key_idx = 0; | 314 | key->hw_key_idx = 0; |
315 | mvm->ptk_ivlen = key->iv_len; | ||
316 | mvm->ptk_icvlen = key->icv_len; | ||
307 | } else { | 317 | } else { |
308 | data->gtk_key_idx++; | 318 | data->gtk_key_idx++; |
309 | key->hw_key_idx = data->gtk_key_idx; | 319 | key->hw_key_idx = data->gtk_key_idx; |
320 | mvm->gtk_ivlen = key->iv_len; | ||
321 | mvm->gtk_icvlen = key->icv_len; | ||
310 | } | 322 | } |
311 | 323 | ||
312 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true); | 324 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true); |
@@ -392,6 +404,233 @@ static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | |||
392 | sizeof(cmd), &cmd); | 404 | sizeof(cmd), &cmd); |
393 | } | 405 | } |
394 | 406 | ||
407 | enum iwl_mvm_tcp_packet_type { | ||
408 | MVM_TCP_TX_SYN, | ||
409 | MVM_TCP_RX_SYNACK, | ||
410 | MVM_TCP_TX_DATA, | ||
411 | MVM_TCP_RX_ACK, | ||
412 | MVM_TCP_RX_WAKE, | ||
413 | MVM_TCP_TX_FIN, | ||
414 | }; | ||
415 | |||
416 | static __le16 pseudo_hdr_check(int len, __be32 saddr, __be32 daddr) | ||
417 | { | ||
418 | __sum16 check = tcp_v4_check(len, saddr, daddr, 0); | ||
419 | return cpu_to_le16(be16_to_cpu((__force __be16)check)); | ||
420 | } | ||
421 | |||
422 | static void iwl_mvm_build_tcp_packet(struct iwl_mvm *mvm, | ||
423 | struct ieee80211_vif *vif, | ||
424 | struct cfg80211_wowlan_tcp *tcp, | ||
425 | void *_pkt, u8 *mask, | ||
426 | __le16 *pseudo_hdr_csum, | ||
427 | enum iwl_mvm_tcp_packet_type ptype) | ||
428 | { | ||
429 | struct { | ||
430 | struct ethhdr eth; | ||
431 | struct iphdr ip; | ||
432 | struct tcphdr tcp; | ||
433 | u8 data[]; | ||
434 | } __packed *pkt = _pkt; | ||
435 | u16 ip_tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr); | ||
436 | int i; | ||
437 | |||
438 | pkt->eth.h_proto = cpu_to_be16(ETH_P_IP), | ||
439 | pkt->ip.version = 4; | ||
440 | pkt->ip.ihl = 5; | ||
441 | pkt->ip.protocol = IPPROTO_TCP; | ||
442 | |||
443 | switch (ptype) { | ||
444 | case MVM_TCP_TX_SYN: | ||
445 | case MVM_TCP_TX_DATA: | ||
446 | case MVM_TCP_TX_FIN: | ||
447 | memcpy(pkt->eth.h_dest, tcp->dst_mac, ETH_ALEN); | ||
448 | memcpy(pkt->eth.h_source, vif->addr, ETH_ALEN); | ||
449 | pkt->ip.ttl = 128; | ||
450 | pkt->ip.saddr = tcp->src; | ||
451 | pkt->ip.daddr = tcp->dst; | ||
452 | pkt->tcp.source = cpu_to_be16(tcp->src_port); | ||
453 | pkt->tcp.dest = cpu_to_be16(tcp->dst_port); | ||
454 | /* overwritten for TX SYN later */ | ||
455 | pkt->tcp.doff = sizeof(struct tcphdr) / 4; | ||
456 | pkt->tcp.window = cpu_to_be16(65000); | ||
457 | break; | ||
458 | case MVM_TCP_RX_SYNACK: | ||
459 | case MVM_TCP_RX_ACK: | ||
460 | case MVM_TCP_RX_WAKE: | ||
461 | memcpy(pkt->eth.h_dest, vif->addr, ETH_ALEN); | ||
462 | memcpy(pkt->eth.h_source, tcp->dst_mac, ETH_ALEN); | ||
463 | pkt->ip.saddr = tcp->dst; | ||
464 | pkt->ip.daddr = tcp->src; | ||
465 | pkt->tcp.source = cpu_to_be16(tcp->dst_port); | ||
466 | pkt->tcp.dest = cpu_to_be16(tcp->src_port); | ||
467 | break; | ||
468 | default: | ||
469 | WARN_ON(1); | ||
470 | return; | ||
471 | } | ||
472 | |||
473 | switch (ptype) { | ||
474 | case MVM_TCP_TX_SYN: | ||
475 | /* firmware assumes 8 option bytes - 8 NOPs for now */ | ||
476 | memset(pkt->data, 0x01, 8); | ||
477 | ip_tot_len += 8; | ||
478 | pkt->tcp.doff = (sizeof(struct tcphdr) + 8) / 4; | ||
479 | pkt->tcp.syn = 1; | ||
480 | break; | ||
481 | case MVM_TCP_TX_DATA: | ||
482 | ip_tot_len += tcp->payload_len; | ||
483 | memcpy(pkt->data, tcp->payload, tcp->payload_len); | ||
484 | pkt->tcp.psh = 1; | ||
485 | pkt->tcp.ack = 1; | ||
486 | break; | ||
487 | case MVM_TCP_TX_FIN: | ||
488 | pkt->tcp.fin = 1; | ||
489 | pkt->tcp.ack = 1; | ||
490 | break; | ||
491 | case MVM_TCP_RX_SYNACK: | ||
492 | pkt->tcp.syn = 1; | ||
493 | pkt->tcp.ack = 1; | ||
494 | break; | ||
495 | case MVM_TCP_RX_ACK: | ||
496 | pkt->tcp.ack = 1; | ||
497 | break; | ||
498 | case MVM_TCP_RX_WAKE: | ||
499 | ip_tot_len += tcp->wake_len; | ||
500 | pkt->tcp.psh = 1; | ||
501 | pkt->tcp.ack = 1; | ||
502 | memcpy(pkt->data, tcp->wake_data, tcp->wake_len); | ||
503 | break; | ||
504 | } | ||
505 | |||
506 | switch (ptype) { | ||
507 | case MVM_TCP_TX_SYN: | ||
508 | case MVM_TCP_TX_DATA: | ||
509 | case MVM_TCP_TX_FIN: | ||
510 | pkt->ip.tot_len = cpu_to_be16(ip_tot_len); | ||
511 | pkt->ip.check = ip_fast_csum(&pkt->ip, pkt->ip.ihl); | ||
512 | break; | ||
513 | case MVM_TCP_RX_WAKE: | ||
514 | for (i = 0; i < DIV_ROUND_UP(tcp->wake_len, 8); i++) { | ||
515 | u8 tmp = tcp->wake_mask[i]; | ||
516 | mask[i + 6] |= tmp << 6; | ||
517 | if (i + 1 < DIV_ROUND_UP(tcp->wake_len, 8)) | ||
518 | mask[i + 7] = tmp >> 2; | ||
519 | } | ||
520 | /* fall through for ethernet/IP/TCP headers mask */ | ||
521 | case MVM_TCP_RX_SYNACK: | ||
522 | case MVM_TCP_RX_ACK: | ||
523 | mask[0] = 0xff; /* match ethernet */ | ||
524 | /* | ||
525 | * match ethernet, ip.version, ip.ihl | ||
526 | * the ip.ihl half byte is really masked out by firmware | ||
527 | */ | ||
528 | mask[1] = 0x7f; | ||
529 | mask[2] = 0x80; /* match ip.protocol */ | ||
530 | mask[3] = 0xfc; /* match ip.saddr, ip.daddr */ | ||
531 | mask[4] = 0x3f; /* match ip.daddr, tcp.source, tcp.dest */ | ||
532 | mask[5] = 0x80; /* match tcp flags */ | ||
533 | /* leave rest (0 or set for MVM_TCP_RX_WAKE) */ | ||
534 | break; | ||
535 | }; | ||
536 | |||
537 | *pseudo_hdr_csum = pseudo_hdr_check(ip_tot_len - sizeof(struct iphdr), | ||
538 | pkt->ip.saddr, pkt->ip.daddr); | ||
539 | } | ||
540 | |||
541 | static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm, | ||
542 | struct ieee80211_vif *vif, | ||
543 | struct cfg80211_wowlan_tcp *tcp) | ||
544 | { | ||
545 | struct iwl_wowlan_remote_wake_config *cfg; | ||
546 | struct iwl_host_cmd cmd = { | ||
547 | .id = REMOTE_WAKE_CONFIG_CMD, | ||
548 | .len = { sizeof(*cfg), }, | ||
549 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, | ||
550 | .flags = CMD_SYNC, | ||
551 | }; | ||
552 | int ret; | ||
553 | |||
554 | if (!tcp) | ||
555 | return 0; | ||
556 | |||
557 | cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); | ||
558 | if (!cfg) | ||
559 | return -ENOMEM; | ||
560 | cmd.data[0] = cfg; | ||
561 | |||
562 | cfg->max_syn_retries = 10; | ||
563 | cfg->max_data_retries = 10; | ||
564 | cfg->tcp_syn_ack_timeout = 1; /* seconds */ | ||
565 | cfg->tcp_ack_timeout = 1; /* seconds */ | ||
566 | |||
567 | /* SYN (TX) */ | ||
568 | iwl_mvm_build_tcp_packet( | ||
569 | mvm, vif, tcp, cfg->syn_tx.data, NULL, | ||
570 | &cfg->syn_tx.info.tcp_pseudo_header_checksum, | ||
571 | MVM_TCP_TX_SYN); | ||
572 | cfg->syn_tx.info.tcp_payload_length = 0; | ||
573 | |||
574 | /* SYN/ACK (RX) */ | ||
575 | iwl_mvm_build_tcp_packet( | ||
576 | mvm, vif, tcp, cfg->synack_rx.data, cfg->synack_rx.rx_mask, | ||
577 | &cfg->synack_rx.info.tcp_pseudo_header_checksum, | ||
578 | MVM_TCP_RX_SYNACK); | ||
579 | cfg->synack_rx.info.tcp_payload_length = 0; | ||
580 | |||
581 | /* KEEPALIVE/ACK (TX) */ | ||
582 | iwl_mvm_build_tcp_packet( | ||
583 | mvm, vif, tcp, cfg->keepalive_tx.data, NULL, | ||
584 | &cfg->keepalive_tx.info.tcp_pseudo_header_checksum, | ||
585 | MVM_TCP_TX_DATA); | ||
586 | cfg->keepalive_tx.info.tcp_payload_length = | ||
587 | cpu_to_le16(tcp->payload_len); | ||
588 | cfg->sequence_number_offset = tcp->payload_seq.offset; | ||
589 | /* length must be 0..4, the field is little endian */ | ||
590 | cfg->sequence_number_length = tcp->payload_seq.len; | ||
591 | cfg->initial_sequence_number = cpu_to_le32(tcp->payload_seq.start); | ||
592 | cfg->keepalive_interval = cpu_to_le16(tcp->data_interval); | ||
593 | if (tcp->payload_tok.len) { | ||
594 | cfg->token_offset = tcp->payload_tok.offset; | ||
595 | cfg->token_length = tcp->payload_tok.len; | ||
596 | cfg->num_tokens = | ||
597 | cpu_to_le16(tcp->tokens_size % tcp->payload_tok.len); | ||
598 | memcpy(cfg->tokens, tcp->payload_tok.token_stream, | ||
599 | tcp->tokens_size); | ||
600 | } else { | ||
601 | /* set tokens to max value to almost never run out */ | ||
602 | cfg->num_tokens = cpu_to_le16(65535); | ||
603 | } | ||
604 | |||
605 | /* ACK (RX) */ | ||
606 | iwl_mvm_build_tcp_packet( | ||
607 | mvm, vif, tcp, cfg->keepalive_ack_rx.data, | ||
608 | cfg->keepalive_ack_rx.rx_mask, | ||
609 | &cfg->keepalive_ack_rx.info.tcp_pseudo_header_checksum, | ||
610 | MVM_TCP_RX_ACK); | ||
611 | cfg->keepalive_ack_rx.info.tcp_payload_length = 0; | ||
612 | |||
613 | /* WAKEUP (RX) */ | ||
614 | iwl_mvm_build_tcp_packet( | ||
615 | mvm, vif, tcp, cfg->wake_rx.data, cfg->wake_rx.rx_mask, | ||
616 | &cfg->wake_rx.info.tcp_pseudo_header_checksum, | ||
617 | MVM_TCP_RX_WAKE); | ||
618 | cfg->wake_rx.info.tcp_payload_length = | ||
619 | cpu_to_le16(tcp->wake_len); | ||
620 | |||
621 | /* FIN */ | ||
622 | iwl_mvm_build_tcp_packet( | ||
623 | mvm, vif, tcp, cfg->fin_tx.data, NULL, | ||
624 | &cfg->fin_tx.info.tcp_pseudo_header_checksum, | ||
625 | MVM_TCP_TX_FIN); | ||
626 | cfg->fin_tx.info.tcp_payload_length = 0; | ||
627 | |||
628 | ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
629 | kfree(cfg); | ||
630 | |||
631 | return ret; | ||
632 | } | ||
633 | |||
395 | struct iwl_d3_iter_data { | 634 | struct iwl_d3_iter_data { |
396 | struct iwl_mvm *mvm; | 635 | struct iwl_mvm *mvm; |
397 | struct ieee80211_vif *vif; | 636 | struct ieee80211_vif *vif; |
@@ -530,7 +769,14 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
530 | struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; | 769 | struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; |
531 | struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; | 770 | struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; |
532 | struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; | 771 | struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; |
533 | struct iwl_d3_manager_config d3_cfg_cmd = {}; | 772 | struct iwl_d3_manager_config d3_cfg_cmd = { |
773 | /* | ||
774 | * Program the minimum sleep time to 10 seconds, as many | ||
775 | * platforms have issues processing a wakeup signal while | ||
776 | * still being in the process of suspending. | ||
777 | */ | ||
778 | .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), | ||
779 | }; | ||
534 | struct wowlan_key_data key_data = { | 780 | struct wowlan_key_data key_data = { |
535 | .use_rsc_tsc = false, | 781 | .use_rsc_tsc = false, |
536 | .tkip = &tkip_cmd, | 782 | .tkip = &tkip_cmd, |
@@ -627,9 +873,21 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
627 | cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH); | 873 | cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH); |
628 | 874 | ||
629 | if (wowlan->rfkill_release) | 875 | if (wowlan->rfkill_release) |
630 | d3_cfg_cmd.wakeup_flags |= | 876 | wowlan_config_cmd.wakeup_filter |= |
631 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); | 877 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); |
632 | 878 | ||
879 | if (wowlan->tcp) { | ||
880 | /* | ||
881 | * Set the "link change" (really "link lost") flag as well | ||
882 | * since that implies losing the TCP connection. | ||
883 | */ | ||
884 | wowlan_config_cmd.wakeup_filter |= | ||
885 | cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS | | ||
886 | IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE | | ||
887 | IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET | | ||
888 | IWL_WOWLAN_WAKEUP_LINK_CHANGE); | ||
889 | } | ||
890 | |||
633 | iwl_mvm_cancel_scan(mvm); | 891 | iwl_mvm_cancel_scan(mvm); |
634 | 892 | ||
635 | iwl_trans_stop_device(mvm->trans); | 893 | iwl_trans_stop_device(mvm->trans); |
@@ -649,6 +907,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
649 | /* We reprogram keys and shouldn't allocate new key indices */ | 907 | /* We reprogram keys and shouldn't allocate new key indices */ |
650 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); | 908 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); |
651 | 909 | ||
910 | mvm->ptk_ivlen = 0; | ||
911 | mvm->ptk_icvlen = 0; | ||
912 | mvm->ptk_ivlen = 0; | ||
913 | mvm->ptk_icvlen = 0; | ||
914 | |||
652 | /* | 915 | /* |
653 | * The D3 firmware still hardcodes the AP station ID for the | 916 | * The D3 firmware still hardcodes the AP station ID for the |
654 | * BSS we're associated with as 0. As a result, we have to move | 917 | * BSS we're associated with as 0. As a result, we have to move |
@@ -740,6 +1003,10 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
740 | if (ret) | 1003 | if (ret) |
741 | goto out; | 1004 | goto out; |
742 | 1005 | ||
1006 | ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp); | ||
1007 | if (ret) | ||
1008 | goto out; | ||
1009 | |||
743 | /* must be last -- this switches firmware state */ | 1010 | /* must be last -- this switches firmware state */ |
744 | ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, | 1011 | ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, |
745 | sizeof(d3_cfg_cmd), &d3_cfg_cmd); | 1012 | sizeof(d3_cfg_cmd), &d3_cfg_cmd); |
@@ -783,7 +1050,6 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
783 | struct iwl_wowlan_status *status; | 1050 | struct iwl_wowlan_status *status; |
784 | u32 reasons; | 1051 | u32 reasons; |
785 | int ret, len; | 1052 | int ret, len; |
786 | bool pkt8023 = false; | ||
787 | struct sk_buff *pkt = NULL; | 1053 | struct sk_buff *pkt = NULL; |
788 | 1054 | ||
789 | iwl_trans_read_mem_bytes(mvm->trans, base, | 1055 | iwl_trans_read_mem_bytes(mvm->trans, base, |
@@ -824,7 +1090,8 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
824 | status = (void *)cmd.resp_pkt->data; | 1090 | status = (void *)cmd.resp_pkt->data; |
825 | 1091 | ||
826 | if (len - sizeof(struct iwl_cmd_header) != | 1092 | if (len - sizeof(struct iwl_cmd_header) != |
827 | sizeof(*status) + le32_to_cpu(status->wake_packet_bufsize)) { | 1093 | sizeof(*status) + |
1094 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) { | ||
828 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1095 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
829 | goto out; | 1096 | goto out; |
830 | } | 1097 | } |
@@ -836,61 +1103,105 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
836 | goto report; | 1103 | goto report; |
837 | } | 1104 | } |
838 | 1105 | ||
839 | if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) { | 1106 | if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) |
840 | wakeup.magic_pkt = true; | 1107 | wakeup.magic_pkt = true; |
841 | pkt8023 = true; | ||
842 | } | ||
843 | 1108 | ||
844 | if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) { | 1109 | if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) |
845 | wakeup.pattern_idx = | 1110 | wakeup.pattern_idx = |
846 | le16_to_cpu(status->pattern_number); | 1111 | le16_to_cpu(status->pattern_number); |
847 | pkt8023 = true; | ||
848 | } | ||
849 | 1112 | ||
850 | if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | | 1113 | if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | |
851 | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) | 1114 | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) |
852 | wakeup.disconnect = true; | 1115 | wakeup.disconnect = true; |
853 | 1116 | ||
854 | if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) { | 1117 | if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) |
855 | wakeup.gtk_rekey_failure = true; | 1118 | wakeup.gtk_rekey_failure = true; |
856 | pkt8023 = true; | ||
857 | } | ||
858 | 1119 | ||
859 | if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) { | 1120 | if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) |
860 | wakeup.rfkill_release = true; | 1121 | wakeup.rfkill_release = true; |
861 | pkt8023 = true; | ||
862 | } | ||
863 | 1122 | ||
864 | if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) { | 1123 | if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) |
865 | wakeup.eap_identity_req = true; | 1124 | wakeup.eap_identity_req = true; |
866 | pkt8023 = true; | ||
867 | } | ||
868 | 1125 | ||
869 | if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) { | 1126 | if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) |
870 | wakeup.four_way_handshake = true; | 1127 | wakeup.four_way_handshake = true; |
871 | pkt8023 = true; | 1128 | |
872 | } | 1129 | if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS) |
1130 | wakeup.tcp_connlost = true; | ||
1131 | |||
1132 | if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE) | ||
1133 | wakeup.tcp_nomoretokens = true; | ||
1134 | |||
1135 | if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET) | ||
1136 | wakeup.tcp_match = true; | ||
873 | 1137 | ||
874 | if (status->wake_packet_bufsize) { | 1138 | if (status->wake_packet_bufsize) { |
875 | u32 pktsize = le32_to_cpu(status->wake_packet_bufsize); | 1139 | int pktsize = le32_to_cpu(status->wake_packet_bufsize); |
876 | u32 pktlen = le32_to_cpu(status->wake_packet_length); | 1140 | int pktlen = le32_to_cpu(status->wake_packet_length); |
1141 | const u8 *pktdata = status->wake_packet; | ||
1142 | struct ieee80211_hdr *hdr = (void *)pktdata; | ||
1143 | int truncated = pktlen - pktsize; | ||
1144 | |||
1145 | /* this would be a firmware bug */ | ||
1146 | if (WARN_ON_ONCE(truncated < 0)) | ||
1147 | truncated = 0; | ||
1148 | |||
1149 | if (ieee80211_is_data(hdr->frame_control)) { | ||
1150 | int hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1151 | int ivlen = 0, icvlen = 4; /* also FCS */ | ||
877 | 1152 | ||
878 | if (pkt8023) { | ||
879 | pkt = alloc_skb(pktsize, GFP_KERNEL); | 1153 | pkt = alloc_skb(pktsize, GFP_KERNEL); |
880 | if (!pkt) | 1154 | if (!pkt) |
881 | goto report; | 1155 | goto report; |
882 | memcpy(skb_put(pkt, pktsize), status->wake_packet, | 1156 | |
883 | pktsize); | 1157 | memcpy(skb_put(pkt, hdrlen), pktdata, hdrlen); |
1158 | pktdata += hdrlen; | ||
1159 | pktsize -= hdrlen; | ||
1160 | |||
1161 | if (ieee80211_has_protected(hdr->frame_control)) { | ||
1162 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
1163 | ivlen = mvm->gtk_ivlen; | ||
1164 | icvlen += mvm->gtk_icvlen; | ||
1165 | } else { | ||
1166 | ivlen = mvm->ptk_ivlen; | ||
1167 | icvlen += mvm->ptk_icvlen; | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1171 | /* if truncated, FCS/ICV is (partially) gone */ | ||
1172 | if (truncated >= icvlen) { | ||
1173 | icvlen = 0; | ||
1174 | truncated -= icvlen; | ||
1175 | } else { | ||
1176 | icvlen -= truncated; | ||
1177 | truncated = 0; | ||
1178 | } | ||
1179 | |||
1180 | pktsize -= ivlen + icvlen; | ||
1181 | pktdata += ivlen; | ||
1182 | |||
1183 | memcpy(skb_put(pkt, pktsize), pktdata, pktsize); | ||
1184 | |||
884 | if (ieee80211_data_to_8023(pkt, vif->addr, vif->type)) | 1185 | if (ieee80211_data_to_8023(pkt, vif->addr, vif->type)) |
885 | goto report; | 1186 | goto report; |
886 | wakeup.packet = pkt->data; | 1187 | wakeup.packet = pkt->data; |
887 | wakeup.packet_present_len = pkt->len; | 1188 | wakeup.packet_present_len = pkt->len; |
888 | wakeup.packet_len = pkt->len - (pktlen - pktsize); | 1189 | wakeup.packet_len = pkt->len - truncated; |
889 | wakeup.packet_80211 = false; | 1190 | wakeup.packet_80211 = false; |
890 | } else { | 1191 | } else { |
1192 | int fcslen = 4; | ||
1193 | |||
1194 | if (truncated >= 4) { | ||
1195 | truncated -= 4; | ||
1196 | fcslen = 0; | ||
1197 | } else { | ||
1198 | fcslen -= truncated; | ||
1199 | truncated = 0; | ||
1200 | } | ||
1201 | pktsize -= fcslen; | ||
891 | wakeup.packet = status->wake_packet; | 1202 | wakeup.packet = status->wake_packet; |
892 | wakeup.packet_present_len = pktsize; | 1203 | wakeup.packet_present_len = pktsize; |
893 | wakeup.packet_len = pktlen; | 1204 | wakeup.packet_len = pktlen - truncated; |
894 | wakeup.packet_80211 = true; | 1205 | wakeup.packet_80211 = true; |
895 | } | 1206 | } |
896 | } | 1207 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index c1bdb5582126..2053dccefcd6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -69,12 +69,6 @@ struct iwl_dbgfs_mvm_ctx { | |||
69 | struct ieee80211_vif *vif; | 69 | struct ieee80211_vif *vif; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) | ||
73 | { | ||
74 | file->private_data = inode->i_private; | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static ssize_t iwl_dbgfs_tx_flush_write(struct file *file, | 72 | static ssize_t iwl_dbgfs_tx_flush_write(struct file *file, |
79 | const char __user *user_buf, | 73 | const char __user *user_buf, |
80 | size_t count, loff_t *ppos) | 74 | size_t count, loff_t *ppos) |
@@ -306,10 +300,191 @@ static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file, | |||
306 | return count; | 300 | return count; |
307 | } | 301 | } |
308 | 302 | ||
303 | static ssize_t iwl_dbgfs_mac_params_read(struct file *file, | ||
304 | char __user *user_buf, | ||
305 | size_t count, loff_t *ppos) | ||
306 | { | ||
307 | struct ieee80211_vif *vif = file->private_data; | ||
308 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
309 | struct iwl_mvm *mvm = mvmvif->dbgfs_data; | ||
310 | u8 ap_sta_id; | ||
311 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
312 | char buf[512]; | ||
313 | int bufsz = sizeof(buf); | ||
314 | int pos = 0; | ||
315 | int i; | ||
316 | |||
317 | mutex_lock(&mvm->mutex); | ||
318 | |||
319 | ap_sta_id = mvmvif->ap_sta_id; | ||
320 | |||
321 | pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n", | ||
322 | mvmvif->id, mvmvif->color); | ||
323 | pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n", | ||
324 | vif->bss_conf.bssid); | ||
325 | pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n"); | ||
326 | for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++) { | ||
327 | pos += scnprintf(buf+pos, bufsz-pos, | ||
328 | "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n", | ||
329 | i, mvmvif->queue_params[i].txop, | ||
330 | mvmvif->queue_params[i].cw_min, | ||
331 | mvmvif->queue_params[i].cw_max, | ||
332 | mvmvif->queue_params[i].aifs, | ||
333 | mvmvif->queue_params[i].uapsd); | ||
334 | } | ||
335 | |||
336 | if (vif->type == NL80211_IFTYPE_STATION && | ||
337 | ap_sta_id != IWL_MVM_STATION_COUNT) { | ||
338 | struct ieee80211_sta *sta; | ||
339 | struct iwl_mvm_sta *mvm_sta; | ||
340 | |||
341 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id], | ||
342 | lockdep_is_held(&mvm->mutex)); | ||
343 | mvm_sta = (void *)sta->drv_priv; | ||
344 | pos += scnprintf(buf+pos, bufsz-pos, | ||
345 | "ap_sta_id %d - reduced Tx power %d\n", | ||
346 | ap_sta_id, mvm_sta->bt_reduced_txpower); | ||
347 | } | ||
348 | |||
349 | rcu_read_lock(); | ||
350 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
351 | if (chanctx_conf) { | ||
352 | pos += scnprintf(buf+pos, bufsz-pos, | ||
353 | "idle rx chains %d, active rx chains: %d\n", | ||
354 | chanctx_conf->rx_chains_static, | ||
355 | chanctx_conf->rx_chains_dynamic); | ||
356 | } | ||
357 | rcu_read_unlock(); | ||
358 | |||
359 | mutex_unlock(&mvm->mutex); | ||
360 | |||
361 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
362 | } | ||
363 | |||
364 | #define BT_MBOX_MSG(_notif, _num, _field) \ | ||
365 | ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ | ||
366 | >> BT_MBOX##_num##_##_field##_POS) | ||
367 | |||
368 | |||
369 | #define BT_MBOX_PRINT(_num, _field, _end) \ | ||
370 | pos += scnprintf(buf + pos, bufsz - pos, \ | ||
371 | "\t%s: %d%s", \ | ||
372 | #_field, \ | ||
373 | BT_MBOX_MSG(notif, _num, _field), \ | ||
374 | true ? "\n" : ", "); | ||
375 | |||
376 | static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, | ||
377 | size_t count, loff_t *ppos) | ||
378 | { | ||
379 | struct iwl_mvm *mvm = file->private_data; | ||
380 | struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; | ||
381 | char *buf; | ||
382 | int ret, pos = 0, bufsz = sizeof(char) * 1024; | ||
383 | |||
384 | buf = kmalloc(bufsz, GFP_KERNEL); | ||
385 | if (!buf) | ||
386 | return -ENOMEM; | ||
387 | |||
388 | mutex_lock(&mvm->mutex); | ||
389 | |||
390 | pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n"); | ||
391 | |||
392 | BT_MBOX_PRINT(0, LE_SLAVE_LAT, false); | ||
393 | BT_MBOX_PRINT(0, LE_PROF1, false); | ||
394 | BT_MBOX_PRINT(0, LE_PROF2, false); | ||
395 | BT_MBOX_PRINT(0, LE_PROF_OTHER, false); | ||
396 | BT_MBOX_PRINT(0, CHL_SEQ_N, false); | ||
397 | BT_MBOX_PRINT(0, INBAND_S, false); | ||
398 | BT_MBOX_PRINT(0, LE_MIN_RSSI, false); | ||
399 | BT_MBOX_PRINT(0, LE_SCAN, false); | ||
400 | BT_MBOX_PRINT(0, LE_ADV, false); | ||
401 | BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false); | ||
402 | BT_MBOX_PRINT(0, OPEN_CON_1, true); | ||
403 | |||
404 | pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n"); | ||
405 | |||
406 | BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false); | ||
407 | BT_MBOX_PRINT(1, IP_SR, false); | ||
408 | BT_MBOX_PRINT(1, LE_MSTR, false); | ||
409 | BT_MBOX_PRINT(1, AGGR_TRFC_LD, false); | ||
410 | BT_MBOX_PRINT(1, MSG_TYPE, false); | ||
411 | BT_MBOX_PRINT(1, SSN, true); | ||
412 | |||
413 | pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n"); | ||
414 | |||
415 | BT_MBOX_PRINT(2, SNIFF_ACT, false); | ||
416 | BT_MBOX_PRINT(2, PAG, false); | ||
417 | BT_MBOX_PRINT(2, INQUIRY, false); | ||
418 | BT_MBOX_PRINT(2, CONN, false); | ||
419 | BT_MBOX_PRINT(2, SNIFF_INTERVAL, false); | ||
420 | BT_MBOX_PRINT(2, DISC, false); | ||
421 | BT_MBOX_PRINT(2, SCO_TX_ACT, false); | ||
422 | BT_MBOX_PRINT(2, SCO_RX_ACT, false); | ||
423 | BT_MBOX_PRINT(2, ESCO_RE_TX, false); | ||
424 | BT_MBOX_PRINT(2, SCO_DURATION, true); | ||
425 | |||
426 | pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n"); | ||
427 | |||
428 | BT_MBOX_PRINT(3, SCO_STATE, false); | ||
429 | BT_MBOX_PRINT(3, SNIFF_STATE, false); | ||
430 | BT_MBOX_PRINT(3, A2DP_STATE, false); | ||
431 | BT_MBOX_PRINT(3, ACL_STATE, false); | ||
432 | BT_MBOX_PRINT(3, MSTR_STATE, false); | ||
433 | BT_MBOX_PRINT(3, OBX_STATE, false); | ||
434 | BT_MBOX_PRINT(3, OPEN_CON_2, false); | ||
435 | BT_MBOX_PRINT(3, TRAFFIC_LOAD, false); | ||
436 | BT_MBOX_PRINT(3, CHL_SEQN_LSB, false); | ||
437 | BT_MBOX_PRINT(3, INBAND_P, false); | ||
438 | BT_MBOX_PRINT(3, MSG_TYPE_2, false); | ||
439 | BT_MBOX_PRINT(3, SSN_2, false); | ||
440 | BT_MBOX_PRINT(3, UPDATE_REQUEST, true); | ||
441 | |||
442 | pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n", | ||
443 | notif->bt_status); | ||
444 | pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n", | ||
445 | notif->bt_open_conn); | ||
446 | pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n", | ||
447 | notif->bt_traffic_load); | ||
448 | pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n", | ||
449 | notif->bt_agg_traffic_load); | ||
450 | pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n", | ||
451 | notif->bt_ci_compliance); | ||
452 | |||
453 | mutex_unlock(&mvm->mutex); | ||
454 | |||
455 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
456 | kfree(buf); | ||
457 | |||
458 | return ret; | ||
459 | } | ||
460 | #undef BT_MBOX_PRINT | ||
461 | |||
462 | static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | ||
463 | const char __user *user_buf, | ||
464 | size_t count, loff_t *ppos) | ||
465 | { | ||
466 | struct iwl_mvm *mvm = file->private_data; | ||
467 | bool restart_fw = iwlwifi_mod_params.restart_fw; | ||
468 | int ret; | ||
469 | |||
470 | iwlwifi_mod_params.restart_fw = true; | ||
471 | |||
472 | mutex_lock(&mvm->mutex); | ||
473 | |||
474 | /* take the return value to make compiler happy - it will fail anyway */ | ||
475 | ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL); | ||
476 | |||
477 | mutex_unlock(&mvm->mutex); | ||
478 | |||
479 | iwlwifi_mod_params.restart_fw = restart_fw; | ||
480 | |||
481 | return count; | ||
482 | } | ||
483 | |||
309 | #define MVM_DEBUGFS_READ_FILE_OPS(name) \ | 484 | #define MVM_DEBUGFS_READ_FILE_OPS(name) \ |
310 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 485 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
311 | .read = iwl_dbgfs_##name##_read, \ | 486 | .read = iwl_dbgfs_##name##_read, \ |
312 | .open = iwl_dbgfs_open_file_generic, \ | 487 | .open = simple_open, \ |
313 | .llseek = generic_file_llseek, \ | 488 | .llseek = generic_file_llseek, \ |
314 | } | 489 | } |
315 | 490 | ||
@@ -317,14 +492,14 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
317 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 492 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
318 | .write = iwl_dbgfs_##name##_write, \ | 493 | .write = iwl_dbgfs_##name##_write, \ |
319 | .read = iwl_dbgfs_##name##_read, \ | 494 | .read = iwl_dbgfs_##name##_read, \ |
320 | .open = iwl_dbgfs_open_file_generic, \ | 495 | .open = simple_open, \ |
321 | .llseek = generic_file_llseek, \ | 496 | .llseek = generic_file_llseek, \ |
322 | }; | 497 | }; |
323 | 498 | ||
324 | #define MVM_DEBUGFS_WRITE_FILE_OPS(name) \ | 499 | #define MVM_DEBUGFS_WRITE_FILE_OPS(name) \ |
325 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 500 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
326 | .write = iwl_dbgfs_##name##_write, \ | 501 | .write = iwl_dbgfs_##name##_write, \ |
327 | .open = iwl_dbgfs_open_file_generic, \ | 502 | .open = simple_open, \ |
328 | .llseek = generic_file_llseek, \ | 503 | .llseek = generic_file_llseek, \ |
329 | }; | 504 | }; |
330 | 505 | ||
@@ -345,8 +520,13 @@ MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush); | |||
345 | MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain); | 520 | MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain); |
346 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram); | 521 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram); |
347 | MVM_DEBUGFS_READ_FILE_OPS(stations); | 522 | MVM_DEBUGFS_READ_FILE_OPS(stations); |
523 | MVM_DEBUGFS_READ_FILE_OPS(bt_notif); | ||
348 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow); | 524 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow); |
349 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow); | 525 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow); |
526 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); | ||
527 | |||
528 | /* Interface specific debugfs entries */ | ||
529 | MVM_DEBUGFS_READ_FILE_OPS(mac_params); | ||
350 | 530 | ||
351 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | 531 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) |
352 | { | 532 | { |
@@ -358,8 +538,10 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
358 | MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR); | 538 | MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR); |
359 | MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); | 539 | MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); |
360 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); | 540 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); |
541 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); | ||
361 | MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR); | 542 | MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR); |
362 | MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR); | 543 | MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR); |
544 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); | ||
363 | 545 | ||
364 | /* | 546 | /* |
365 | * Create a symlink with mac80211. It will be removed when mac80211 | 547 | * Create a symlink with mac80211. It will be removed when mac80211 |
@@ -376,3 +558,58 @@ err: | |||
376 | IWL_ERR(mvm, "Can't create the mvm debugfs directory\n"); | 558 | IWL_ERR(mvm, "Can't create the mvm debugfs directory\n"); |
377 | return -ENOMEM; | 559 | return -ENOMEM; |
378 | } | 560 | } |
561 | |||
562 | void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
563 | { | ||
564 | struct dentry *dbgfs_dir = vif->debugfs_dir; | ||
565 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
566 | char buf[100]; | ||
567 | |||
568 | if (!dbgfs_dir) | ||
569 | return; | ||
570 | |||
571 | mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir); | ||
572 | mvmvif->dbgfs_data = mvm; | ||
573 | |||
574 | if (!mvmvif->dbgfs_dir) { | ||
575 | IWL_ERR(mvm, "Failed to create debugfs directory under %s\n", | ||
576 | dbgfs_dir->d_name.name); | ||
577 | return; | ||
578 | } | ||
579 | |||
580 | MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, | ||
581 | S_IRUSR); | ||
582 | |||
583 | /* | ||
584 | * Create symlink for convenience pointing to interface specific | ||
585 | * debugfs entries for the driver. For example, under | ||
586 | * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/ | ||
587 | * find | ||
588 | * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/ | ||
589 | */ | ||
590 | snprintf(buf, 100, "../../../%s/%s/%s/%s", | ||
591 | dbgfs_dir->d_parent->d_parent->d_name.name, | ||
592 | dbgfs_dir->d_parent->d_name.name, | ||
593 | dbgfs_dir->d_name.name, | ||
594 | mvmvif->dbgfs_dir->d_name.name); | ||
595 | |||
596 | mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name, | ||
597 | mvm->debugfs_dir, buf); | ||
598 | if (!mvmvif->dbgfs_slink) | ||
599 | IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n", | ||
600 | dbgfs_dir->d_name.name); | ||
601 | return; | ||
602 | err: | ||
603 | IWL_ERR(mvm, "Can't create debugfs entity\n"); | ||
604 | } | ||
605 | |||
606 | void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
607 | { | ||
608 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
609 | |||
610 | debugfs_remove(mvmvif->dbgfs_slink); | ||
611 | mvmvif->dbgfs_slink = NULL; | ||
612 | |||
613 | debugfs_remove_recursive(mvmvif->dbgfs_dir); | ||
614 | mvmvif->dbgfs_dir = NULL; | ||
615 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h new file mode 100644 index 000000000000..05c61d6f384e --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h | |||
@@ -0,0 +1,319 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called COPYING. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __fw_api_bt_coex_h__ | ||
64 | #define __fw_api_bt_coex_h__ | ||
65 | |||
66 | #include <linux/types.h> | ||
67 | #include <linux/bitops.h> | ||
68 | |||
69 | #define BITS(nb) (BIT(nb) - 1) | ||
70 | |||
71 | /** | ||
72 | * enum iwl_bt_coex_flags - flags for BT_COEX command | ||
73 | * @BT_CH_PRIMARY_EN: | ||
74 | * @BT_CH_SECONDARY_EN: | ||
75 | * @BT_NOTIF_COEX_OFF: | ||
76 | * @BT_COEX_MODE_POS: | ||
77 | * @BT_COEX_MODE_MSK: | ||
78 | * @BT_COEX_DISABLE: | ||
79 | * @BT_COEX_2W: | ||
80 | * @BT_COEX_3W: | ||
81 | * @BT_COEX_NW: | ||
82 | * @BT_USE_DEFAULTS: | ||
83 | * @BT_SYNC_2_BT_DISABLE: | ||
84 | * @BT_COEX_CORUNNING_TBL_EN: | ||
85 | */ | ||
86 | enum iwl_bt_coex_flags { | ||
87 | BT_CH_PRIMARY_EN = BIT(0), | ||
88 | BT_CH_SECONDARY_EN = BIT(1), | ||
89 | BT_NOTIF_COEX_OFF = BIT(2), | ||
90 | BT_COEX_MODE_POS = 3, | ||
91 | BT_COEX_MODE_MSK = BITS(3) << BT_COEX_MODE_POS, | ||
92 | BT_COEX_DISABLE = 0x0 << BT_COEX_MODE_POS, | ||
93 | BT_COEX_2W = 0x1 << BT_COEX_MODE_POS, | ||
94 | BT_COEX_3W = 0x2 << BT_COEX_MODE_POS, | ||
95 | BT_COEX_NW = 0x3 << BT_COEX_MODE_POS, | ||
96 | BT_USE_DEFAULTS = BIT(6), | ||
97 | BT_SYNC_2_BT_DISABLE = BIT(7), | ||
98 | /* | ||
99 | * For future use - when the flags will be enlarged | ||
100 | * BT_COEX_CORUNNING_TBL_EN = BIT(8), | ||
101 | */ | ||
102 | }; | ||
103 | |||
104 | /* | ||
105 | * indicates what has changed in the BT_COEX command. | ||
106 | */ | ||
107 | enum iwl_bt_coex_valid_bit_msk { | ||
108 | BT_VALID_ENABLE = BIT(0), | ||
109 | BT_VALID_BT_PRIO_BOOST = BIT(1), | ||
110 | BT_VALID_MAX_KILL = BIT(2), | ||
111 | BT_VALID_3W_TMRS = BIT(3), | ||
112 | BT_VALID_KILL_ACK = BIT(4), | ||
113 | BT_VALID_KILL_CTS = BIT(5), | ||
114 | BT_VALID_REDUCED_TX_POWER = BIT(6), | ||
115 | BT_VALID_LUT = BIT(7), | ||
116 | BT_VALID_WIFI_RX_SW_PRIO_BOOST = BIT(8), | ||
117 | BT_VALID_WIFI_TX_SW_PRIO_BOOST = BIT(9), | ||
118 | BT_VALID_MULTI_PRIO_LUT = BIT(10), | ||
119 | BT_VALID_TRM_KICK_FILTER = BIT(11), | ||
120 | BT_VALID_CORUN_LUT_20 = BIT(12), | ||
121 | BT_VALID_CORUN_LUT_40 = BIT(13), | ||
122 | BT_VALID_ANT_ISOLATION = BIT(14), | ||
123 | BT_VALID_ANT_ISOLATION_THRS = BIT(15), | ||
124 | /* | ||
125 | * For future use - when the valid flags will be enlarged | ||
126 | * BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16), | ||
127 | * BT_VALID_TXRX_MAX_FREQ_0 = BIT(17), | ||
128 | */ | ||
129 | }; | ||
130 | |||
131 | /** | ||
132 | * enum iwl_bt_reduced_tx_power - allows to reduce txpower for WiFi frames. | ||
133 | * @BT_REDUCED_TX_POWER_CTL: reduce Tx power for control frames | ||
134 | * @BT_REDUCED_TX_POWER_DATA: reduce Tx power for data frames | ||
135 | * | ||
136 | * This mechanism allows to have BT and WiFi run concurrently. Since WiFi | ||
137 | * reduces its Tx power, it can work along with BT, hence reducing the amount | ||
138 | * of WiFi frames being killed by BT. | ||
139 | */ | ||
140 | enum iwl_bt_reduced_tx_power { | ||
141 | BT_REDUCED_TX_POWER_CTL = BIT(0), | ||
142 | BT_REDUCED_TX_POWER_DATA = BIT(1), | ||
143 | }; | ||
144 | |||
145 | #define BT_COEX_LUT_SIZE (12) | ||
146 | |||
147 | /** | ||
148 | * struct iwl_bt_coex_cmd - bt coex configuration command | ||
149 | * @flags:&enum iwl_bt_coex_flags | ||
150 | * @lead_time: | ||
151 | * @max_kill: | ||
152 | * @bt3_time_t7_value: | ||
153 | * @kill_ack_msk: | ||
154 | * @kill_cts_msk: | ||
155 | * @bt3_prio_sample_time: | ||
156 | * @bt3_timer_t2_value: | ||
157 | * @bt4_reaction_time: | ||
158 | * @decision_lut[12]: | ||
159 | * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power | ||
160 | * @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk | ||
161 | * @bt_prio_boost: values for PTA boost register | ||
162 | * @wifi_tx_prio_boost: SW boost of wifi tx priority | ||
163 | * @wifi_rx_prio_boost: SW boost of wifi rx priority | ||
164 | * | ||
165 | * The structure is used for the BT_COEX command. | ||
166 | */ | ||
167 | struct iwl_bt_coex_cmd { | ||
168 | u8 flags; | ||
169 | u8 lead_time; | ||
170 | u8 max_kill; | ||
171 | u8 bt3_time_t7_value; | ||
172 | __le32 kill_ack_msk; | ||
173 | __le32 kill_cts_msk; | ||
174 | u8 bt3_prio_sample_time; | ||
175 | u8 bt3_timer_t2_value; | ||
176 | __le16 bt4_reaction_time; | ||
177 | __le32 decision_lut[BT_COEX_LUT_SIZE]; | ||
178 | u8 bt_reduced_tx_power; | ||
179 | u8 reserved; | ||
180 | __le16 valid_bit_msk; | ||
181 | __le32 bt_prio_boost; | ||
182 | u8 reserved2; | ||
183 | u8 wifi_tx_prio_boost; | ||
184 | __le16 wifi_rx_prio_boost; | ||
185 | } __packed; /* BT_COEX_CMD_API_S_VER_3 */ | ||
186 | |||
187 | #define BT_MBOX(n_dw, _msg, _pos, _nbits) \ | ||
188 | BT_MBOX##n_dw##_##_msg##_POS = (_pos), \ | ||
189 | BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS | ||
190 | |||
191 | enum iwl_bt_mxbox_dw0 { | ||
192 | BT_MBOX(0, LE_SLAVE_LAT, 0, 3), | ||
193 | BT_MBOX(0, LE_PROF1, 3, 1), | ||
194 | BT_MBOX(0, LE_PROF2, 4, 1), | ||
195 | BT_MBOX(0, LE_PROF_OTHER, 5, 1), | ||
196 | BT_MBOX(0, CHL_SEQ_N, 8, 4), | ||
197 | BT_MBOX(0, INBAND_S, 13, 1), | ||
198 | BT_MBOX(0, LE_MIN_RSSI, 16, 4), | ||
199 | BT_MBOX(0, LE_SCAN, 20, 1), | ||
200 | BT_MBOX(0, LE_ADV, 21, 1), | ||
201 | BT_MBOX(0, LE_MAX_TX_POWER, 24, 4), | ||
202 | BT_MBOX(0, OPEN_CON_1, 28, 2), | ||
203 | }; | ||
204 | |||
205 | enum iwl_bt_mxbox_dw1 { | ||
206 | BT_MBOX(1, BR_MAX_TX_POWER, 0, 4), | ||
207 | BT_MBOX(1, IP_SR, 4, 1), | ||
208 | BT_MBOX(1, LE_MSTR, 5, 1), | ||
209 | BT_MBOX(1, AGGR_TRFC_LD, 8, 6), | ||
210 | BT_MBOX(1, MSG_TYPE, 16, 3), | ||
211 | BT_MBOX(1, SSN, 19, 2), | ||
212 | }; | ||
213 | |||
214 | enum iwl_bt_mxbox_dw2 { | ||
215 | BT_MBOX(2, SNIFF_ACT, 0, 3), | ||
216 | BT_MBOX(2, PAG, 3, 1), | ||
217 | BT_MBOX(2, INQUIRY, 4, 1), | ||
218 | BT_MBOX(2, CONN, 5, 1), | ||
219 | BT_MBOX(2, SNIFF_INTERVAL, 8, 5), | ||
220 | BT_MBOX(2, DISC, 13, 1), | ||
221 | BT_MBOX(2, SCO_TX_ACT, 16, 2), | ||
222 | BT_MBOX(2, SCO_RX_ACT, 18, 2), | ||
223 | BT_MBOX(2, ESCO_RE_TX, 20, 2), | ||
224 | BT_MBOX(2, SCO_DURATION, 24, 6), | ||
225 | }; | ||
226 | |||
227 | enum iwl_bt_mxbox_dw3 { | ||
228 | BT_MBOX(3, SCO_STATE, 0, 1), | ||
229 | BT_MBOX(3, SNIFF_STATE, 1, 1), | ||
230 | BT_MBOX(3, A2DP_STATE, 2, 1), | ||
231 | BT_MBOX(3, ACL_STATE, 3, 1), | ||
232 | BT_MBOX(3, MSTR_STATE, 4, 1), | ||
233 | BT_MBOX(3, OBX_STATE, 5, 1), | ||
234 | BT_MBOX(3, OPEN_CON_2, 8, 2), | ||
235 | BT_MBOX(3, TRAFFIC_LOAD, 10, 2), | ||
236 | BT_MBOX(3, CHL_SEQN_LSB, 12, 1), | ||
237 | BT_MBOX(3, INBAND_P, 13, 1), | ||
238 | BT_MBOX(3, MSG_TYPE_2, 16, 3), | ||
239 | BT_MBOX(3, SSN_2, 19, 2), | ||
240 | BT_MBOX(3, UPDATE_REQUEST, 21, 1), | ||
241 | }; | ||
242 | |||
243 | #define BT_MBOX_MSG(_notif, _num, _field) \ | ||
244 | ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ | ||
245 | >> BT_MBOX##_num##_##_field##_POS) | ||
246 | |||
247 | /** | ||
248 | * struct iwl_bt_coex_profile_notif - notification about BT coex | ||
249 | * @mbox_msg: message from BT to WiFi | ||
250 | * @:bt_status: 0 - off, 1 - on | ||
251 | * @:bt_open_conn: number of BT connections open | ||
252 | * @:bt_traffic_load: load of BT traffic | ||
253 | * @:bt_agg_traffic_load: aggregated load of BT traffic | ||
254 | * @:bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant | ||
255 | */ | ||
256 | struct iwl_bt_coex_profile_notif { | ||
257 | __le32 mbox_msg[4]; | ||
258 | u8 bt_status; | ||
259 | u8 bt_open_conn; | ||
260 | u8 bt_traffic_load; | ||
261 | u8 bt_agg_traffic_load; | ||
262 | u8 bt_ci_compliance; | ||
263 | u8 reserved[3]; | ||
264 | } __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */ | ||
265 | |||
266 | enum iwl_bt_coex_prio_table_event { | ||
267 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB1 = 0, | ||
268 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2 = 1, | ||
269 | BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1 = 2, | ||
270 | BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2 = 3, | ||
271 | BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1 = 4, | ||
272 | BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2 = 5, | ||
273 | BT_COEX_PRIO_TBL_EVT_DTIM = 6, | ||
274 | BT_COEX_PRIO_TBL_EVT_SCAN52 = 7, | ||
275 | BT_COEX_PRIO_TBL_EVT_SCAN24 = 8, | ||
276 | BT_COEX_PRIO_TBL_EVT_IDLE = 9, | ||
277 | BT_COEX_PRIO_TBL_EVT_MAX = 16, | ||
278 | }; /* BT_COEX_PRIO_TABLE_EVENTS_API_E_VER_1 */ | ||
279 | |||
280 | enum iwl_bt_coex_prio_table_prio { | ||
281 | BT_COEX_PRIO_TBL_DISABLED = 0, | ||
282 | BT_COEX_PRIO_TBL_PRIO_LOW = 1, | ||
283 | BT_COEX_PRIO_TBL_PRIO_HIGH = 2, | ||
284 | BT_COEX_PRIO_TBL_PRIO_BYPASS = 3, | ||
285 | BT_COEX_PRIO_TBL_PRIO_COEX_OFF = 4, | ||
286 | BT_COEX_PRIO_TBL_PRIO_COEX_ON = 5, | ||
287 | BT_COEX_PRIO_TBL_PRIO_COEX_IDLE = 6, | ||
288 | BT_COEX_PRIO_TBL_MAX = 8, | ||
289 | }; /* BT_COEX_PRIO_TABLE_PRIORITIES_API_E_VER_1 */ | ||
290 | |||
291 | #define BT_COEX_PRIO_TBL_SHRD_ANT_POS (0) | ||
292 | #define BT_COEX_PRIO_TBL_PRIO_POS (1) | ||
293 | #define BT_COEX_PRIO_TBL_RESERVED_POS (4) | ||
294 | |||
295 | /** | ||
296 | * struct iwl_bt_coex_prio_tbl_cmd - priority table for BT coex | ||
297 | * @prio_tbl: | ||
298 | */ | ||
299 | struct iwl_bt_coex_prio_tbl_cmd { | ||
300 | u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX]; | ||
301 | } __packed; | ||
302 | |||
303 | enum iwl_bt_coex_env_action { | ||
304 | BT_COEX_ENV_CLOSE = 0, | ||
305 | BT_COEX_ENV_OPEN = 1, | ||
306 | }; /* BT_COEX_PROT_ENV_ACTION_API_E_VER_1 */ | ||
307 | |||
308 | /** | ||
309 | * struct iwl_bt_coex_prot_env_cmd - BT Protection Envelope | ||
310 | * @action: enum %iwl_bt_coex_env_action | ||
311 | * @type: enum %iwl_bt_coex_prio_table_event | ||
312 | */ | ||
313 | struct iwl_bt_coex_prot_env_cmd { | ||
314 | u8 action; /* 0 = closed, 1 = open */ | ||
315 | u8 type; /* 0 .. 15 */ | ||
316 | u8 reserved[2]; | ||
317 | } __packed; | ||
318 | |||
319 | #endif /* __fw_api_bt_coex_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h index cf6f9a02fb74..51e015d1dfb2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -258,7 +258,7 @@ enum iwl_wowlan_wakeup_reason { | |||
258 | IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE = BIT(8), | 258 | IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE = BIT(8), |
259 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS = BIT(9), | 259 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS = BIT(9), |
260 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE = BIT(10), | 260 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE = BIT(10), |
261 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_TCP_EXTERNAL = BIT(11), | 261 | /* BIT(11) reserved */ |
262 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12), | 262 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12), |
263 | }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ | 263 | }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ |
264 | 264 | ||
@@ -277,6 +277,55 @@ struct iwl_wowlan_status { | |||
277 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ | 277 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ |
278 | } __packed; /* WOWLAN_STATUSES_API_S_VER_4 */ | 278 | } __packed; /* WOWLAN_STATUSES_API_S_VER_4 */ |
279 | 279 | ||
280 | #define IWL_WOWLAN_TCP_MAX_PACKET_LEN 64 | ||
281 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN 128 | ||
282 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS 2048 | ||
283 | |||
284 | struct iwl_tcp_packet_info { | ||
285 | __le16 tcp_pseudo_header_checksum; | ||
286 | __le16 tcp_payload_length; | ||
287 | } __packed; /* TCP_PACKET_INFO_API_S_VER_2 */ | ||
288 | |||
289 | struct iwl_tcp_packet { | ||
290 | struct iwl_tcp_packet_info info; | ||
291 | u8 rx_mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8]; | ||
292 | u8 data[IWL_WOWLAN_TCP_MAX_PACKET_LEN]; | ||
293 | } __packed; /* TCP_PROTOCOL_PACKET_API_S_VER_1 */ | ||
294 | |||
295 | struct iwl_remote_wake_packet { | ||
296 | struct iwl_tcp_packet_info info; | ||
297 | u8 rx_mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8]; | ||
298 | u8 data[IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN]; | ||
299 | } __packed; /* TCP_PROTOCOL_PACKET_API_S_VER_1 */ | ||
300 | |||
301 | struct iwl_wowlan_remote_wake_config { | ||
302 | __le32 connection_max_time; /* unused */ | ||
303 | /* TCP_PROTOCOL_CONFIG_API_S_VER_1 */ | ||
304 | u8 max_syn_retries; | ||
305 | u8 max_data_retries; | ||
306 | u8 tcp_syn_ack_timeout; | ||
307 | u8 tcp_ack_timeout; | ||
308 | |||
309 | struct iwl_tcp_packet syn_tx; | ||
310 | struct iwl_tcp_packet synack_rx; | ||
311 | struct iwl_tcp_packet keepalive_ack_rx; | ||
312 | struct iwl_tcp_packet fin_tx; | ||
313 | |||
314 | struct iwl_remote_wake_packet keepalive_tx; | ||
315 | struct iwl_remote_wake_packet wake_rx; | ||
316 | |||
317 | /* REMOTE_WAKE_OFFSET_INFO_API_S_VER_1 */ | ||
318 | u8 sequence_number_offset; | ||
319 | u8 sequence_number_length; | ||
320 | u8 token_offset; | ||
321 | u8 token_length; | ||
322 | /* REMOTE_WAKE_PROTOCOL_PARAMS_API_S_VER_1 */ | ||
323 | __le32 initial_sequence_number; | ||
324 | __le16 keepalive_interval; | ||
325 | __le16 num_tokens; | ||
326 | u8 tokens[IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS]; | ||
327 | } __packed; /* REMOTE_WAKE_CONFIG_API_S_VER_2 */ | ||
328 | |||
280 | /* TODO: NetDetect API */ | 329 | /* TODO: NetDetect API */ |
281 | 330 | ||
282 | #endif /* __fw_api_d3_h__ */ | 331 | #endif /* __fw_api_d3_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h index ae39b7dfda7b..d68640ea41d4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index be36b7604b7f..81fe45f46be7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -68,73 +68,53 @@ | |||
68 | 68 | ||
69 | /** | 69 | /** |
70 | * enum iwl_scan_flags - masks for power table command flags | 70 | * enum iwl_scan_flags - masks for power table command flags |
71 | * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off | ||
72 | * receiver and transmitter. '0' - does not allow. | ||
71 | * @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management, | 73 | * @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management, |
72 | * '1' Driver enables PM (use rest of parameters) | 74 | * '1' Driver enables PM (use rest of parameters) |
73 | * @POWER_FLAGS_SLEEP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM, | 75 | * @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM, |
74 | * '1' PM could sleep over DTIM till listen Interval. | 76 | * '1' PM could sleep over DTIM till listen Interval. |
75 | * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable. | ||
76 | * @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all | ||
77 | * access categories are both delivery and trigger enabled. | ||
78 | * @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and | ||
79 | * PBW Snoozing enabled | ||
80 | * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask | 77 | * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask |
78 | * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable. | ||
81 | */ | 79 | */ |
82 | enum iwl_power_flags { | 80 | enum iwl_power_flags { |
83 | POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(0), | 81 | POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), |
84 | POWER_FLAGS_SLEEP_OVER_DTIM_MSK = BIT(1), | 82 | POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1), |
85 | POWER_FLAGS_LPRX_ENA_MSK = BIT(2), | 83 | POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2), |
86 | POWER_FLAGS_SNOOZE_ENA_MSK = BIT(3), | 84 | POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9), |
87 | POWER_FLAGS_BT_SCO_ENA = BIT(4), | 85 | POWER_FLAGS_LPRX_ENA_MSK = BIT(11), |
88 | POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(5) | ||
89 | }; | 86 | }; |
90 | 87 | ||
88 | #define IWL_POWER_VEC_SIZE 5 | ||
89 | |||
91 | /** | 90 | /** |
92 | * struct iwl_powertable_cmd - Power Table Command | 91 | * struct iwl_powertable_cmd - Power Table Command |
93 | * POWER_TABLE_CMD = 0x77 (command, has simple generic response) | 92 | * POWER_TABLE_CMD = 0x77 (command, has simple generic response) |
94 | * | 93 | * |
95 | * @id_and_color: MAC contex identifier | ||
96 | * @action: Action on context - no action, add new, | ||
97 | * modify existent, remove | ||
98 | * @flags: Power table command flags from POWER_FLAGS_* | 94 | * @flags: Power table command flags from POWER_FLAGS_* |
99 | * @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec. | 95 | * @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec. |
100 | * Minimum allowed:- 3 * DTIM | 96 | * Minimum allowed:- 3 * DTIM. Keep alive period must be |
97 | * set regardless of power scheme or current power state. | ||
98 | * FW use this value also when PM is disabled. | ||
101 | * @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to | 99 | * @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to |
102 | * PSM transition - legacy PM | 100 | * PSM transition - legacy PM |
103 | * @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to | 101 | * @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to |
104 | * PSM transition - legacy PM | 102 | * PSM transition - legacy PM |
105 | * @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to | 103 | * @sleep_interval: not in use |
106 | * PSM transition - uAPSD | 104 | * @keep_alive_beacons: not in use |
107 | * @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to | ||
108 | * PSM transition - uAPSD | ||
109 | * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled. | 105 | * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled. |
110 | * Default: 80dbm | 106 | * Default: 80dbm |
111 | * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set | ||
112 | * @snooze_interval: TBD | ||
113 | * @snooze_window: TBD | ||
114 | * @snooze_step: TBD | ||
115 | * @qndp_tid: TBD | ||
116 | * @uapsd_ac_flags: TBD | ||
117 | * @uapsd_max_sp: TBD | ||
118 | */ | 107 | */ |
119 | struct iwl_powertable_cmd { | 108 | struct iwl_powertable_cmd { |
120 | /* COMMON_INDEX_HDR_API_S_VER_1 */ | 109 | /* PM_POWER_TABLE_CMD_API_S_VER_5 */ |
121 | __le32 id_and_color; | ||
122 | __le32 action; | ||
123 | __le16 flags; | 110 | __le16 flags; |
124 | u8 reserved; | 111 | u8 keep_alive_seconds; |
125 | __le16 keep_alive_seconds; | 112 | u8 debug_flags; |
126 | __le32 rx_data_timeout; | 113 | __le32 rx_data_timeout; |
127 | __le32 tx_data_timeout; | 114 | __le32 tx_data_timeout; |
128 | __le32 rx_data_timeout_uapsd; | 115 | __le32 sleep_interval[IWL_POWER_VEC_SIZE]; |
129 | __le32 tx_data_timeout_uapsd; | 116 | __le32 keep_alive_beacons; |
130 | u8 lprx_rssi_threshold; | 117 | __le32 lprx_rssi_threshold; |
131 | u8 num_skip_dtim; | ||
132 | __le16 snooze_interval; | ||
133 | __le16 snooze_window; | ||
134 | u8 snooze_step; | ||
135 | u8 qndp_tid; | ||
136 | u8 uapsd_ac_flags; | ||
137 | u8 uapsd_max_sp; | ||
138 | } __packed; | 118 | } __packed; |
139 | 119 | ||
140 | #endif | 120 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h index aa3474d08231..fdd33bc0a594 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 670ac8f95e26..b60d14151721 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h index 0acb53dda22d..a30691a8a85b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 2677914bf0a6..007a93b25bd7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -537,6 +537,12 @@ struct iwl_mac_beacon_cmd { | |||
537 | struct ieee80211_hdr frame[0]; | 537 | struct ieee80211_hdr frame[0]; |
538 | } __packed; | 538 | } __packed; |
539 | 539 | ||
540 | struct iwl_beacon_notif { | ||
541 | struct iwl_mvm_tx_resp beacon_notify_hdr; | ||
542 | __le64 tsf; | ||
543 | __le32 ibss_mgr_status; | ||
544 | } __packed; | ||
545 | |||
540 | /** | 546 | /** |
541 | * enum iwl_dump_control - dump (flush) control flags | 547 | * enum iwl_dump_control - dump (flush) control flags |
542 | * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty | 548 | * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 23eebda848b0..191dcae8ba47 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -70,6 +70,7 @@ | |||
70 | #include "fw-api-mac.h" | 70 | #include "fw-api-mac.h" |
71 | #include "fw-api-power.h" | 71 | #include "fw-api-power.h" |
72 | #include "fw-api-d3.h" | 72 | #include "fw-api-d3.h" |
73 | #include "fw-api-bt-coex.h" | ||
73 | 74 | ||
74 | /* queue and FIFO numbers by usage */ | 75 | /* queue and FIFO numbers by usage */ |
75 | enum { | 76 | enum { |
@@ -150,8 +151,10 @@ enum { | |||
150 | 151 | ||
151 | SET_CALIB_DEFAULT_CMD = 0x8e, | 152 | SET_CALIB_DEFAULT_CMD = 0x8e, |
152 | 153 | ||
154 | BEACON_NOTIFICATION = 0x90, | ||
153 | BEACON_TEMPLATE_CMD = 0x91, | 155 | BEACON_TEMPLATE_CMD = 0x91, |
154 | TX_ANT_CONFIGURATION_CMD = 0x98, | 156 | TX_ANT_CONFIGURATION_CMD = 0x98, |
157 | BT_CONFIG = 0x9b, | ||
155 | STATISTICS_NOTIFICATION = 0x9d, | 158 | STATISTICS_NOTIFICATION = 0x9d, |
156 | 159 | ||
157 | /* RF-KILL commands and notifications */ | 160 | /* RF-KILL commands and notifications */ |
@@ -162,6 +165,11 @@ enum { | |||
162 | REPLY_RX_MPDU_CMD = 0xc1, | 165 | REPLY_RX_MPDU_CMD = 0xc1, |
163 | BA_NOTIF = 0xc5, | 166 | BA_NOTIF = 0xc5, |
164 | 167 | ||
168 | /* BT Coex */ | ||
169 | BT_COEX_PRIO_TABLE = 0xcc, | ||
170 | BT_COEX_PROT_ENV = 0xcd, | ||
171 | BT_PROFILE_NOTIFICATION = 0xce, | ||
172 | |||
165 | REPLY_DEBUG_CMD = 0xf0, | 173 | REPLY_DEBUG_CMD = 0xf0, |
166 | DEBUG_LOG_MSG = 0xf7, | 174 | DEBUG_LOG_MSG = 0xf7, |
167 | 175 | ||
@@ -271,38 +279,7 @@ enum { | |||
271 | NVM_ACCESS_TARGET_EEPROM = 2, | 279 | NVM_ACCESS_TARGET_EEPROM = 2, |
272 | }; | 280 | }; |
273 | 281 | ||
274 | /** | 282 | /* Section types for NVM_ACCESS_CMD */ |
275 | * struct iwl_nvm_access_cmd_ver1 - Request the device to send the NVM. | ||
276 | * @op_code: 0 - read, 1 - write. | ||
277 | * @target: NVM_ACCESS_TARGET_*. should be 0 for read. | ||
278 | * @cache_refresh: 0 - None, 1- NVM. | ||
279 | * @offset: offset in the nvm data. | ||
280 | * @length: of the chunk. | ||
281 | * @data: empty on read, the NVM chunk on write | ||
282 | */ | ||
283 | struct iwl_nvm_access_cmd_ver1 { | ||
284 | u8 op_code; | ||
285 | u8 target; | ||
286 | u8 cache_refresh; | ||
287 | u8 reserved; | ||
288 | __le16 offset; | ||
289 | __le16 length; | ||
290 | u8 data[]; | ||
291 | } __packed; /* NVM_ACCESS_CMD_API_S_VER_1 */ | ||
292 | |||
293 | /** | ||
294 | * struct iwl_nvm_access_resp_ver1 - response to NVM_ACCESS_CMD | ||
295 | * @offset: the offset in the nvm data | ||
296 | * @length: of the chunk | ||
297 | * @data: the nvm chunk on when NVM_ACCESS_CMD was read, nothing on write | ||
298 | */ | ||
299 | struct iwl_nvm_access_resp_ver1 { | ||
300 | __le16 offset; | ||
301 | __le16 length; | ||
302 | u8 data[]; | ||
303 | } __packed; /* NVM_ACCESS_CMD_RESP_API_S_VER_1 */ | ||
304 | |||
305 | /* Section types for NVM_ACCESS_CMD version 2 */ | ||
306 | enum { | 283 | enum { |
307 | NVM_SECTION_TYPE_HW = 0, | 284 | NVM_SECTION_TYPE_HW = 0, |
308 | NVM_SECTION_TYPE_SW, | 285 | NVM_SECTION_TYPE_SW, |
@@ -323,7 +300,7 @@ enum { | |||
323 | * @length: in bytes, to read/write | 300 | * @length: in bytes, to read/write |
324 | * @data: if write operation, the data to write. On read its empty | 301 | * @data: if write operation, the data to write. On read its empty |
325 | */ | 302 | */ |
326 | struct iwl_nvm_access_cmd_ver2 { | 303 | struct iwl_nvm_access_cmd { |
327 | u8 op_code; | 304 | u8 op_code; |
328 | u8 target; | 305 | u8 target; |
329 | __le16 type; | 306 | __le16 type; |
@@ -340,7 +317,7 @@ struct iwl_nvm_access_cmd_ver2 { | |||
340 | * @status: 0 for success, fail otherwise | 317 | * @status: 0 for success, fail otherwise |
341 | * @data: if read operation, the data returned. Empty on write. | 318 | * @data: if read operation, the data returned. Empty on write. |
342 | */ | 319 | */ |
343 | struct iwl_nvm_access_resp_ver2 { | 320 | struct iwl_nvm_access_resp { |
344 | __le16 offset; | 321 | __le16 offset; |
345 | __le16 length; | 322 | __le16 length; |
346 | __le16 type; | 323 | __le16 type; |
@@ -503,15 +480,34 @@ enum { | |||
503 | TE_DEP_TSF = 2, | 480 | TE_DEP_TSF = 2, |
504 | TE_EVENT_SOCIOPATHIC = 4, | 481 | TE_EVENT_SOCIOPATHIC = 4, |
505 | }; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */ | 482 | }; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */ |
506 | 483 | /* | |
507 | /* When to send Time Event notifications and to whom (internal = FW) */ | 484 | * Supported Time event notifications configuration. |
485 | * A notification (both event and fragment) includes a status indicating weather | ||
486 | * the FW was able to schedule the event or not. For fragment start/end | ||
487 | * notification the status is always success. There is no start/end fragment | ||
488 | * notification for monolithic events. | ||
489 | * | ||
490 | * @TE_NOTIF_NONE: no notifications | ||
491 | * @TE_NOTIF_HOST_EVENT_START: request/receive notification on event start | ||
492 | * @TE_NOTIF_HOST_EVENT_END:request/receive notification on event end | ||
493 | * @TE_NOTIF_INTERNAL_EVENT_START: internal FW use | ||
494 | * @TE_NOTIF_INTERNAL_EVENT_END: internal FW use. | ||
495 | * @TE_NOTIF_HOST_FRAG_START: request/receive notification on frag start | ||
496 | * @TE_NOTIF_HOST_FRAG_END:request/receive notification on frag end | ||
497 | * @TE_NOTIF_INTERNAL_FRAG_START: internal FW use. | ||
498 | * @TE_NOTIF_INTERNAL_FRAG_END: internal FW use. | ||
499 | */ | ||
508 | enum { | 500 | enum { |
509 | TE_NOTIF_NONE = 0, | 501 | TE_NOTIF_NONE = 0, |
510 | TE_NOTIF_HOST_START = 0x1, | 502 | TE_NOTIF_HOST_EVENT_START = 0x1, |
511 | TE_NOTIF_HOST_END = 0x2, | 503 | TE_NOTIF_HOST_EVENT_END = 0x2, |
512 | TE_NOTIF_INTERNAL_START = 0x4, | 504 | TE_NOTIF_INTERNAL_EVENT_START = 0x4, |
513 | TE_NOTIF_INTERNAL_END = 0x8 | 505 | TE_NOTIF_INTERNAL_EVENT_END = 0x8, |
514 | }; /* MAC_EVENT_ACTION_API_E_VER_1 */ | 506 | TE_NOTIF_HOST_FRAG_START = 0x10, |
507 | TE_NOTIF_HOST_FRAG_END = 0x20, | ||
508 | TE_NOTIF_INTERNAL_FRAG_START = 0x40, | ||
509 | TE_NOTIF_INTERNAL_FRAG_END = 0x80 | ||
510 | }; /* MAC_EVENT_ACTION_API_E_VER_2 */ | ||
515 | 511 | ||
516 | /* | 512 | /* |
517 | * @TE_FRAG_NONE: fragmentation of the time event is NOT allowed. | 513 | * @TE_FRAG_NONE: fragmentation of the time event is NOT allowed. |
@@ -762,18 +758,20 @@ struct iwl_phy_context_cmd { | |||
762 | #define IWL_RX_INFO_PHY_CNT 8 | 758 | #define IWL_RX_INFO_PHY_CNT 8 |
763 | #define IWL_RX_INFO_AGC_IDX 1 | 759 | #define IWL_RX_INFO_AGC_IDX 1 |
764 | #define IWL_RX_INFO_RSSI_AB_IDX 2 | 760 | #define IWL_RX_INFO_RSSI_AB_IDX 2 |
765 | #define IWL_RX_INFO_RSSI_C_IDX 3 | 761 | #define IWL_OFDM_AGC_A_MSK 0x0000007f |
766 | #define IWL_OFDM_AGC_DB_MSK 0xfe00 | 762 | #define IWL_OFDM_AGC_A_POS 0 |
767 | #define IWL_OFDM_AGC_DB_POS 9 | 763 | #define IWL_OFDM_AGC_B_MSK 0x00003f80 |
764 | #define IWL_OFDM_AGC_B_POS 7 | ||
765 | #define IWL_OFDM_AGC_CODE_MSK 0x3fe00000 | ||
766 | #define IWL_OFDM_AGC_CODE_POS 20 | ||
768 | #define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff | 767 | #define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff |
769 | #define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00 | ||
770 | #define IWL_OFDM_RSSI_A_POS 0 | 768 | #define IWL_OFDM_RSSI_A_POS 0 |
769 | #define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00 | ||
770 | #define IWL_OFDM_RSSI_ALLBAND_A_POS 8 | ||
771 | #define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000 | 771 | #define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000 |
772 | #define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000 | ||
773 | #define IWL_OFDM_RSSI_B_POS 16 | 772 | #define IWL_OFDM_RSSI_B_POS 16 |
774 | #define IWL_OFDM_RSSI_INBAND_C_MSK 0x00ff | 773 | #define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000 |
775 | #define IWL_OFDM_RSSI_ALLBAND_C_MSK 0xff00 | 774 | #define IWL_OFDM_RSSI_ALLBAND_B_POS 24 |
776 | #define IWL_OFDM_RSSI_C_POS 0 | ||
777 | 775 | ||
778 | /** | 776 | /** |
779 | * struct iwl_rx_phy_info - phy info | 777 | * struct iwl_rx_phy_info - phy info |
@@ -792,6 +790,7 @@ struct iwl_phy_context_cmd { | |||
792 | * @byte_count: frame's byte-count | 790 | * @byte_count: frame's byte-count |
793 | * @frame_time: frame's time on the air, based on byte count and frame rate | 791 | * @frame_time: frame's time on the air, based on byte count and frame rate |
794 | * calculation | 792 | * calculation |
793 | * @mac_active_msk: what MACs were active when the frame was received | ||
795 | * | 794 | * |
796 | * Before each Rx, the device sends this data. It contains PHY information | 795 | * Before each Rx, the device sends this data. It contains PHY information |
797 | * about the reception of the packet. | 796 | * about the reception of the packet. |
@@ -809,7 +808,7 @@ struct iwl_rx_phy_info { | |||
809 | __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT]; | 808 | __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT]; |
810 | __le32 rate_n_flags; | 809 | __le32 rate_n_flags; |
811 | __le32 byte_count; | 810 | __le32 byte_count; |
812 | __le16 reserved2; | 811 | __le16 mac_active_msk; |
813 | __le16 frame_time; | 812 | __le16 frame_time; |
814 | } __packed; | 813 | } __packed; |
815 | 814 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index d3d959db03a9..e18c92dd60ec 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -79,17 +79,8 @@ | |||
79 | #define UCODE_VALID_OK cpu_to_le32(0x1) | 79 | #define UCODE_VALID_OK cpu_to_le32(0x1) |
80 | 80 | ||
81 | /* Default calibration values for WkP - set to INIT image w/o running */ | 81 | /* Default calibration values for WkP - set to INIT image w/o running */ |
82 | static const u8 wkp_calib_values_bb_filter[] = { 0xbf, 0x00, 0x5f, 0x00, 0x2f, | ||
83 | 0x00, 0x18, 0x00 }; | ||
84 | static const u8 wkp_calib_values_rx_dc[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, | ||
85 | 0x7f, 0x7f, 0x7f }; | ||
86 | static const u8 wkp_calib_values_tx_lo[] = { 0x00, 0x00, 0x00, 0x00 }; | ||
87 | static const u8 wkp_calib_values_tx_iq[] = { 0xff, 0x00, 0xff, 0x00, 0x00, | ||
88 | 0x00 }; | ||
89 | static const u8 wkp_calib_values_rx_iq[] = { 0xff, 0x00, 0x00, 0x00 }; | ||
90 | static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 }; | 82 | static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 }; |
91 | static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 }; | 83 | static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 }; |
92 | static const u8 wkp_calib_values_xtal[] = { 0xd2, 0xd2 }; | ||
93 | 84 | ||
94 | struct iwl_calib_default_data { | 85 | struct iwl_calib_default_data { |
95 | u16 size; | 86 | u16 size; |
@@ -99,12 +90,7 @@ struct iwl_calib_default_data { | |||
99 | #define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf} | 90 | #define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf} |
100 | 91 | ||
101 | static const struct iwl_calib_default_data wkp_calib_default_data[12] = { | 92 | static const struct iwl_calib_default_data wkp_calib_default_data[12] = { |
102 | [5] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_dc), | ||
103 | [6] = CALIB_SIZE_N_DATA(wkp_calib_values_bb_filter), | ||
104 | [7] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_lo), | ||
105 | [8] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq), | ||
106 | [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew), | 93 | [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew), |
107 | [10] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq), | ||
108 | [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew), | 94 | [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew), |
109 | }; | 95 | }; |
110 | 96 | ||
@@ -128,7 +114,7 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant) | |||
128 | .valid = cpu_to_le32(valid_tx_ant), | 114 | .valid = cpu_to_le32(valid_tx_ant), |
129 | }; | 115 | }; |
130 | 116 | ||
131 | IWL_DEBUG_HC(mvm, "select valid tx ant: %u\n", valid_tx_ant); | 117 | IWL_DEBUG_FW(mvm, "select valid tx ant: %u\n", valid_tx_ant); |
132 | return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC, | 118 | return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC, |
133 | sizeof(tx_ant_cmd), &tx_ant_cmd); | 119 | sizeof(tx_ant_cmd), &tx_ant_cmd); |
134 | } | 120 | } |
@@ -148,9 +134,10 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
148 | alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr); | 134 | alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr); |
149 | 135 | ||
150 | alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK; | 136 | alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK; |
151 | IWL_DEBUG_FW(mvm, "Alive ucode status 0x%04x revision 0x%01X 0x%01X\n", | 137 | IWL_DEBUG_FW(mvm, |
138 | "Alive ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n", | ||
152 | le16_to_cpu(palive->status), palive->ver_type, | 139 | le16_to_cpu(palive->status), palive->ver_type, |
153 | palive->ver_subtype); | 140 | palive->ver_subtype, palive->flags); |
154 | 141 | ||
155 | return true; | 142 | return true; |
156 | } | 143 | } |
@@ -241,20 +228,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
241 | 228 | ||
242 | return 0; | 229 | return 0; |
243 | } | 230 | } |
244 | #define IWL_HW_REV_ID_RAINBOW 0x2 | ||
245 | #define IWL_PROJ_TYPE_LHP 0x5 | ||
246 | |||
247 | static u32 iwl_mvm_build_phy_cfg(struct iwl_mvm *mvm) | ||
248 | { | ||
249 | struct iwl_nvm_data *data = mvm->nvm_data; | ||
250 | /* Temp calls to static definitions, will be changed to CSR calls */ | ||
251 | u8 hw_rev_id = IWL_HW_REV_ID_RAINBOW; | ||
252 | u8 project_type = IWL_PROJ_TYPE_LHP; | ||
253 | |||
254 | return data->radio_cfg_dash | (data->radio_cfg_step << 2) | | ||
255 | (hw_rev_id << 4) | ((project_type & 0x7f) << 6) | | ||
256 | (data->valid_tx_ant << 16) | (data->valid_rx_ant << 20); | ||
257 | } | ||
258 | 231 | ||
259 | static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) | 232 | static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) |
260 | { | 233 | { |
@@ -262,7 +235,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) | |||
262 | enum iwl_ucode_type ucode_type = mvm->cur_ucode; | 235 | enum iwl_ucode_type ucode_type = mvm->cur_ucode; |
263 | 236 | ||
264 | /* Set parameters */ | 237 | /* Set parameters */ |
265 | phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_build_phy_cfg(mvm)); | 238 | phy_cfg_cmd.phy_cfg = cpu_to_le32(mvm->fw->phy_config); |
266 | phy_cfg_cmd.calib_control.event_trigger = | 239 | phy_cfg_cmd.calib_control.event_trigger = |
267 | mvm->fw->default_calib[ucode_type].event_trigger; | 240 | mvm->fw->default_calib[ucode_type].event_trigger; |
268 | phy_cfg_cmd.calib_control.flow_trigger = | 241 | phy_cfg_cmd.calib_control.flow_trigger = |
@@ -275,103 +248,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) | |||
275 | sizeof(phy_cfg_cmd), &phy_cfg_cmd); | 248 | sizeof(phy_cfg_cmd), &phy_cfg_cmd); |
276 | } | 249 | } |
277 | 250 | ||
278 | /* Starting with the new PHY DB implementation - New calibs are enabled */ | ||
279 | /* Value - 0x405e7 */ | ||
280 | #define IWL_CALIB_DEFAULT_FLOW_INIT (IWL_CALIB_CFG_XTAL_IDX |\ | ||
281 | IWL_CALIB_CFG_TEMPERATURE_IDX |\ | ||
282 | IWL_CALIB_CFG_VOLTAGE_READ_IDX |\ | ||
283 | IWL_CALIB_CFG_DC_IDX |\ | ||
284 | IWL_CALIB_CFG_BB_FILTER_IDX |\ | ||
285 | IWL_CALIB_CFG_LO_LEAKAGE_IDX |\ | ||
286 | IWL_CALIB_CFG_TX_IQ_IDX |\ | ||
287 | IWL_CALIB_CFG_RX_IQ_IDX |\ | ||
288 | IWL_CALIB_CFG_AGC_IDX) | ||
289 | |||
290 | #define IWL_CALIB_DEFAULT_EVENT_INIT 0x0 | ||
291 | |||
292 | /* Value 0x41567 */ | ||
293 | #define IWL_CALIB_DEFAULT_FLOW_RUN (IWL_CALIB_CFG_XTAL_IDX |\ | ||
294 | IWL_CALIB_CFG_TEMPERATURE_IDX |\ | ||
295 | IWL_CALIB_CFG_VOLTAGE_READ_IDX |\ | ||
296 | IWL_CALIB_CFG_BB_FILTER_IDX |\ | ||
297 | IWL_CALIB_CFG_DC_IDX |\ | ||
298 | IWL_CALIB_CFG_TX_IQ_IDX |\ | ||
299 | IWL_CALIB_CFG_RX_IQ_IDX |\ | ||
300 | IWL_CALIB_CFG_SENSITIVITY_IDX |\ | ||
301 | IWL_CALIB_CFG_AGC_IDX) | ||
302 | |||
303 | #define IWL_CALIB_DEFAULT_EVENT_RUN (IWL_CALIB_CFG_XTAL_IDX |\ | ||
304 | IWL_CALIB_CFG_TEMPERATURE_IDX |\ | ||
305 | IWL_CALIB_CFG_VOLTAGE_READ_IDX |\ | ||
306 | IWL_CALIB_CFG_TX_PWR_IDX |\ | ||
307 | IWL_CALIB_CFG_DC_IDX |\ | ||
308 | IWL_CALIB_CFG_TX_IQ_IDX |\ | ||
309 | IWL_CALIB_CFG_SENSITIVITY_IDX) | ||
310 | |||
311 | /* | ||
312 | * Sets the calibrations trigger values that will be sent to the FW for runtime | ||
313 | * and init calibrations. | ||
314 | * The ones given in the FW TLV are not correct. | ||
315 | */ | ||
316 | static void iwl_set_default_calib_trigger(struct iwl_mvm *mvm) | ||
317 | { | ||
318 | struct iwl_tlv_calib_ctrl default_calib; | ||
319 | |||
320 | /* | ||
321 | * WkP FW TLV calib bits are wrong, overwrite them. | ||
322 | * This defines the dynamic calibrations which are implemented in the | ||
323 | * uCode both for init(flow) calculation and event driven calibs. | ||
324 | */ | ||
325 | |||
326 | /* Init Image */ | ||
327 | default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_INIT); | ||
328 | default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_INIT); | ||
329 | |||
330 | if (default_calib.event_trigger != | ||
331 | mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger) | ||
332 | IWL_ERR(mvm, | ||
333 | "Updating the event calib for INIT image: 0x%x -> 0x%x\n", | ||
334 | mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger, | ||
335 | default_calib.event_trigger); | ||
336 | if (default_calib.flow_trigger != | ||
337 | mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger) | ||
338 | IWL_ERR(mvm, | ||
339 | "Updating the flow calib for INIT image: 0x%x -> 0x%x\n", | ||
340 | mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger, | ||
341 | default_calib.flow_trigger); | ||
342 | |||
343 | memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_INIT], | ||
344 | &default_calib, sizeof(struct iwl_tlv_calib_ctrl)); | ||
345 | IWL_ERR(mvm, | ||
346 | "Setting uCode init calibrations event 0x%x, trigger 0x%x\n", | ||
347 | default_calib.event_trigger, | ||
348 | default_calib.flow_trigger); | ||
349 | |||
350 | /* Run time image */ | ||
351 | default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_RUN); | ||
352 | default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_RUN); | ||
353 | |||
354 | if (default_calib.event_trigger != | ||
355 | mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger) | ||
356 | IWL_ERR(mvm, | ||
357 | "Updating the event calib for RT image: 0x%x -> 0x%x\n", | ||
358 | mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger, | ||
359 | default_calib.event_trigger); | ||
360 | if (default_calib.flow_trigger != | ||
361 | mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger) | ||
362 | IWL_ERR(mvm, | ||
363 | "Updating the flow calib for RT image: 0x%x -> 0x%x\n", | ||
364 | mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger, | ||
365 | default_calib.flow_trigger); | ||
366 | |||
367 | memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_REGULAR], | ||
368 | &default_calib, sizeof(struct iwl_tlv_calib_ctrl)); | ||
369 | IWL_ERR(mvm, | ||
370 | "Setting uCode runtime calibs event 0x%x, trigger 0x%x\n", | ||
371 | default_calib.event_trigger, | ||
372 | default_calib.flow_trigger); | ||
373 | } | ||
374 | |||
375 | static int iwl_set_default_calibrations(struct iwl_mvm *mvm) | 251 | static int iwl_set_default_calibrations(struct iwl_mvm *mvm) |
376 | { | 252 | { |
377 | u8 cmd_raw[16]; /* holds the variable size commands */ | 253 | u8 cmd_raw[16]; /* holds the variable size commands */ |
@@ -434,6 +310,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
434 | goto error; | 310 | goto error; |
435 | } | 311 | } |
436 | 312 | ||
313 | ret = iwl_send_bt_prio_tbl(mvm); | ||
314 | if (ret) | ||
315 | goto error; | ||
316 | |||
437 | if (read_nvm) { | 317 | if (read_nvm) { |
438 | /* Read nvm */ | 318 | /* Read nvm */ |
439 | ret = iwl_nvm_init(mvm); | 319 | ret = iwl_nvm_init(mvm); |
@@ -446,15 +326,15 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
446 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); | 326 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); |
447 | WARN_ON(ret); | 327 | WARN_ON(ret); |
448 | 328 | ||
449 | /* Override the calibrations from TLV and the const of fw */ | 329 | /* Send TX valid antennas before triggering calibrations */ |
450 | iwl_set_default_calib_trigger(mvm); | 330 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); |
331 | if (ret) | ||
332 | goto error; | ||
451 | 333 | ||
452 | /* WkP doesn't have all calibrations, need to set default values */ | 334 | /* need to set default values */ |
453 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 335 | ret = iwl_set_default_calibrations(mvm); |
454 | ret = iwl_set_default_calibrations(mvm); | 336 | if (ret) |
455 | if (ret) | 337 | goto error; |
456 | goto error; | ||
457 | } | ||
458 | 338 | ||
459 | /* | 339 | /* |
460 | * Send phy configurations command to init uCode | 340 | * Send phy configurations command to init uCode |
@@ -533,7 +413,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
533 | goto error; | 413 | goto error; |
534 | } | 414 | } |
535 | 415 | ||
536 | ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant); | 416 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); |
417 | if (ret) | ||
418 | goto error; | ||
419 | |||
420 | ret = iwl_send_bt_prio_tbl(mvm); | ||
421 | if (ret) | ||
422 | goto error; | ||
423 | |||
424 | ret = iwl_send_bt_init_conf(mvm); | ||
537 | if (ret) | 425 | if (ret) |
538 | goto error; | 426 | goto error; |
539 | 427 | ||
@@ -579,7 +467,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm) | |||
579 | goto error; | 467 | goto error; |
580 | } | 468 | } |
581 | 469 | ||
582 | ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant); | 470 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); |
583 | if (ret) | 471 | if (ret) |
584 | goto error; | 472 | goto error; |
585 | 473 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/led.c b/drivers/net/wireless/iwlwifi/mvm/led.c index 011906e73a05..2269a9e5cc67 100644 --- a/drivers/net/wireless/iwlwifi/mvm/led.c +++ b/drivers/net/wireless/iwlwifi/mvm/led.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 1d20287b1120..e6eca4d66f6c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -196,7 +196,7 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, | |||
196 | u32 qmask, ac; | 196 | u32 qmask, ac; |
197 | 197 | ||
198 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) | 198 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) |
199 | return BIT(IWL_OFFCHANNEL_QUEUE); | 199 | return BIT(IWL_MVM_OFFCHANNEL_QUEUE); |
200 | 200 | ||
201 | qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ? | 201 | qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ? |
202 | BIT(vif->cab_queue) : 0; | 202 | BIT(vif->cab_queue) : 0; |
@@ -553,9 +553,9 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, | |||
553 | if (vif->bss_conf.qos) | 553 | if (vif->bss_conf.qos) |
554 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); | 554 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); |
555 | 555 | ||
556 | /* Don't use cts to self as the fw doesn't support it currently. */ | ||
556 | if (vif->bss_conf.use_cts_prot) | 557 | if (vif->bss_conf.use_cts_prot) |
557 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT | | 558 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); |
558 | MAC_PROT_FLG_SELF_CTS_EN); | ||
559 | 559 | ||
560 | /* | 560 | /* |
561 | * I think that we should enable these 2 flags regardless the HT PROT | 561 | * I think that we should enable these 2 flags regardless the HT PROT |
@@ -651,6 +651,13 @@ static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm, | |||
651 | /* Fill the common data for all mac context types */ | 651 | /* Fill the common data for all mac context types */ |
652 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 652 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
653 | 653 | ||
654 | /* Allow beacons to pass through as long as we are not associated,or we | ||
655 | * do not have dtim period information */ | ||
656 | if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period) | ||
657 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); | ||
658 | else | ||
659 | cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON); | ||
660 | |||
654 | /* Fill the data specific for station mode */ | 661 | /* Fill the data specific for station mode */ |
655 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta); | 662 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta); |
656 | 663 | ||
@@ -687,7 +694,12 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm, | |||
687 | WARN_ON(vif->type != NL80211_IFTYPE_MONITOR); | 694 | WARN_ON(vif->type != NL80211_IFTYPE_MONITOR); |
688 | 695 | ||
689 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 696 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
690 | /* No other data to be filled */ | 697 | |
698 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC | | ||
699 | MAC_FILTER_IN_CONTROL_AND_MGMT | | ||
700 | MAC_FILTER_IN_BEACON | | ||
701 | MAC_FILTER_IN_PROBE_REQUEST); | ||
702 | |||
691 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 703 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
692 | } | 704 | } |
693 | 705 | ||
@@ -716,7 +728,9 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm, | |||
716 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 728 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
717 | 729 | ||
718 | cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); | 730 | cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); |
719 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROMISC); | 731 | |
732 | /* Override the filter flags to accept only probe requests */ | ||
733 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); | ||
720 | 734 | ||
721 | /* | 735 | /* |
722 | * This flag should be set to true when the P2P Device is | 736 | * This flag should be set to true when the P2P Device is |
@@ -791,7 +805,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | |||
791 | TX_CMD_FLG_TSF); | 805 | TX_CMD_FLG_TSF); |
792 | 806 | ||
793 | mvm->mgmt_last_antenna_idx = | 807 | mvm->mgmt_last_antenna_idx = |
794 | iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant, | 808 | iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw), |
795 | mvm->mgmt_last_antenna_idx); | 809 | mvm->mgmt_last_antenna_idx); |
796 | 810 | ||
797 | beacon_cmd.tx.rate_n_flags = | 811 | beacon_cmd.tx.rate_n_flags = |
@@ -848,10 +862,10 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, | |||
848 | */ | 862 | */ |
849 | static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, | 863 | static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, |
850 | struct ieee80211_vif *vif, | 864 | struct ieee80211_vif *vif, |
851 | struct iwl_mac_data_ap *ctxt_ap) | 865 | struct iwl_mac_data_ap *ctxt_ap, |
866 | bool add) | ||
852 | { | 867 | { |
853 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 868 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
854 | u32 curr_dev_time; | ||
855 | 869 | ||
856 | ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int); | 870 | ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int); |
857 | ctxt_ap->bi_reciprocal = | 871 | ctxt_ap->bi_reciprocal = |
@@ -863,10 +877,19 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, | |||
863 | vif->bss_conf.dtim_period)); | 877 | vif->bss_conf.dtim_period)); |
864 | 878 | ||
865 | ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue); | 879 | ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue); |
866 | curr_dev_time = iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG); | ||
867 | ctxt_ap->beacon_time = cpu_to_le32(curr_dev_time); | ||
868 | 880 | ||
869 | ctxt_ap->beacon_tsf = cpu_to_le64(curr_dev_time); | 881 | /* |
882 | * Only read the system time when the MAC is being added, when we | ||
883 | * just modify the MAC then we should keep the time -- the firmware | ||
884 | * can otherwise have a "jumping" TBTT. | ||
885 | */ | ||
886 | if (add) | ||
887 | mvmvif->ap_beacon_time = | ||
888 | iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG); | ||
889 | |||
890 | ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time); | ||
891 | |||
892 | ctxt_ap->beacon_tsf = 0; /* unused */ | ||
870 | 893 | ||
871 | /* TODO: Assume that the beacon id == mac context id */ | 894 | /* TODO: Assume that the beacon id == mac context id */ |
872 | ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id); | 895 | ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id); |
@@ -883,8 +906,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, | |||
883 | /* Fill the common data for all mac context types */ | 906 | /* Fill the common data for all mac context types */ |
884 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 907 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
885 | 908 | ||
909 | /* Also enable probe requests to pass */ | ||
910 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); | ||
911 | |||
886 | /* Fill the data specific for ap mode */ | 912 | /* Fill the data specific for ap mode */ |
887 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap); | 913 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, |
914 | action == FW_CTXT_ACTION_ADD); | ||
888 | 915 | ||
889 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 916 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
890 | } | 917 | } |
@@ -902,7 +929,8 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm, | |||
902 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 929 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
903 | 930 | ||
904 | /* Fill the data specific for GO mode */ | 931 | /* Fill the data specific for GO mode */ |
905 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap); | 932 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap, |
933 | action == FW_CTXT_ACTION_ADD); | ||
906 | 934 | ||
907 | cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow & | 935 | cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow & |
908 | IEEE80211_P2P_OPPPS_CTWINDOW_MASK); | 936 | IEEE80211_P2P_OPPPS_CTWINDOW_MASK); |
@@ -996,3 +1024,22 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
996 | mvmvif->uploaded = false; | 1024 | mvmvif->uploaded = false; |
997 | return 0; | 1025 | return 0; |
998 | } | 1026 | } |
1027 | |||
1028 | int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | ||
1029 | struct iwl_rx_cmd_buffer *rxb, | ||
1030 | struct iwl_device_cmd *cmd) | ||
1031 | { | ||
1032 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1033 | struct iwl_beacon_notif *beacon = (void *)pkt->data; | ||
1034 | u16 status __maybe_unused = | ||
1035 | le16_to_cpu(beacon->beacon_notify_hdr.status.status); | ||
1036 | u32 rate __maybe_unused = | ||
1037 | le32_to_cpu(beacon->beacon_notify_hdr.initial_rate); | ||
1038 | |||
1039 | IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n", | ||
1040 | status & TX_STATUS_MSK, | ||
1041 | beacon->beacon_notify_hdr.failure_frame, | ||
1042 | le64_to_cpu(beacon->tsf), | ||
1043 | rate); | ||
1044 | return 0; | ||
1045 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 23460f4a4c75..fe031608fd91 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -65,7 +65,9 @@ | |||
65 | #include <linux/skbuff.h> | 65 | #include <linux/skbuff.h> |
66 | #include <linux/netdevice.h> | 66 | #include <linux/netdevice.h> |
67 | #include <linux/etherdevice.h> | 67 | #include <linux/etherdevice.h> |
68 | #include <linux/ip.h> | ||
68 | #include <net/mac80211.h> | 69 | #include <net/mac80211.h> |
70 | #include <net/tcp.h> | ||
69 | 71 | ||
70 | #include "iwl-op-mode.h" | 72 | #include "iwl-op-mode.h" |
71 | #include "iwl-io.h" | 73 | #include "iwl-io.h" |
@@ -102,10 +104,33 @@ static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = { | |||
102 | }, | 104 | }, |
103 | }; | 105 | }; |
104 | 106 | ||
107 | #ifdef CONFIG_PM_SLEEP | ||
108 | static const struct nl80211_wowlan_tcp_data_token_feature | ||
109 | iwl_mvm_wowlan_tcp_token_feature = { | ||
110 | .min_len = 0, | ||
111 | .max_len = 255, | ||
112 | .bufsize = IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS, | ||
113 | }; | ||
114 | |||
115 | static const struct wiphy_wowlan_tcp_support iwl_mvm_wowlan_tcp_support = { | ||
116 | .tok = &iwl_mvm_wowlan_tcp_token_feature, | ||
117 | .data_payload_max = IWL_WOWLAN_TCP_MAX_PACKET_LEN - | ||
118 | sizeof(struct ethhdr) - | ||
119 | sizeof(struct iphdr) - | ||
120 | sizeof(struct tcphdr), | ||
121 | .data_interval_max = 65535, /* __le16 in API */ | ||
122 | .wake_payload_max = IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN - | ||
123 | sizeof(struct ethhdr) - | ||
124 | sizeof(struct iphdr) - | ||
125 | sizeof(struct tcphdr), | ||
126 | .seq = true, | ||
127 | }; | ||
128 | #endif | ||
129 | |||
105 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | 130 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) |
106 | { | 131 | { |
107 | struct ieee80211_hw *hw = mvm->hw; | 132 | struct ieee80211_hw *hw = mvm->hw; |
108 | int num_mac, ret; | 133 | int num_mac, ret, i; |
109 | 134 | ||
110 | /* Tell mac80211 our characteristics */ | 135 | /* Tell mac80211 our characteristics */ |
111 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 136 | hw->flags = IEEE80211_HW_SIGNAL_DBM | |
@@ -118,8 +143,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
118 | IEEE80211_HW_AMPDU_AGGREGATION | | 143 | IEEE80211_HW_AMPDU_AGGREGATION | |
119 | IEEE80211_HW_TIMING_BEACON_ONLY; | 144 | IEEE80211_HW_TIMING_BEACON_ONLY; |
120 | 145 | ||
121 | hw->queues = IWL_FIRST_AMPDU_QUEUE; | 146 | hw->queues = IWL_MVM_FIRST_AGG_QUEUE; |
122 | hw->offchannel_tx_hw_queue = IWL_OFFCHANNEL_QUEUE; | 147 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; |
123 | hw->rate_control_algorithm = "iwl-mvm-rs"; | 148 | hw->rate_control_algorithm = "iwl-mvm-rs"; |
124 | 149 | ||
125 | /* | 150 | /* |
@@ -149,18 +174,22 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
149 | hw->wiphy->n_iface_combinations = | 174 | hw->wiphy->n_iface_combinations = |
150 | ARRAY_SIZE(iwl_mvm_iface_combinations); | 175 | ARRAY_SIZE(iwl_mvm_iface_combinations); |
151 | 176 | ||
152 | hw->wiphy->max_remain_on_channel_duration = 500; | 177 | hw->wiphy->max_remain_on_channel_duration = 10000; |
153 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | 178 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; |
154 | 179 | ||
155 | /* Extract MAC address */ | 180 | /* Extract MAC address */ |
156 | memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); | 181 | memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); |
157 | hw->wiphy->addresses = mvm->addresses; | 182 | hw->wiphy->addresses = mvm->addresses; |
158 | hw->wiphy->n_addresses = 1; | 183 | hw->wiphy->n_addresses = 1; |
159 | num_mac = mvm->nvm_data->n_hw_addrs; | 184 | |
160 | if (num_mac > 1) { | 185 | /* Extract additional MAC addresses if available */ |
161 | memcpy(mvm->addresses[1].addr, mvm->addresses[0].addr, | 186 | num_mac = (mvm->nvm_data->n_hw_addrs > 1) ? |
187 | min(IWL_MVM_MAX_ADDRESSES, mvm->nvm_data->n_hw_addrs) : 1; | ||
188 | |||
189 | for (i = 1; i < num_mac; i++) { | ||
190 | memcpy(mvm->addresses[i].addr, mvm->addresses[i-1].addr, | ||
162 | ETH_ALEN); | 191 | ETH_ALEN); |
163 | mvm->addresses[1].addr[5]++; | 192 | mvm->addresses[i].addr[5]++; |
164 | hw->wiphy->n_addresses++; | 193 | hw->wiphy->n_addresses++; |
165 | } | 194 | } |
166 | 195 | ||
@@ -206,6 +235,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
206 | hw->wiphy->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS; | 235 | hw->wiphy->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS; |
207 | hw->wiphy->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN; | 236 | hw->wiphy->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN; |
208 | hw->wiphy->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN; | 237 | hw->wiphy->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN; |
238 | hw->wiphy->wowlan.tcp = &iwl_mvm_wowlan_tcp_support; | ||
209 | } | 239 | } |
210 | #endif | 240 | #endif |
211 | 241 | ||
@@ -227,7 +257,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, | |||
227 | goto drop; | 257 | goto drop; |
228 | } | 258 | } |
229 | 259 | ||
230 | if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_OFFCHANNEL_QUEUE && | 260 | if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE && |
231 | !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) | 261 | !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) |
232 | goto drop; | 262 | goto drop; |
233 | 263 | ||
@@ -273,12 +303,18 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
273 | ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false); | 303 | ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false); |
274 | break; | 304 | break; |
275 | case IEEE80211_AMPDU_TX_START: | 305 | case IEEE80211_AMPDU_TX_START: |
306 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) { | ||
307 | ret = -EINVAL; | ||
308 | break; | ||
309 | } | ||
276 | ret = iwl_mvm_sta_tx_agg_start(mvm, vif, sta, tid, ssn); | 310 | ret = iwl_mvm_sta_tx_agg_start(mvm, vif, sta, tid, ssn); |
277 | break; | 311 | break; |
278 | case IEEE80211_AMPDU_TX_STOP_CONT: | 312 | case IEEE80211_AMPDU_TX_STOP_CONT: |
313 | ret = iwl_mvm_sta_tx_agg_stop(mvm, vif, sta, tid); | ||
314 | break; | ||
279 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | 315 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
280 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | 316 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
281 | ret = iwl_mvm_sta_tx_agg_stop(mvm, vif, sta, tid); | 317 | ret = iwl_mvm_sta_tx_agg_flush(mvm, vif, sta, tid); |
282 | break; | 318 | break; |
283 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 319 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
284 | ret = iwl_mvm_sta_tx_agg_oper(mvm, vif, sta, tid, buf_size); | 320 | ret = iwl_mvm_sta_tx_agg_oper(mvm, vif, sta, tid, buf_size); |
@@ -466,11 +502,15 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
466 | /* | 502 | /* |
467 | * TODO: remove this temporary code. | 503 | * TODO: remove this temporary code. |
468 | * Currently MVM FW supports power management only on single MAC. | 504 | * Currently MVM FW supports power management only on single MAC. |
469 | * Iterate and disable PM on all active interfaces. | 505 | * If new interface added, disable PM on existing interface. |
506 | * P2P device is a special case, since it is handled by FW similary to | ||
507 | * scan. If P2P deviced is added, PM remains enabled on existing | ||
508 | * interface. | ||
470 | * Note: the method below does not count the new interface being added | 509 | * Note: the method below does not count the new interface being added |
471 | * at this moment. | 510 | * at this moment. |
472 | */ | 511 | */ |
473 | mvm->vif_count++; | 512 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) |
513 | mvm->vif_count++; | ||
474 | if (mvm->vif_count > 1) { | 514 | if (mvm->vif_count > 1) { |
475 | IWL_DEBUG_MAC80211(mvm, | 515 | IWL_DEBUG_MAC80211(mvm, |
476 | "Disable power on existing interfaces\n"); | 516 | "Disable power on existing interfaces\n"); |
@@ -526,6 +566,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
526 | mvm->p2p_device_vif = vif; | 566 | mvm->p2p_device_vif = vif; |
527 | } | 567 | } |
528 | 568 | ||
569 | iwl_mvm_vif_dbgfs_register(mvm, vif); | ||
529 | goto out_unlock; | 570 | goto out_unlock; |
530 | 571 | ||
531 | out_unbind: | 572 | out_unbind: |
@@ -539,10 +580,11 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
539 | /* | 580 | /* |
540 | * TODO: remove this temporary code. | 581 | * TODO: remove this temporary code. |
541 | * Currently MVM FW supports power management only on single MAC. | 582 | * Currently MVM FW supports power management only on single MAC. |
542 | * Check if only one additional interface remains after rereasing | 583 | * Check if only one additional interface remains after releasing |
543 | * current one. Update power mode on the remaining interface. | 584 | * current one. Update power mode on the remaining interface. |
544 | */ | 585 | */ |
545 | mvm->vif_count--; | 586 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) |
587 | mvm->vif_count--; | ||
546 | IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n", | 588 | IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n", |
547 | mvm->vif_count); | 589 | mvm->vif_count); |
548 | if (mvm->vif_count == 1) { | 590 | if (mvm->vif_count == 1) { |
@@ -557,11 +599,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
557 | return ret; | 599 | return ret; |
558 | } | 600 | } |
559 | 601 | ||
560 | static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | 602 | static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, |
561 | struct ieee80211_vif *vif) | 603 | struct ieee80211_vif *vif) |
562 | { | 604 | { |
563 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
564 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
565 | u32 tfd_msk = 0, ac; | 605 | u32 tfd_msk = 0, ac; |
566 | 606 | ||
567 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 607 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
@@ -594,12 +634,23 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
594 | */ | 634 | */ |
595 | flush_work(&mvm->sta_drained_wk); | 635 | flush_work(&mvm->sta_drained_wk); |
596 | } | 636 | } |
637 | } | ||
638 | |||
639 | static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | ||
640 | struct ieee80211_vif *vif) | ||
641 | { | ||
642 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
643 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
644 | |||
645 | iwl_mvm_prepare_mac_removal(mvm, vif); | ||
597 | 646 | ||
598 | mutex_lock(&mvm->mutex); | 647 | mutex_lock(&mvm->mutex); |
599 | 648 | ||
649 | iwl_mvm_vif_dbgfs_clean(mvm, vif); | ||
650 | |||
600 | /* | 651 | /* |
601 | * For AP/GO interface, the tear down of the resources allocated to the | 652 | * For AP/GO interface, the tear down of the resources allocated to the |
602 | * interface should be handled as part of the bss_info_changed flow. | 653 | * interface is be handled as part of the stop_ap flow. |
603 | */ | 654 | */ |
604 | if (vif->type == NL80211_IFTYPE_AP) { | 655 | if (vif->type == NL80211_IFTYPE_AP) { |
605 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); | 656 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); |
@@ -620,7 +671,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
620 | * Check if only one additional interface remains after removing | 671 | * Check if only one additional interface remains after removing |
621 | * current one. Update power mode on the remaining interface. | 672 | * current one. Update power mode on the remaining interface. |
622 | */ | 673 | */ |
623 | if (mvm->vif_count) | 674 | if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE) |
624 | mvm->vif_count--; | 675 | mvm->vif_count--; |
625 | IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n", | 676 | IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n", |
626 | mvm->vif_count); | 677 | mvm->vif_count); |
@@ -670,6 +721,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
670 | IWL_ERR(mvm, "failed to update quotas\n"); | 721 | IWL_ERR(mvm, "failed to update quotas\n"); |
671 | return; | 722 | return; |
672 | } | 723 | } |
724 | iwl_mvm_bt_coex_vif_assoc(mvm, vif); | ||
673 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { | 725 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { |
674 | /* remove AP station now that the MAC is unassoc */ | 726 | /* remove AP station now that the MAC is unassoc */ |
675 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); | 727 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); |
@@ -763,6 +815,8 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
763 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 815 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
764 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 816 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
765 | 817 | ||
818 | iwl_mvm_prepare_mac_removal(mvm, vif); | ||
819 | |||
766 | mutex_lock(&mvm->mutex); | 820 | mutex_lock(&mvm->mutex); |
767 | 821 | ||
768 | mvmvif->ap_active = false; | 822 | mvmvif->ap_active = false; |
@@ -886,7 +940,7 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | |||
886 | */ | 940 | */ |
887 | break; | 941 | break; |
888 | case STA_NOTIFY_AWAKE: | 942 | case STA_NOTIFY_AWAKE: |
889 | if (WARN_ON(mvmsta->sta_id == IWL_INVALID_STATION)) | 943 | if (WARN_ON(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) |
890 | break; | 944 | break; |
891 | iwl_mvm_sta_modify_ps_wake(mvm, sta); | 945 | iwl_mvm_sta_modify_ps_wake(mvm, sta); |
892 | break; | 946 | break; |
@@ -1042,6 +1096,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, | |||
1042 | 1096 | ||
1043 | switch (cmd) { | 1097 | switch (cmd) { |
1044 | case SET_KEY: | 1098 | case SET_KEY: |
1099 | if (vif->type == NL80211_IFTYPE_AP && !sta) { | ||
1100 | /* GTK on AP interface is a TX-only key, return 0 */ | ||
1101 | ret = 0; | ||
1102 | key->hw_key_idx = STA_KEY_IDX_INVALID; | ||
1103 | break; | ||
1104 | } | ||
1105 | |||
1045 | IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n"); | 1106 | IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n"); |
1046 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false); | 1107 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false); |
1047 | if (ret) { | 1108 | if (ret) { |
@@ -1050,11 +1111,17 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, | |||
1050 | * can't add key for RX, but we don't need it | 1111 | * can't add key for RX, but we don't need it |
1051 | * in the device for TX so still return 0 | 1112 | * in the device for TX so still return 0 |
1052 | */ | 1113 | */ |
1114 | key->hw_key_idx = STA_KEY_IDX_INVALID; | ||
1053 | ret = 0; | 1115 | ret = 0; |
1054 | } | 1116 | } |
1055 | 1117 | ||
1056 | break; | 1118 | break; |
1057 | case DISABLE_KEY: | 1119 | case DISABLE_KEY: |
1120 | if (key->hw_key_idx == STA_KEY_IDX_INVALID) { | ||
1121 | ret = 0; | ||
1122 | break; | ||
1123 | } | ||
1124 | |||
1058 | IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n"); | 1125 | IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n"); |
1059 | ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key); | 1126 | ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key); |
1060 | break; | 1127 | break; |
@@ -1103,7 +1170,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, | |||
1103 | &chandef, 1, 1); | 1170 | &chandef, 1, 1); |
1104 | 1171 | ||
1105 | /* Schedule the time events */ | 1172 | /* Schedule the time events */ |
1106 | ret = iwl_mvm_start_p2p_roc(mvm, vif, duration); | 1173 | ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type); |
1107 | 1174 | ||
1108 | mutex_unlock(&mvm->mutex); | 1175 | mutex_unlock(&mvm->mutex); |
1109 | IWL_DEBUG_MAC80211(mvm, "leave\n"); | 1176 | IWL_DEBUG_MAC80211(mvm, "leave\n"); |
@@ -1207,6 +1274,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
1207 | * will handle quota settings. | 1274 | * will handle quota settings. |
1208 | */ | 1275 | */ |
1209 | if (vif->type == NL80211_IFTYPE_MONITOR) { | 1276 | if (vif->type == NL80211_IFTYPE_MONITOR) { |
1277 | mvmvif->monitor_active = true; | ||
1210 | ret = iwl_mvm_update_quotas(mvm, vif); | 1278 | ret = iwl_mvm_update_quotas(mvm, vif); |
1211 | if (ret) | 1279 | if (ret) |
1212 | goto out_remove_binding; | 1280 | goto out_remove_binding; |
@@ -1237,15 +1305,16 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
1237 | if (vif->type == NL80211_IFTYPE_AP) | 1305 | if (vif->type == NL80211_IFTYPE_AP) |
1238 | goto out_unlock; | 1306 | goto out_unlock; |
1239 | 1307 | ||
1240 | iwl_mvm_binding_remove_vif(mvm, vif); | ||
1241 | switch (vif->type) { | 1308 | switch (vif->type) { |
1242 | case NL80211_IFTYPE_MONITOR: | 1309 | case NL80211_IFTYPE_MONITOR: |
1243 | iwl_mvm_update_quotas(mvm, vif); | 1310 | mvmvif->monitor_active = false; |
1311 | iwl_mvm_update_quotas(mvm, NULL); | ||
1244 | break; | 1312 | break; |
1245 | default: | 1313 | default: |
1246 | break; | 1314 | break; |
1247 | } | 1315 | } |
1248 | 1316 | ||
1317 | iwl_mvm_binding_remove_vif(mvm, vif); | ||
1249 | out_unlock: | 1318 | out_unlock: |
1250 | mvmvif->phy_ctxt = NULL; | 1319 | mvmvif->phy_ctxt = NULL; |
1251 | mutex_unlock(&mvm->mutex); | 1320 | mutex_unlock(&mvm->mutex); |
@@ -1266,6 +1335,15 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw, | |||
1266 | return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif); | 1335 | return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif); |
1267 | } | 1336 | } |
1268 | 1337 | ||
1338 | static void iwl_mvm_mac_rssi_callback(struct ieee80211_hw *hw, | ||
1339 | struct ieee80211_vif *vif, | ||
1340 | enum ieee80211_rssi_event rssi_event) | ||
1341 | { | ||
1342 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
1343 | |||
1344 | iwl_mvm_bt_rssi_event(mvm, vif, rssi_event); | ||
1345 | } | ||
1346 | |||
1269 | struct ieee80211_ops iwl_mvm_hw_ops = { | 1347 | struct ieee80211_ops iwl_mvm_hw_ops = { |
1270 | .tx = iwl_mvm_mac_tx, | 1348 | .tx = iwl_mvm_mac_tx, |
1271 | .ampdu_action = iwl_mvm_mac_ampdu_action, | 1349 | .ampdu_action = iwl_mvm_mac_ampdu_action, |
@@ -1289,6 +1367,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = { | |||
1289 | .update_tkip_key = iwl_mvm_mac_update_tkip_key, | 1367 | .update_tkip_key = iwl_mvm_mac_update_tkip_key, |
1290 | .remain_on_channel = iwl_mvm_roc, | 1368 | .remain_on_channel = iwl_mvm_roc, |
1291 | .cancel_remain_on_channel = iwl_mvm_cancel_roc, | 1369 | .cancel_remain_on_channel = iwl_mvm_cancel_roc, |
1370 | .rssi_callback = iwl_mvm_mac_rssi_callback, | ||
1292 | 1371 | ||
1293 | .add_chanctx = iwl_mvm_add_chanctx, | 1372 | .add_chanctx = iwl_mvm_add_chanctx, |
1294 | .remove_chanctx = iwl_mvm_remove_chanctx, | 1373 | .remove_chanctx = iwl_mvm_remove_chanctx, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 4e339ccfa800..8269bc562951 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -79,8 +79,9 @@ | |||
79 | #include "fw-api.h" | 79 | #include "fw-api.h" |
80 | 80 | ||
81 | #define IWL_INVALID_MAC80211_QUEUE 0xff | 81 | #define IWL_INVALID_MAC80211_QUEUE 0xff |
82 | #define IWL_MVM_MAX_ADDRESSES 2 | 82 | #define IWL_MVM_MAX_ADDRESSES 5 |
83 | #define IWL_RSSI_OFFSET 44 | 83 | /* RSSI offset for WkP */ |
84 | #define IWL_RSSI_OFFSET 50 | ||
84 | 85 | ||
85 | enum iwl_mvm_tx_fifo { | 86 | enum iwl_mvm_tx_fifo { |
86 | IWL_MVM_TX_FIFO_BK = 0, | 87 | IWL_MVM_TX_FIFO_BK = 0, |
@@ -89,10 +90,6 @@ enum iwl_mvm_tx_fifo { | |||
89 | IWL_MVM_TX_FIFO_VO, | 90 | IWL_MVM_TX_FIFO_VO, |
90 | }; | 91 | }; |
91 | 92 | ||
92 | /* Placeholder */ | ||
93 | #define IWL_OFFCHANNEL_QUEUE 8 | ||
94 | #define IWL_FIRST_AMPDU_QUEUE 11 | ||
95 | |||
96 | extern struct ieee80211_ops iwl_mvm_hw_ops; | 93 | extern struct ieee80211_ops iwl_mvm_hw_ops; |
97 | /** | 94 | /** |
98 | * struct iwl_mvm_mod_params - module parameters for iwlmvm | 95 | * struct iwl_mvm_mod_params - module parameters for iwlmvm |
@@ -160,6 +157,8 @@ enum iwl_power_scheme { | |||
160 | * @uploaded: indicates the MAC context has been added to the device | 157 | * @uploaded: indicates the MAC context has been added to the device |
161 | * @ap_active: indicates that ap context is configured, and that the interface | 158 | * @ap_active: indicates that ap context is configured, and that the interface |
162 | * should get quota etc. | 159 | * should get quota etc. |
160 | * @monitor_active: indicates that monitor context is configured, and that the | ||
161 | * interface should get quota etc. | ||
163 | * @queue_params: QoS params for this MAC | 162 | * @queue_params: QoS params for this MAC |
164 | * @bcast_sta: station used for broadcast packets. Used by the following | 163 | * @bcast_sta: station used for broadcast packets. Used by the following |
165 | * vifs: P2P_DEVICE, GO and AP. | 164 | * vifs: P2P_DEVICE, GO and AP. |
@@ -172,6 +171,9 @@ struct iwl_mvm_vif { | |||
172 | 171 | ||
173 | bool uploaded; | 172 | bool uploaded; |
174 | bool ap_active; | 173 | bool ap_active; |
174 | bool monitor_active; | ||
175 | |||
176 | u32 ap_beacon_time; | ||
175 | 177 | ||
176 | enum iwl_tsf_id tsf_id; | 178 | enum iwl_tsf_id tsf_id; |
177 | 179 | ||
@@ -210,6 +212,7 @@ struct iwl_mvm_vif { | |||
210 | 212 | ||
211 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 213 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
212 | struct dentry *dbgfs_dir; | 214 | struct dentry *dbgfs_dir; |
215 | struct dentry *dbgfs_slink; | ||
213 | void *dbgfs_data; | 216 | void *dbgfs_data; |
214 | #endif | 217 | #endif |
215 | }; | 218 | }; |
@@ -278,10 +281,7 @@ struct iwl_mvm { | |||
278 | atomic_t queue_stop_count[IWL_MAX_HW_QUEUES]; | 281 | atomic_t queue_stop_count[IWL_MAX_HW_QUEUES]; |
279 | 282 | ||
280 | struct iwl_nvm_data *nvm_data; | 283 | struct iwl_nvm_data *nvm_data; |
281 | /* eeprom blob for debugfs/testmode */ | 284 | /* NVM sections */ |
282 | u8 *eeprom_blob; | ||
283 | size_t eeprom_blob_size; | ||
284 | /* NVM sections for 7000 family */ | ||
285 | struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS]; | 285 | struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS]; |
286 | 286 | ||
287 | /* EEPROM MAC addresses */ | 287 | /* EEPROM MAC addresses */ |
@@ -322,11 +322,26 @@ struct iwl_mvm { | |||
322 | * can hold 16 keys at most. Reflect this fact. | 322 | * can hold 16 keys at most. Reflect this fact. |
323 | */ | 323 | */ |
324 | unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; | 324 | unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; |
325 | |||
326 | /* | ||
327 | * This counter of created interfaces is referenced only in conjunction | ||
328 | * with FW limitation related to power management. Currently PM is | ||
329 | * supported only on a single interface. | ||
330 | * IMPORTANT: this variable counts all interfaces except P2P device. | ||
331 | */ | ||
325 | u8 vif_count; | 332 | u8 vif_count; |
326 | 333 | ||
327 | struct led_classdev led; | 334 | struct led_classdev led; |
328 | 335 | ||
329 | struct ieee80211_vif *p2p_device_vif; | 336 | struct ieee80211_vif *p2p_device_vif; |
337 | |||
338 | #ifdef CONFIG_PM_SLEEP | ||
339 | int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; | ||
340 | #endif | ||
341 | |||
342 | /* BT-Coex */ | ||
343 | u8 bt_kill_msk; | ||
344 | struct iwl_bt_coex_profile_notif last_bt_notif; | ||
330 | }; | 345 | }; |
331 | 346 | ||
332 | /* Extract MVM priv from op_mode and _hw */ | 347 | /* Extract MVM priv from op_mode and _hw */ |
@@ -440,6 +455,9 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, | |||
440 | struct ieee80211_vif *vif); | 455 | struct ieee80211_vif *vif); |
441 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, | 456 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, |
442 | struct ieee80211_vif *vif); | 457 | struct ieee80211_vif *vif); |
458 | int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | ||
459 | struct iwl_rx_cmd_buffer *rxb, | ||
460 | struct iwl_device_cmd *cmd); | ||
443 | 461 | ||
444 | /* Bindings */ | 462 | /* Bindings */ |
445 | int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 463 | int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
@@ -461,16 +479,22 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm); | |||
461 | /* MVM debugfs */ | 479 | /* MVM debugfs */ |
462 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 480 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
463 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir); | 481 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir); |
464 | int iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 482 | void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
465 | struct dentry *dbgfs_dir); | 483 | void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
466 | void iwl_power_get_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
467 | struct iwl_powertable_cmd *cmd); | ||
468 | #else | 484 | #else |
469 | static inline int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, | 485 | static inline int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, |
470 | struct dentry *dbgfs_dir) | 486 | struct dentry *dbgfs_dir) |
471 | { | 487 | { |
472 | return 0; | 488 | return 0; |
473 | } | 489 | } |
490 | static inline void | ||
491 | iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
492 | { | ||
493 | } | ||
494 | static inline void | ||
495 | iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
496 | { | ||
497 | } | ||
474 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 498 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
475 | 499 | ||
476 | /* rate scaling */ | 500 | /* rate scaling */ |
@@ -480,6 +504,8 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, | |||
480 | /* power managment */ | 504 | /* power managment */ |
481 | int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 505 | int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
482 | int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 506 | int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
507 | void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
508 | struct iwl_powertable_cmd *cmd); | ||
483 | 509 | ||
484 | int iwl_mvm_leds_init(struct iwl_mvm *mvm); | 510 | int iwl_mvm_leds_init(struct iwl_mvm *mvm); |
485 | void iwl_mvm_leds_exit(struct iwl_mvm *mvm); | 511 | void iwl_mvm_leds_exit(struct iwl_mvm *mvm); |
@@ -497,4 +523,14 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw, | |||
497 | void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, | 523 | void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, |
498 | struct ieee80211_vif *vif, int idx); | 524 | struct ieee80211_vif *vif, int idx); |
499 | 525 | ||
526 | /* BT Coex */ | ||
527 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); | ||
528 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm); | ||
529 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | ||
530 | struct iwl_rx_cmd_buffer *rxb, | ||
531 | struct iwl_device_cmd *cmd); | ||
532 | void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
533 | enum ieee80211_rssi_event rssi_event); | ||
534 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | ||
535 | |||
500 | #endif /* __IWL_MVM_H__ */ | 536 | #endif /* __IWL_MVM_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 20016bcbdeab..b8ec02f89acc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -74,26 +74,11 @@ static const int nvm_to_read[] = { | |||
74 | NVM_SECTION_TYPE_PRODUCTION, | 74 | NVM_SECTION_TYPE_PRODUCTION, |
75 | }; | 75 | }; |
76 | 76 | ||
77 | /* used to simplify the shared operations on NCM_ACCESS_CMD versions */ | 77 | /* Default NVM size to read */ |
78 | union iwl_nvm_access_cmd { | 78 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024); |
79 | struct iwl_nvm_access_cmd_ver1 ver1; | ||
80 | struct iwl_nvm_access_cmd_ver2 ver2; | ||
81 | }; | ||
82 | union iwl_nvm_access_resp { | ||
83 | struct iwl_nvm_access_resp_ver1 ver1; | ||
84 | struct iwl_nvm_access_resp_ver2 ver2; | ||
85 | }; | ||
86 | |||
87 | static inline void iwl_nvm_fill_read_ver1(struct iwl_nvm_access_cmd_ver1 *cmd, | ||
88 | u16 offset, u16 length) | ||
89 | { | ||
90 | cmd->offset = cpu_to_le16(offset); | ||
91 | cmd->length = cpu_to_le16(length); | ||
92 | cmd->cache_refresh = 1; | ||
93 | } | ||
94 | 79 | ||
95 | static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd, | 80 | static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd, |
96 | u16 offset, u16 length, u16 section) | 81 | u16 offset, u16 length, u16 section) |
97 | { | 82 | { |
98 | cmd->offset = cpu_to_le16(offset); | 83 | cmd->offset = cpu_to_le16(offset); |
99 | cmd->length = cpu_to_le16(length); | 84 | cmd->length = cpu_to_le16(length); |
@@ -103,8 +88,8 @@ static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd, | |||
103 | static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | 88 | static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, |
104 | u16 offset, u16 length, u8 *data) | 89 | u16 offset, u16 length, u8 *data) |
105 | { | 90 | { |
106 | union iwl_nvm_access_cmd nvm_access_cmd; | 91 | struct iwl_nvm_access_cmd nvm_access_cmd = {}; |
107 | union iwl_nvm_access_resp *nvm_resp; | 92 | struct iwl_nvm_access_resp *nvm_resp; |
108 | struct iwl_rx_packet *pkt; | 93 | struct iwl_rx_packet *pkt; |
109 | struct iwl_host_cmd cmd = { | 94 | struct iwl_host_cmd cmd = { |
110 | .id = NVM_ACCESS_CMD, | 95 | .id = NVM_ACCESS_CMD, |
@@ -114,18 +99,8 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | |||
114 | int ret, bytes_read, offset_read; | 99 | int ret, bytes_read, offset_read; |
115 | u8 *resp_data; | 100 | u8 *resp_data; |
116 | 101 | ||
117 | memset(&nvm_access_cmd, 0, sizeof(nvm_access_cmd)); | 102 | iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section); |
118 | 103 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd); | |
119 | /* TODO: not sure family should be the decider, maybe FW version? */ | ||
120 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | ||
121 | iwl_nvm_fill_read_ver2(&(nvm_access_cmd.ver2), | ||
122 | offset, length, section); | ||
123 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver2); | ||
124 | } else { | ||
125 | iwl_nvm_fill_read_ver1(&(nvm_access_cmd.ver1), | ||
126 | offset, length); | ||
127 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver1); | ||
128 | } | ||
129 | 104 | ||
130 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 105 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
131 | if (ret) | 106 | if (ret) |
@@ -141,17 +116,10 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | |||
141 | 116 | ||
142 | /* Extract NVM response */ | 117 | /* Extract NVM response */ |
143 | nvm_resp = (void *)pkt->data; | 118 | nvm_resp = (void *)pkt->data; |
144 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 119 | ret = le16_to_cpu(nvm_resp->status); |
145 | ret = le16_to_cpu(nvm_resp->ver2.status); | 120 | bytes_read = le16_to_cpu(nvm_resp->length); |
146 | bytes_read = le16_to_cpu(nvm_resp->ver2.length); | 121 | offset_read = le16_to_cpu(nvm_resp->offset); |
147 | offset_read = le16_to_cpu(nvm_resp->ver2.offset); | 122 | resp_data = nvm_resp->data; |
148 | resp_data = nvm_resp->ver2.data; | ||
149 | } else { | ||
150 | ret = le16_to_cpu(nvm_resp->ver1.length) <= 0; | ||
151 | bytes_read = le16_to_cpu(nvm_resp->ver1.length); | ||
152 | offset_read = le16_to_cpu(nvm_resp->ver1.offset); | ||
153 | resp_data = nvm_resp->ver1.data; | ||
154 | } | ||
155 | if (ret) { | 123 | if (ret) { |
156 | IWL_ERR(mvm, | 124 | IWL_ERR(mvm, |
157 | "NVM access command failed with status %d (device: %s)\n", | 125 | "NVM access command failed with status %d (device: %s)\n", |
@@ -191,17 +159,10 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, | |||
191 | { | 159 | { |
192 | u16 length, offset = 0; | 160 | u16 length, offset = 0; |
193 | int ret; | 161 | int ret; |
194 | bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000; | ||
195 | 162 | ||
196 | length = (iwlwifi_mod_params.amsdu_size_8K ? (8 * 1024) : (4 * 1024)) | 163 | /* Set nvm section read length */ |
197 | - sizeof(union iwl_nvm_access_cmd) | 164 | length = IWL_NVM_DEFAULT_CHUNK_SIZE; |
198 | - sizeof(struct iwl_rx_packet); | 165 | |
199 | /* | ||
200 | * if length is greater than EEPROM size, truncate it because uCode | ||
201 | * doesn't check it by itself, and exit the loop when reached. | ||
202 | */ | ||
203 | if (old_eeprom && length > mvm->cfg->base_params->eeprom_size) | ||
204 | length = mvm->cfg->base_params->eeprom_size; | ||
205 | ret = length; | 166 | ret = length; |
206 | 167 | ||
207 | /* Read the NVM until exhausted (reading less than requested) */ | 168 | /* Read the NVM until exhausted (reading less than requested) */ |
@@ -214,8 +175,6 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, | |||
214 | return ret; | 175 | return ret; |
215 | } | 176 | } |
216 | offset += ret; | 177 | offset += ret; |
217 | if (old_eeprom && offset == mvm->cfg->base_params->eeprom_size) | ||
218 | break; | ||
219 | } | 178 | } |
220 | 179 | ||
221 | IWL_INFO(mvm, "NVM section %d read completed\n", section); | 180 | IWL_INFO(mvm, "NVM section %d read completed\n", section); |
@@ -249,63 +208,31 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
249 | int ret, i, section; | 208 | int ret, i, section; |
250 | u8 *nvm_buffer, *temp; | 209 | u8 *nvm_buffer, *temp; |
251 | 210 | ||
252 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 211 | /* TODO: find correct NVM max size for a section */ |
253 | /* TODO: find correct NVM max size for a section */ | 212 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, |
254 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, | 213 | GFP_KERNEL); |
255 | GFP_KERNEL); | 214 | if (!nvm_buffer) |
256 | if (!nvm_buffer) | 215 | return -ENOMEM; |
257 | return -ENOMEM; | 216 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { |
258 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { | 217 | section = nvm_to_read[i]; |
259 | section = nvm_to_read[i]; | 218 | /* we override the constness for initial read */ |
260 | /* we override the constness for initial read */ | 219 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); |
261 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); | ||
262 | if (ret < 0) | ||
263 | break; | ||
264 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); | ||
265 | if (!temp) { | ||
266 | ret = -ENOMEM; | ||
267 | break; | ||
268 | } | ||
269 | mvm->nvm_sections[section].data = temp; | ||
270 | mvm->nvm_sections[section].length = ret; | ||
271 | } | ||
272 | kfree(nvm_buffer); | ||
273 | if (ret < 0) | 220 | if (ret < 0) |
274 | return ret; | 221 | break; |
275 | } else { | 222 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); |
276 | /* allocate eeprom */ | 223 | if (!temp) { |
277 | mvm->eeprom_blob_size = mvm->cfg->base_params->eeprom_size; | 224 | ret = -ENOMEM; |
278 | IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM size = %zd\n", | 225 | break; |
279 | mvm->eeprom_blob_size); | ||
280 | mvm->eeprom_blob = kzalloc(mvm->eeprom_blob_size, GFP_KERNEL); | ||
281 | if (!mvm->eeprom_blob) | ||
282 | return -ENOMEM; | ||
283 | |||
284 | ret = iwl_nvm_read_section(mvm, 0, mvm->eeprom_blob); | ||
285 | if (ret != mvm->eeprom_blob_size) { | ||
286 | IWL_ERR(mvm, "Read partial NVM %d/%zd\n", | ||
287 | ret, mvm->eeprom_blob_size); | ||
288 | kfree(mvm->eeprom_blob); | ||
289 | mvm->eeprom_blob = NULL; | ||
290 | return -EINVAL; | ||
291 | } | 226 | } |
227 | mvm->nvm_sections[section].data = temp; | ||
228 | mvm->nvm_sections[section].length = ret; | ||
292 | } | 229 | } |
230 | kfree(nvm_buffer); | ||
231 | if (ret < 0) | ||
232 | return ret; | ||
293 | 233 | ||
294 | ret = 0; | 234 | ret = 0; |
295 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) | 235 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); |
296 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); | ||
297 | else | ||
298 | mvm->nvm_data = | ||
299 | iwl_parse_eeprom_data(mvm->trans->dev, | ||
300 | mvm->cfg, | ||
301 | mvm->eeprom_blob, | ||
302 | mvm->eeprom_blob_size); | ||
303 | |||
304 | if (!mvm->nvm_data) { | ||
305 | kfree(mvm->eeprom_blob); | ||
306 | mvm->eeprom_blob = NULL; | ||
307 | ret = -ENOMEM; | ||
308 | } | ||
309 | 236 | ||
310 | return ret; | 237 | return ret; |
311 | } | 238 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index aa59adf87db3..fe031d304d1e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -143,21 +143,12 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode) | |||
143 | u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash; | 143 | u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash; |
144 | u32 reg_val = 0; | 144 | u32 reg_val = 0; |
145 | 145 | ||
146 | /* | 146 | radio_cfg_type = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_TYPE) >> |
147 | * We can't upload the correct value to the INIT image | 147 | FW_PHY_CFG_RADIO_TYPE_POS; |
148 | * as we don't have nvm_data by that time. | 148 | radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >> |
149 | * | 149 | FW_PHY_CFG_RADIO_STEP_POS; |
150 | * TODO: Figure out what we should do here | 150 | radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >> |
151 | */ | 151 | FW_PHY_CFG_RADIO_DASH_POS; |
152 | if (mvm->nvm_data) { | ||
153 | radio_cfg_type = mvm->nvm_data->radio_cfg_type; | ||
154 | radio_cfg_step = mvm->nvm_data->radio_cfg_step; | ||
155 | radio_cfg_dash = mvm->nvm_data->radio_cfg_dash; | ||
156 | } else { | ||
157 | radio_cfg_type = 0; | ||
158 | radio_cfg_step = 0; | ||
159 | radio_cfg_dash = 0; | ||
160 | } | ||
161 | 152 | ||
162 | /* SKU control */ | 153 | /* SKU control */ |
163 | reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) << | 154 | reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) << |
@@ -175,7 +166,6 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode) | |||
175 | 166 | ||
176 | /* silicon bits */ | 167 | /* silicon bits */ |
177 | reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI; | 168 | reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI; |
178 | reg_val |= CSR_HW_IF_CONFIG_REG_BIT_MAC_SI; | ||
179 | 169 | ||
180 | iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG, | 170 | iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG, |
181 | CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH | | 171 | CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH | |
@@ -230,6 +220,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
230 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), | 220 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), |
231 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), | 221 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), |
232 | 222 | ||
223 | RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), | ||
224 | RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false), | ||
225 | |||
233 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), | 226 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), |
234 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), | 227 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), |
235 | 228 | ||
@@ -274,6 +267,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
274 | CMD(WEP_KEY), | 267 | CMD(WEP_KEY), |
275 | CMD(REPLY_RX_PHY_CMD), | 268 | CMD(REPLY_RX_PHY_CMD), |
276 | CMD(REPLY_RX_MPDU_CMD), | 269 | CMD(REPLY_RX_MPDU_CMD), |
270 | CMD(BEACON_NOTIFICATION), | ||
277 | CMD(BEACON_TEMPLATE_CMD), | 271 | CMD(BEACON_TEMPLATE_CMD), |
278 | CMD(STATISTICS_NOTIFICATION), | 272 | CMD(STATISTICS_NOTIFICATION), |
279 | CMD(TX_ANT_CONFIGURATION_CMD), | 273 | CMD(TX_ANT_CONFIGURATION_CMD), |
@@ -293,6 +287,11 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
293 | CMD(NET_DETECT_PROFILES_CMD), | 287 | CMD(NET_DETECT_PROFILES_CMD), |
294 | CMD(NET_DETECT_HOTSPOTS_CMD), | 288 | CMD(NET_DETECT_HOTSPOTS_CMD), |
295 | CMD(NET_DETECT_HOTSPOTS_QUERY_CMD), | 289 | CMD(NET_DETECT_HOTSPOTS_QUERY_CMD), |
290 | CMD(CARD_STATE_NOTIFICATION), | ||
291 | CMD(BT_COEX_PRIO_TABLE), | ||
292 | CMD(BT_COEX_PROT_ENV), | ||
293 | CMD(BT_PROFILE_NOTIFICATION), | ||
294 | CMD(BT_CONFIG), | ||
296 | }; | 295 | }; |
297 | #undef CMD | 296 | #undef CMD |
298 | 297 | ||
@@ -312,16 +311,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
312 | }; | 311 | }; |
313 | int err, scan_size; | 312 | int err, scan_size; |
314 | 313 | ||
315 | switch (cfg->device_family) { | ||
316 | case IWL_DEVICE_FAMILY_6030: | ||
317 | case IWL_DEVICE_FAMILY_6005: | ||
318 | case IWL_DEVICE_FAMILY_7000: | ||
319 | break; | ||
320 | default: | ||
321 | IWL_ERR(trans, "Trying to load mvm on an unsupported device\n"); | ||
322 | return NULL; | ||
323 | } | ||
324 | |||
325 | /******************************** | 314 | /******************************** |
326 | * 1. Allocating and configuring HW data | 315 | * 1. Allocating and configuring HW data |
327 | ********************************/ | 316 | ********************************/ |
@@ -363,8 +352,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
363 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); | 352 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); |
364 | trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K; | 353 | trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K; |
365 | 354 | ||
366 | /* TODO: this should really be a TLV */ | 355 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE) |
367 | if (cfg->device_family == IWL_DEVICE_FAMILY_7000) | ||
368 | trans_cfg.bc_table_dword = true; | 356 | trans_cfg.bc_table_dword = true; |
369 | 357 | ||
370 | if (!iwlwifi_mod_params.wd_disable) | 358 | if (!iwlwifi_mod_params.wd_disable) |
@@ -438,7 +426,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
438 | out_free: | 426 | out_free: |
439 | iwl_phy_db_free(mvm->phy_db); | 427 | iwl_phy_db_free(mvm->phy_db); |
440 | kfree(mvm->scan_cmd); | 428 | kfree(mvm->scan_cmd); |
441 | kfree(mvm->eeprom_blob); | ||
442 | iwl_trans_stop_hw(trans, true); | 429 | iwl_trans_stop_hw(trans, true); |
443 | ieee80211_free_hw(mvm->hw); | 430 | ieee80211_free_hw(mvm->hw); |
444 | return NULL; | 431 | return NULL; |
@@ -460,7 +447,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
460 | iwl_phy_db_free(mvm->phy_db); | 447 | iwl_phy_db_free(mvm->phy_db); |
461 | mvm->phy_db = NULL; | 448 | mvm->phy_db = NULL; |
462 | 449 | ||
463 | kfree(mvm->eeprom_blob); | ||
464 | iwl_free_nvm_data(mvm->nvm_data); | 450 | iwl_free_nvm_data(mvm->nvm_data); |
465 | for (i = 0; i < NVM_NUM_OF_SECTIONS; i++) | 451 | for (i = 0; i < NVM_NUM_OF_SECTIONS; i++) |
466 | kfree(mvm->nvm_sections[i].data); | 452 | kfree(mvm->nvm_sections[i].data); |
@@ -624,12 +610,8 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | |||
624 | ieee80211_free_txskb(mvm->hw, skb); | 610 | ieee80211_free_txskb(mvm->hw, skb); |
625 | } | 611 | } |
626 | 612 | ||
627 | static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) | 613 | static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) |
628 | { | 614 | { |
629 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
630 | |||
631 | iwl_mvm_dump_nic_error_log(mvm); | ||
632 | |||
633 | iwl_abort_notification_waits(&mvm->notif_wait); | 615 | iwl_abort_notification_waits(&mvm->notif_wait); |
634 | 616 | ||
635 | /* | 617 | /* |
@@ -663,9 +645,21 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) | |||
663 | } | 645 | } |
664 | } | 646 | } |
665 | 647 | ||
648 | static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) | ||
649 | { | ||
650 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
651 | |||
652 | iwl_mvm_dump_nic_error_log(mvm); | ||
653 | |||
654 | iwl_mvm_nic_restart(mvm); | ||
655 | } | ||
656 | |||
666 | static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode) | 657 | static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode) |
667 | { | 658 | { |
659 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
660 | |||
668 | WARN_ON(1); | 661 | WARN_ON(1); |
662 | iwl_mvm_nic_restart(mvm); | ||
669 | } | 663 | } |
670 | 664 | ||
671 | static const struct iwl_op_mode_ops iwl_mvm_ops = { | 665 | static const struct iwl_op_mode_ops iwl_mvm_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index b428448f8ddf..0f0b44eabd93 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -142,7 +142,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, | |||
142 | struct cfg80211_chan_def *chandef, | 142 | struct cfg80211_chan_def *chandef, |
143 | u8 chains_static, u8 chains_dynamic) | 143 | u8 chains_static, u8 chains_dynamic) |
144 | { | 144 | { |
145 | u8 valid_rx_chains, active_cnt, idle_cnt; | 145 | u8 active_cnt, idle_cnt; |
146 | 146 | ||
147 | /* Set the channel info data */ | 147 | /* Set the channel info data */ |
148 | cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ? | 148 | cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ? |
@@ -158,17 +158,16 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, | |||
158 | * Need to add on chain noise calibration limitations, and | 158 | * Need to add on chain noise calibration limitations, and |
159 | * BT coex considerations. | 159 | * BT coex considerations. |
160 | */ | 160 | */ |
161 | valid_rx_chains = mvm->nvm_data->valid_rx_ant; | ||
162 | idle_cnt = chains_static; | 161 | idle_cnt = chains_static; |
163 | active_cnt = chains_dynamic; | 162 | active_cnt = chains_dynamic; |
164 | 163 | ||
165 | cmd->rxchain_info = cpu_to_le32(valid_rx_chains << | 164 | cmd->rxchain_info = cpu_to_le32(iwl_fw_valid_rx_ant(mvm->fw) << |
166 | PHY_RX_CHAIN_VALID_POS); | 165 | PHY_RX_CHAIN_VALID_POS); |
167 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); | 166 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); |
168 | cmd->rxchain_info |= cpu_to_le32(active_cnt << | 167 | cmd->rxchain_info |= cpu_to_le32(active_cnt << |
169 | PHY_RX_CHAIN_MIMO_CNT_POS); | 168 | PHY_RX_CHAIN_MIMO_CNT_POS); |
170 | 169 | ||
171 | cmd->txchain_info = cpu_to_le32(mvm->nvm_data->valid_tx_ant); | 170 | cmd->txchain_info = cpu_to_le32(iwl_fw_valid_tx_ant(mvm->fw)); |
172 | } | 171 | } |
173 | 172 | ||
174 | /* | 173 | /* |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 5a92a4978795..9395ab2a1af2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -75,23 +75,49 @@ | |||
75 | 75 | ||
76 | #define POWER_KEEP_ALIVE_PERIOD_SEC 25 | 76 | #define POWER_KEEP_ALIVE_PERIOD_SEC 25 |
77 | 77 | ||
78 | static void iwl_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 78 | static void iwl_mvm_power_log(struct iwl_mvm *mvm, |
79 | struct iwl_powertable_cmd *cmd) | 79 | struct iwl_powertable_cmd *cmd) |
80 | { | ||
81 | IWL_DEBUG_POWER(mvm, | ||
82 | "Sending power table command for power level %d, flags = 0x%X\n", | ||
83 | iwlmvm_mod_params.power_scheme, | ||
84 | le16_to_cpu(cmd->flags)); | ||
85 | IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds); | ||
86 | |||
87 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { | ||
88 | IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n", | ||
89 | le32_to_cpu(cmd->rx_data_timeout)); | ||
90 | IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n", | ||
91 | le32_to_cpu(cmd->tx_data_timeout)); | ||
92 | IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", | ||
93 | cmd->lprx_rssi_threshold); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
98 | struct iwl_powertable_cmd *cmd) | ||
80 | { | 99 | { |
81 | struct ieee80211_hw *hw = mvm->hw; | 100 | struct ieee80211_hw *hw = mvm->hw; |
82 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
83 | struct ieee80211_chanctx_conf *chanctx_conf; | 101 | struct ieee80211_chanctx_conf *chanctx_conf; |
84 | struct ieee80211_channel *chan; | 102 | struct ieee80211_channel *chan; |
85 | int dtimper, dtimper_msec; | 103 | int dtimper, dtimper_msec; |
86 | int keep_alive; | 104 | int keep_alive; |
87 | bool radar_detect = false; | 105 | bool radar_detect = false; |
88 | 106 | ||
89 | cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | 107 | /* |
90 | mvmvif->color)); | 108 | * Regardless of power management state the driver must set |
91 | cmd->action = cpu_to_le32(FW_CTXT_ACTION_MODIFY); | 109 | * keep alive period. FW will use it for sending keep alive NDPs |
110 | * immediately after association. | ||
111 | */ | ||
112 | cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC; | ||
113 | |||
114 | if ((iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) || | ||
115 | !iwlwifi_mod_params.power_save) | ||
116 | return; | ||
117 | |||
118 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | ||
92 | 119 | ||
93 | if ((!vif->bss_conf.ps) || | 120 | if (!vif->bss_conf.ps) |
94 | (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)) | ||
95 | return; | 121 | return; |
96 | 122 | ||
97 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); | 123 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); |
@@ -110,26 +136,23 @@ static void iwl_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
110 | 136 | ||
111 | /* Check skip over DTIM conditions */ | 137 | /* Check skip over DTIM conditions */ |
112 | if (!radar_detect && (dtimper <= 10) && | 138 | if (!radar_detect && (dtimper <= 10) && |
113 | (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP)) { | 139 | (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP)) |
114 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SLEEP_OVER_DTIM_MSK); | 140 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); |
115 | cmd->num_skip_dtim = 2; | ||
116 | } | ||
117 | 141 | ||
118 | /* Check that keep alive period is at least 3 * DTIM */ | 142 | /* Check that keep alive period is at least 3 * DTIM */ |
119 | dtimper_msec = dtimper * vif->bss_conf.beacon_int; | 143 | dtimper_msec = dtimper * vif->bss_conf.beacon_int; |
120 | keep_alive = max_t(int, 3 * dtimper_msec, | 144 | keep_alive = max_t(int, 3 * dtimper_msec, |
121 | MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC); | 145 | MSEC_PER_SEC * cmd->keep_alive_seconds); |
122 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); | 146 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); |
123 | 147 | cmd->keep_alive_seconds = keep_alive; | |
124 | cmd->keep_alive_seconds = cpu_to_le16(keep_alive); | ||
125 | 148 | ||
126 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP) { | 149 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP) { |
127 | /* TODO: Also for D3 (device sleep / WoWLAN) */ | 150 | /* TODO: Also for D3 (device sleep / WoWLAN) */ |
128 | cmd->rx_data_timeout = cpu_to_le32(10); | 151 | cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); |
129 | cmd->tx_data_timeout = cpu_to_le32(10); | 152 | cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); |
130 | } else { | 153 | } else { |
131 | cmd->rx_data_timeout = cpu_to_le32(50); | 154 | cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); |
132 | cmd->tx_data_timeout = cpu_to_le32(50); | 155 | cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); |
133 | } | 156 | } |
134 | } | 157 | } |
135 | 158 | ||
@@ -137,36 +160,11 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
137 | { | 160 | { |
138 | struct iwl_powertable_cmd cmd = {}; | 161 | struct iwl_powertable_cmd cmd = {}; |
139 | 162 | ||
140 | if (!iwlwifi_mod_params.power_save) { | ||
141 | IWL_DEBUG_POWER(mvm, "Power management is not allowed\n"); | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 163 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) |
146 | return 0; | 164 | return 0; |
147 | 165 | ||
148 | iwl_power_build_cmd(mvm, vif, &cmd); | 166 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); |
149 | 167 | iwl_mvm_power_log(mvm, &cmd); | |
150 | IWL_DEBUG_POWER(mvm, | ||
151 | "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n", | ||
152 | cmd.id_and_color, iwlmvm_mod_params.power_scheme, | ||
153 | le16_to_cpu(cmd.flags)); | ||
154 | |||
155 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { | ||
156 | IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", | ||
157 | le16_to_cpu(cmd.keep_alive_seconds)); | ||
158 | IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n", | ||
159 | le32_to_cpu(cmd.rx_data_timeout)); | ||
160 | IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n", | ||
161 | le32_to_cpu(cmd.tx_data_timeout)); | ||
162 | IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n", | ||
163 | le32_to_cpu(cmd.rx_data_timeout_uapsd)); | ||
164 | IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n", | ||
165 | le32_to_cpu(cmd.tx_data_timeout_uapsd)); | ||
166 | IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", | ||
167 | cmd.lprx_rssi_threshold); | ||
168 | IWL_DEBUG_POWER(mvm, "DTIMs to skip = %u\n", cmd.num_skip_dtim); | ||
169 | } | ||
170 | 168 | ||
171 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, | 169 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, |
172 | sizeof(cmd), &cmd); | 170 | sizeof(cmd), &cmd); |
@@ -175,33 +173,16 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
175 | int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 173 | int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
176 | { | 174 | { |
177 | struct iwl_powertable_cmd cmd = {}; | 175 | struct iwl_powertable_cmd cmd = {}; |
178 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
179 | |||
180 | if (!iwlwifi_mod_params.power_save) { | ||
181 | IWL_DEBUG_POWER(mvm, "Power management is not allowed\n"); | ||
182 | return 0; | ||
183 | } | ||
184 | 176 | ||
185 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 177 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) |
186 | return 0; | 178 | return 0; |
187 | 179 | ||
188 | cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | 180 | if ((iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) && |
189 | mvmvif->color)); | 181 | iwlwifi_mod_params.power_save) |
190 | cmd.action = cpu_to_le32(FW_CTXT_ACTION_MODIFY); | 182 | cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
191 | 183 | ||
192 | IWL_DEBUG_POWER(mvm, | 184 | iwl_mvm_power_log(mvm, &cmd); |
193 | "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n", | ||
194 | cmd.id_and_color, iwlmvm_mod_params.power_scheme, | ||
195 | le16_to_cpu(cmd.flags)); | ||
196 | 185 | ||
197 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, | 186 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, |
198 | sizeof(cmd), &cmd); | 187 | sizeof(cmd), &cmd); |
199 | } | 188 | } |
200 | |||
201 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
202 | void iwl_power_get_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
203 | struct iwl_powertable_cmd *cmd) | ||
204 | { | ||
205 | iwl_power_build_cmd(mvm, vif, cmd); | ||
206 | } | ||
207 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index 925628468146..a1e3e923ea3e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -114,7 +114,8 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac, | |||
114 | data->n_interfaces[id]++; | 114 | data->n_interfaces[id]++; |
115 | break; | 115 | break; |
116 | case NL80211_IFTYPE_MONITOR: | 116 | case NL80211_IFTYPE_MONITOR: |
117 | data->n_interfaces[id]++; | 117 | if (mvmvif->monitor_active) |
118 | data->n_interfaces[id]++; | ||
118 | break; | 119 | break; |
119 | case NL80211_IFTYPE_P2P_DEVICE: | 120 | case NL80211_IFTYPE_P2P_DEVICE: |
120 | break; | 121 | break; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 56b636d9ab30..55334d542e26 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -680,12 +680,14 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
680 | */ | 680 | */ |
681 | static bool rs_use_green(struct ieee80211_sta *sta) | 681 | static bool rs_use_green(struct ieee80211_sta *sta) |
682 | { | 682 | { |
683 | struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv; | 683 | /* |
684 | 684 | * There's a bug somewhere in this code that causes the | |
685 | bool use_green = !(sta_priv->vif->bss_conf.ht_operation_mode & | 685 | * scaling to get stuck because GF+SGI can't be combined |
686 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | 686 | * in SISO rates. Until we find that bug, disable GF, it |
687 | 687 | * has only limited benefit and we still interoperate with | |
688 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && use_green; | 688 | * GF APs since we can always receive GF transmissions. |
689 | */ | ||
690 | return false; | ||
689 | } | 691 | } |
690 | 692 | ||
691 | /** | 693 | /** |
@@ -791,7 +793,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
791 | 793 | ||
792 | if (num_of_ant(tbl->ant_type) > 1) | 794 | if (num_of_ant(tbl->ant_type) > 1) |
793 | tbl->ant_type = | 795 | tbl->ant_type = |
794 | first_antenna(mvm->nvm_data->valid_tx_ant); | 796 | first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); |
795 | 797 | ||
796 | tbl->is_ht40 = 0; | 798 | tbl->is_ht40 = 0; |
797 | tbl->is_SGI = 0; | 799 | tbl->is_SGI = 0; |
@@ -1233,7 +1235,7 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm, | |||
1233 | return -1; | 1235 | return -1; |
1234 | 1236 | ||
1235 | /* Need both Tx chains/antennas to support MIMO */ | 1237 | /* Need both Tx chains/antennas to support MIMO */ |
1236 | if (num_of_ant(mvm->nvm_data->valid_tx_ant) < 2) | 1238 | if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 2) |
1237 | return -1; | 1239 | return -1; |
1238 | 1240 | ||
1239 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n"); | 1241 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n"); |
@@ -1285,7 +1287,7 @@ static int rs_switch_to_mimo3(struct iwl_mvm *mvm, | |||
1285 | return -1; | 1287 | return -1; |
1286 | 1288 | ||
1287 | /* Need both Tx chains/antennas to support MIMO */ | 1289 | /* Need both Tx chains/antennas to support MIMO */ |
1288 | if (num_of_ant(mvm->nvm_data->valid_tx_ant) < 3) | 1290 | if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 3) |
1289 | return -1; | 1291 | return -1; |
1290 | 1292 | ||
1291 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO3\n"); | 1293 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO3\n"); |
@@ -1379,7 +1381,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, | |||
1379 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1381 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1380 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1382 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1381 | u8 start_action; | 1383 | u8 start_action; |
1382 | u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant; | 1384 | u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
1383 | u8 tx_chains_num = num_of_ant(valid_tx_ant); | 1385 | u8 tx_chains_num = num_of_ant(valid_tx_ant); |
1384 | int ret; | 1386 | int ret; |
1385 | u8 update_search_tbl_counter = 0; | 1387 | u8 update_search_tbl_counter = 0; |
@@ -1512,7 +1514,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
1512 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1514 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1513 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1515 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1514 | u8 start_action; | 1516 | u8 start_action; |
1515 | u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant; | 1517 | u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
1516 | u8 tx_chains_num = num_of_ant(valid_tx_ant); | 1518 | u8 tx_chains_num = num_of_ant(valid_tx_ant); |
1517 | u8 update_search_tbl_counter = 0; | 1519 | u8 update_search_tbl_counter = 0; |
1518 | int ret; | 1520 | int ret; |
@@ -1647,7 +1649,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
1647 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1649 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1648 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1650 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1649 | u8 start_action; | 1651 | u8 start_action; |
1650 | u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant; | 1652 | u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
1651 | u8 tx_chains_num = num_of_ant(valid_tx_ant); | 1653 | u8 tx_chains_num = num_of_ant(valid_tx_ant); |
1652 | u8 update_search_tbl_counter = 0; | 1654 | u8 update_search_tbl_counter = 0; |
1653 | int ret; | 1655 | int ret; |
@@ -1784,7 +1786,7 @@ static int rs_move_mimo3_to_other(struct iwl_mvm *mvm, | |||
1784 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1786 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1785 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1787 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1786 | u8 start_action; | 1788 | u8 start_action; |
1787 | u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant; | 1789 | u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
1788 | u8 tx_chains_num = num_of_ant(valid_tx_ant); | 1790 | u8 tx_chains_num = num_of_ant(valid_tx_ant); |
1789 | int ret; | 1791 | int ret; |
1790 | u8 update_search_tbl_counter = 0; | 1792 | u8 update_search_tbl_counter = 0; |
@@ -2447,7 +2449,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
2447 | 2449 | ||
2448 | i = lq_sta->last_txrate_idx; | 2450 | i = lq_sta->last_txrate_idx; |
2449 | 2451 | ||
2450 | valid_tx_ant = mvm->nvm_data->valid_tx_ant; | 2452 | valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
2451 | 2453 | ||
2452 | if (!lq_sta->search_better_tbl) | 2454 | if (!lq_sta->search_better_tbl) |
2453 | active_tbl = lq_sta->active_tbl; | 2455 | active_tbl = lq_sta->active_tbl; |
@@ -2637,15 +2639,15 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2637 | 2639 | ||
2638 | /* These values will be overridden later */ | 2640 | /* These values will be overridden later */ |
2639 | lq_sta->lq.single_stream_ant_msk = | 2641 | lq_sta->lq.single_stream_ant_msk = |
2640 | first_antenna(mvm->nvm_data->valid_tx_ant); | 2642 | first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); |
2641 | lq_sta->lq.dual_stream_ant_msk = | 2643 | lq_sta->lq.dual_stream_ant_msk = |
2642 | mvm->nvm_data->valid_tx_ant & | 2644 | iwl_fw_valid_tx_ant(mvm->fw) & |
2643 | ~first_antenna(mvm->nvm_data->valid_tx_ant); | 2645 | ~first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); |
2644 | if (!lq_sta->lq.dual_stream_ant_msk) { | 2646 | if (!lq_sta->lq.dual_stream_ant_msk) { |
2645 | lq_sta->lq.dual_stream_ant_msk = ANT_AB; | 2647 | lq_sta->lq.dual_stream_ant_msk = ANT_AB; |
2646 | } else if (num_of_ant(mvm->nvm_data->valid_tx_ant) == 2) { | 2648 | } else if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) == 2) { |
2647 | lq_sta->lq.dual_stream_ant_msk = | 2649 | lq_sta->lq.dual_stream_ant_msk = |
2648 | mvm->nvm_data->valid_tx_ant; | 2650 | iwl_fw_valid_tx_ant(mvm->fw); |
2649 | } | 2651 | } |
2650 | 2652 | ||
2651 | /* as default allow aggregation for all tids */ | 2653 | /* as default allow aggregation for all tids */ |
@@ -2706,7 +2708,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, | |||
2706 | index++; | 2708 | index++; |
2707 | repeat_rate--; | 2709 | repeat_rate--; |
2708 | if (mvm) | 2710 | if (mvm) |
2709 | valid_tx_ant = mvm->nvm_data->valid_tx_ant; | 2711 | valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
2710 | 2712 | ||
2711 | /* Fill rest of rate table */ | 2713 | /* Fill rest of rate table */ |
2712 | while (index < LINK_QUAL_MAX_RETRY_NUM) { | 2714 | while (index < LINK_QUAL_MAX_RETRY_NUM) { |
@@ -2811,7 +2813,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
2811 | u8 ant_sel_tx; | 2813 | u8 ant_sel_tx; |
2812 | 2814 | ||
2813 | mvm = lq_sta->drv; | 2815 | mvm = lq_sta->drv; |
2814 | valid_tx_ant = mvm->nvm_data->valid_tx_ant; | 2816 | valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
2815 | if (lq_sta->dbg_fixed_rate) { | 2817 | if (lq_sta->dbg_fixed_rate) { |
2816 | ant_sel_tx = | 2818 | ant_sel_tx = |
2817 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) | 2819 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) |
@@ -2882,9 +2884,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
2882 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", | 2884 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", |
2883 | lq_sta->dbg_fixed_rate); | 2885 | lq_sta->dbg_fixed_rate); |
2884 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", | 2886 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", |
2885 | (mvm->nvm_data->valid_tx_ant & ANT_A) ? "ANT_A," : "", | 2887 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_A) ? "ANT_A," : "", |
2886 | (mvm->nvm_data->valid_tx_ant & ANT_B) ? "ANT_B," : "", | 2888 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "", |
2887 | (mvm->nvm_data->valid_tx_ant & ANT_C) ? "ANT_C" : ""); | 2889 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : ""); |
2888 | desc += sprintf(buff+desc, "lq type %s\n", | 2890 | desc += sprintf(buff+desc, "lq type %s\n", |
2889 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | 2891 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); |
2890 | if (is_Ht(tbl->lq_type)) { | 2892 | if (is_Ht(tbl->lq_type)) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 3f40ab05bbd8..4dfc21a3e83e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -131,33 +131,42 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, | |||
131 | static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm, | 131 | static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm, |
132 | struct iwl_rx_phy_info *phy_info) | 132 | struct iwl_rx_phy_info *phy_info) |
133 | { | 133 | { |
134 | u32 rssi_a, rssi_b, rssi_c, max_rssi, agc_db; | 134 | int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm; |
135 | int rssi_all_band_a, rssi_all_band_b; | ||
136 | u32 agc_a, agc_b, max_agc; | ||
135 | u32 val; | 137 | u32 val; |
136 | 138 | ||
137 | /* Find max rssi among 3 possible receivers. | 139 | /* Find max rssi among 2 possible receivers. |
138 | * These values are measured by the Digital Signal Processor (DSP). | 140 | * These values are measured by the Digital Signal Processor (DSP). |
139 | * They should stay fairly constant even as the signal strength varies, | 141 | * They should stay fairly constant even as the signal strength varies, |
140 | * if the radio's Automatic Gain Control (AGC) is working right. | 142 | * if the radio's Automatic Gain Control (AGC) is working right. |
141 | * AGC value (see below) will provide the "interesting" info. | 143 | * AGC value (see below) will provide the "interesting" info. |
142 | */ | 144 | */ |
145 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); | ||
146 | agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS; | ||
147 | agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS; | ||
148 | max_agc = max_t(u32, agc_a, agc_b); | ||
149 | |||
143 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]); | 150 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]); |
144 | rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS; | 151 | rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS; |
145 | rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS; | 152 | rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS; |
146 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_C_IDX]); | 153 | rssi_all_band_a = (val & IWL_OFDM_RSSI_ALLBAND_A_MSK) >> |
147 | rssi_c = (val & IWL_OFDM_RSSI_INBAND_C_MSK) >> IWL_OFDM_RSSI_C_POS; | 154 | IWL_OFDM_RSSI_ALLBAND_A_POS; |
148 | 155 | rssi_all_band_b = (val & IWL_OFDM_RSSI_ALLBAND_B_MSK) >> | |
149 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); | 156 | IWL_OFDM_RSSI_ALLBAND_B_POS; |
150 | agc_db = (val & IWL_OFDM_AGC_DB_MSK) >> IWL_OFDM_AGC_DB_POS; | ||
151 | 157 | ||
152 | max_rssi = max_t(u32, rssi_a, rssi_b); | 158 | /* |
153 | max_rssi = max_t(u32, max_rssi, rssi_c); | 159 | * dBm = rssi dB - agc dB - constant. |
160 | * Higher AGC (higher radio gain) means lower signal. | ||
161 | */ | ||
162 | rssi_a_dbm = rssi_a - IWL_RSSI_OFFSET - agc_a; | ||
163 | rssi_b_dbm = rssi_b - IWL_RSSI_OFFSET - agc_b; | ||
164 | max_rssi_dbm = max_t(int, rssi_a_dbm, rssi_b_dbm); | ||
154 | 165 | ||
155 | IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", | 166 | IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n", |
156 | rssi_a, rssi_b, rssi_c, max_rssi, agc_db); | 167 | rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b); |
157 | 168 | ||
158 | /* dBm = max_rssi dB - agc dB - constant. | 169 | return max_rssi_dbm; |
159 | * Higher AGC (higher radio gain) means lower signal. */ | ||
160 | return max_rssi - agc_db - IWL_RSSI_OFFSET; | ||
161 | } | 170 | } |
162 | 171 | ||
163 | /* | 172 | /* |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 9b21b92aa8d1..2157b0f8ced5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -74,7 +74,7 @@ | |||
74 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) | 74 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) |
75 | { | 75 | { |
76 | u16 rx_chain; | 76 | u16 rx_chain; |
77 | u8 rx_ant = mvm->nvm_data->valid_rx_ant; | 77 | u8 rx_ant = iwl_fw_valid_rx_ant(mvm->fw); |
78 | 78 | ||
79 | rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; | 79 | rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; |
80 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; | 80 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; |
@@ -115,7 +115,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band, | |||
115 | u32 tx_ant; | 115 | u32 tx_ant; |
116 | 116 | ||
117 | mvm->scan_last_antenna_idx = | 117 | mvm->scan_last_antenna_idx = |
118 | iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant, | 118 | iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw), |
119 | mvm->scan_last_antenna_idx); | 119 | mvm->scan_last_antenna_idx); |
120 | tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; | 120 | tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; |
121 | 121 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 52aecf20d0df..0fd96e4da461 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -101,8 +101,55 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
101 | } | 101 | } |
102 | add_sta_cmd.add_modify = update ? 1 : 0; | 102 | add_sta_cmd.add_modify = update ? 1 : 0; |
103 | 103 | ||
104 | /* STA_FLG_FAT_EN_MSK ? */ | 104 | add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK | |
105 | /* STA_FLG_MIMO_EN_MSK ? */ | 105 | STA_FLG_MIMO_EN_MSK); |
106 | |||
107 | switch (sta->bandwidth) { | ||
108 | case IEEE80211_STA_RX_BW_160: | ||
109 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_160MHZ); | ||
110 | /* fall through */ | ||
111 | case IEEE80211_STA_RX_BW_80: | ||
112 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_80MHZ); | ||
113 | /* fall through */ | ||
114 | case IEEE80211_STA_RX_BW_40: | ||
115 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_40MHZ); | ||
116 | /* fall through */ | ||
117 | case IEEE80211_STA_RX_BW_20: | ||
118 | if (sta->ht_cap.ht_supported) | ||
119 | add_sta_cmd.station_flags |= | ||
120 | cpu_to_le32(STA_FLG_FAT_EN_20MHZ); | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | switch (sta->rx_nss) { | ||
125 | case 1: | ||
126 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO); | ||
127 | break; | ||
128 | case 2: | ||
129 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO2); | ||
130 | break; | ||
131 | case 3 ... 8: | ||
132 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO3); | ||
133 | break; | ||
134 | } | ||
135 | |||
136 | switch (sta->smps_mode) { | ||
137 | case IEEE80211_SMPS_AUTOMATIC: | ||
138 | case IEEE80211_SMPS_NUM_MODES: | ||
139 | WARN_ON(1); | ||
140 | break; | ||
141 | case IEEE80211_SMPS_STATIC: | ||
142 | /* override NSS */ | ||
143 | add_sta_cmd.station_flags &= ~cpu_to_le32(STA_FLG_MIMO_EN_MSK); | ||
144 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO); | ||
145 | break; | ||
146 | case IEEE80211_SMPS_DYNAMIC: | ||
147 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_RTS_MIMO_PROT); | ||
148 | break; | ||
149 | case IEEE80211_SMPS_OFF: | ||
150 | /* nothing */ | ||
151 | break; | ||
152 | } | ||
106 | 153 | ||
107 | if (sta->ht_cap.ht_supported) { | 154 | if (sta->ht_cap.ht_supported) { |
108 | add_sta_cmd.station_flags_msk |= | 155 | add_sta_cmd.station_flags_msk |= |
@@ -340,6 +387,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
340 | 387 | ||
341 | if (vif->type == NL80211_IFTYPE_STATION && | 388 | if (vif->type == NL80211_IFTYPE_STATION && |
342 | mvmvif->ap_sta_id == mvm_sta->sta_id) { | 389 | mvmvif->ap_sta_id == mvm_sta->sta_id) { |
390 | /* flush its queues here since we are freeing mvm_sta */ | ||
391 | ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true); | ||
392 | |||
343 | /* | 393 | /* |
344 | * Put a non-NULL since the fw station isn't removed. | 394 | * Put a non-NULL since the fw station isn't removed. |
345 | * It will be removed after the MAC will be set as | 395 | * It will be removed after the MAC will be set as |
@@ -348,9 +398,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
348 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], | 398 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], |
349 | ERR_PTR(-EINVAL)); | 399 | ERR_PTR(-EINVAL)); |
350 | 400 | ||
351 | /* flush its queues here since we are freeing mvm_sta */ | ||
352 | ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true); | ||
353 | |||
354 | /* if we are associated - we can't remove the AP STA now */ | 401 | /* if we are associated - we can't remove the AP STA now */ |
355 | if (vif->bss_conf.assoc) | 402 | if (vif->bss_conf.assoc) |
356 | return ret; | 403 | return ret; |
@@ -770,6 +817,16 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
770 | u16 txq_id; | 817 | u16 txq_id; |
771 | int err; | 818 | int err; |
772 | 819 | ||
820 | |||
821 | /* | ||
822 | * If mac80211 is cleaning its state, then say that we finished since | ||
823 | * our state has been cleared anyway. | ||
824 | */ | ||
825 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { | ||
826 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
827 | return 0; | ||
828 | } | ||
829 | |||
773 | spin_lock_bh(&mvmsta->lock); | 830 | spin_lock_bh(&mvmsta->lock); |
774 | 831 | ||
775 | txq_id = tid_data->txq_id; | 832 | txq_id = tid_data->txq_id; |
@@ -824,6 +881,34 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
824 | return err; | 881 | return err; |
825 | } | 882 | } |
826 | 883 | ||
884 | int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
885 | struct ieee80211_sta *sta, u16 tid) | ||
886 | { | ||
887 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
888 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; | ||
889 | u16 txq_id; | ||
890 | |||
891 | /* | ||
892 | * First set the agg state to OFF to avoid calling | ||
893 | * ieee80211_stop_tx_ba_cb in iwl_mvm_check_ratid_empty. | ||
894 | */ | ||
895 | spin_lock_bh(&mvmsta->lock); | ||
896 | txq_id = tid_data->txq_id; | ||
897 | IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n", | ||
898 | mvmsta->sta_id, tid, txq_id, tid_data->state); | ||
899 | tid_data->state = IWL_AGG_OFF; | ||
900 | spin_unlock_bh(&mvmsta->lock); | ||
901 | |||
902 | if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true)) | ||
903 | IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); | ||
904 | |||
905 | iwl_trans_txq_disable(mvm->trans, tid_data->txq_id); | ||
906 | mvm->queue_to_mac80211[tid_data->txq_id] = | ||
907 | IWL_INVALID_MAC80211_QUEUE; | ||
908 | |||
909 | return 0; | ||
910 | } | ||
911 | |||
827 | static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm) | 912 | static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm) |
828 | { | 913 | { |
829 | int i; | 914 | int i; |
@@ -860,7 +945,7 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif, | |||
860 | mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) | 945 | mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) |
861 | return mvmvif->ap_sta_id; | 946 | return mvmvif->ap_sta_id; |
862 | 947 | ||
863 | return IWL_INVALID_STATION; | 948 | return IWL_MVM_STATION_COUNT; |
864 | } | 949 | } |
865 | 950 | ||
866 | static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | 951 | static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, |
@@ -1008,7 +1093,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, | |||
1008 | 1093 | ||
1009 | /* Get the station id from the mvm local station table */ | 1094 | /* Get the station id from the mvm local station table */ |
1010 | sta_id = iwl_mvm_get_key_sta_id(vif, sta); | 1095 | sta_id = iwl_mvm_get_key_sta_id(vif, sta); |
1011 | if (sta_id == IWL_INVALID_STATION) { | 1096 | if (sta_id == IWL_MVM_STATION_COUNT) { |
1012 | IWL_ERR(mvm, "Failed to find station id\n"); | 1097 | IWL_ERR(mvm, "Failed to find station id\n"); |
1013 | return -EINVAL; | 1098 | return -EINVAL; |
1014 | } | 1099 | } |
@@ -1103,7 +1188,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, | |||
1103 | return -ENOENT; | 1188 | return -ENOENT; |
1104 | } | 1189 | } |
1105 | 1190 | ||
1106 | if (sta_id == IWL_INVALID_STATION) { | 1191 | if (sta_id == IWL_MVM_STATION_COUNT) { |
1107 | IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n"); | 1192 | IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n"); |
1108 | return 0; | 1193 | return 0; |
1109 | } | 1194 | } |
@@ -1169,7 +1254,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm, | |||
1169 | struct iwl_mvm_sta *mvm_sta; | 1254 | struct iwl_mvm_sta *mvm_sta; |
1170 | u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta); | 1255 | u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta); |
1171 | 1256 | ||
1172 | if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION)) | 1257 | if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT)) |
1173 | return; | 1258 | return; |
1174 | 1259 | ||
1175 | rcu_read_lock(); | 1260 | rcu_read_lock(); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index 896f88ac8145..12abd2d71835 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -271,6 +271,7 @@ struct iwl_mvm_tid_data { | |||
271 | * @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for | 271 | * @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for |
272 | * tid. | 272 | * tid. |
273 | * @max_agg_bufsize: the maximal size of the AGG buffer for this station | 273 | * @max_agg_bufsize: the maximal size of the AGG buffer for this station |
274 | * @bt_reduced_txpower: is reduced tx power enabled for this station | ||
274 | * @lock: lock to protect the whole struct. Since %tid_data is access from Tx | 275 | * @lock: lock to protect the whole struct. Since %tid_data is access from Tx |
275 | * and from Tx response flow, it needs a spinlock. | 276 | * and from Tx response flow, it needs a spinlock. |
276 | * @pending_frames: number of frames for this STA on the shared Tx queues. | 277 | * @pending_frames: number of frames for this STA on the shared Tx queues. |
@@ -287,6 +288,7 @@ struct iwl_mvm_sta { | |||
287 | u32 mac_id_n_color; | 288 | u32 mac_id_n_color; |
288 | u16 tid_disable_agg; | 289 | u16 tid_disable_agg; |
289 | u8 max_agg_bufsize; | 290 | u8 max_agg_bufsize; |
291 | bool bt_reduced_txpower; | ||
290 | spinlock_t lock; | 292 | spinlock_t lock; |
291 | atomic_t pending_frames; | 293 | atomic_t pending_frames; |
292 | struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; | 294 | struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; |
@@ -348,6 +350,8 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
348 | struct ieee80211_sta *sta, u16 tid, u8 buf_size); | 350 | struct ieee80211_sta *sta, u16 tid, u8 buf_size); |
349 | int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 351 | int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
350 | struct ieee80211_sta *sta, u16 tid); | 352 | struct ieee80211_sta *sta, u16 tid); |
353 | int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
354 | struct ieee80211_sta *sta, u16 tid); | ||
351 | 355 | ||
352 | int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm); | 356 | int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm); |
353 | int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta, | 357 | int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index e437e02c7149..ad9bbca99213 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -76,14 +76,12 @@ | |||
76 | #define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024)) | 76 | #define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024)) |
77 | #define MSEC_TO_TU(_msec) (_msec*1000/1024) | 77 | #define MSEC_TO_TU(_msec) (_msec*1000/1024) |
78 | 78 | ||
79 | /* For ROC use a TE type which has priority high enough to be scheduled when | 79 | /* |
80 | * there is a concurrent BSS or GO/AP. Currently, use a TE type that has | 80 | * For the high priority TE use a time event type that has similar priority to |
81 | * priority similar to the TE priority used for action scans by the FW. | 81 | * the FW's action scan priority. |
82 | * TODO: This needs to be changed, based on the reason for the ROC, i.e., use | ||
83 | * TE_P2P_DEVICE_DISCOVERABLE for remain on channel without mgmt skb, and use | ||
84 | * TE_P2P_DEVICE_ACTION_SCAN | ||
85 | */ | 82 | */ |
86 | #define IWL_MVM_ROC_TE_TYPE TE_P2P_DEVICE_ACTION_SCAN | 83 | #define IWL_MVM_ROC_TE_TYPE_NORMAL TE_P2P_DEVICE_DISCOVERABLE |
84 | #define IWL_MVM_ROC_TE_TYPE_MGMT_TX TE_P2P_CLIENT_ASSOC | ||
87 | 85 | ||
88 | void iwl_mvm_te_clear_data(struct iwl_mvm *mvm, | 86 | void iwl_mvm_te_clear_data(struct iwl_mvm *mvm, |
89 | struct iwl_mvm_time_event_data *te_data) | 87 | struct iwl_mvm_time_event_data *te_data) |
@@ -116,7 +114,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) | |||
116 | * issue as it will have to complete before the next command is | 114 | * issue as it will have to complete before the next command is |
117 | * executed, and a new time event means a new command. | 115 | * executed, and a new time event means a new command. |
118 | */ | 116 | */ |
119 | iwl_mvm_flush_tx_path(mvm, BIT(IWL_OFFCHANNEL_QUEUE), false); | 117 | iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false); |
120 | } | 118 | } |
121 | 119 | ||
122 | static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) | 120 | static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) |
@@ -168,7 +166,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, | |||
168 | WARN_ONCE(!le32_to_cpu(notif->status), | 166 | WARN_ONCE(!le32_to_cpu(notif->status), |
169 | "Failed to schedule time event\n"); | 167 | "Failed to schedule time event\n"); |
170 | 168 | ||
171 | if (le32_to_cpu(notif->action) == TE_NOTIF_HOST_END) { | 169 | if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_END) { |
172 | IWL_DEBUG_TE(mvm, | 170 | IWL_DEBUG_TE(mvm, |
173 | "TE ended - current time %lu, estimated end %lu\n", | 171 | "TE ended - current time %lu, estimated end %lu\n", |
174 | jiffies, te_data->end_jiffies); | 172 | jiffies, te_data->end_jiffies); |
@@ -191,7 +189,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, | |||
191 | } | 189 | } |
192 | 190 | ||
193 | iwl_mvm_te_clear_data(mvm, te_data); | 191 | iwl_mvm_te_clear_data(mvm, te_data); |
194 | } else if (le32_to_cpu(notif->action) == TE_NOTIF_HOST_START) { | 192 | } else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) { |
195 | te_data->running = true; | 193 | te_data->running = true; |
196 | te_data->end_jiffies = jiffies + | 194 | te_data->end_jiffies = jiffies + |
197 | TU_TO_JIFFIES(te_data->duration); | 195 | TU_TO_JIFFIES(te_data->duration); |
@@ -370,7 +368,8 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, | |||
370 | time_cmd.interval_reciprocal = cpu_to_le32(iwl_mvm_reciprocal(1)); | 368 | time_cmd.interval_reciprocal = cpu_to_le32(iwl_mvm_reciprocal(1)); |
371 | time_cmd.duration = cpu_to_le32(duration); | 369 | time_cmd.duration = cpu_to_le32(duration); |
372 | time_cmd.repeat = cpu_to_le32(1); | 370 | time_cmd.repeat = cpu_to_le32(1); |
373 | time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END); | 371 | time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START | |
372 | TE_NOTIF_HOST_EVENT_END); | ||
374 | 373 | ||
375 | iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 374 | iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
376 | } | 375 | } |
@@ -438,7 +437,7 @@ void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm, | |||
438 | } | 437 | } |
439 | 438 | ||
440 | int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 439 | int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
441 | int duration) | 440 | int duration, enum ieee80211_roc_type type) |
442 | { | 441 | { |
443 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 442 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
444 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; | 443 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; |
@@ -459,27 +458,36 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
459 | time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD); | 458 | time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD); |
460 | time_cmd.id_and_color = | 459 | time_cmd.id_and_color = |
461 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); | 460 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); |
462 | time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE); | 461 | |
462 | switch (type) { | ||
463 | case IEEE80211_ROC_TYPE_NORMAL: | ||
464 | time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_NORMAL); | ||
465 | break; | ||
466 | case IEEE80211_ROC_TYPE_MGMT_TX: | ||
467 | time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_MGMT_TX); | ||
468 | break; | ||
469 | default: | ||
470 | WARN_ONCE(1, "Got an invalid ROC type\n"); | ||
471 | return -EINVAL; | ||
472 | } | ||
463 | 473 | ||
464 | time_cmd.apply_time = cpu_to_le32(0); | 474 | time_cmd.apply_time = cpu_to_le32(0); |
465 | time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT); | 475 | time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT); |
466 | time_cmd.is_present = cpu_to_le32(1); | 476 | time_cmd.is_present = cpu_to_le32(1); |
467 | |||
468 | time_cmd.interval = cpu_to_le32(1); | 477 | time_cmd.interval = cpu_to_le32(1); |
469 | 478 | ||
470 | /* | 479 | /* |
471 | * IWL_MVM_ROC_TE_TYPE can have lower priority than other events | 480 | * The P2P Device TEs can have lower priority than other events |
472 | * that are being scheduled by the driver/fw, and thus it might not be | 481 | * that are being scheduled by the driver/fw, and thus it might not be |
473 | * scheduled. To improve the chances of it being scheduled, allow it to | 482 | * scheduled. To improve the chances of it being scheduled, allow them |
474 | * be fragmented. | 483 | * to be fragmented, and in addition allow them to be delayed. |
475 | * In addition, for the same reasons, allow to delay the scheduling of | ||
476 | * the time event. | ||
477 | */ | 484 | */ |
478 | time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20); | 485 | time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20); |
479 | time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); | 486 | time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); |
480 | time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); | 487 | time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); |
481 | time_cmd.repeat = cpu_to_le32(1); | 488 | time_cmd.repeat = cpu_to_le32(1); |
482 | time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END); | 489 | time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START | |
490 | TE_NOTIF_HOST_EVENT_END); | ||
483 | 491 | ||
484 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 492 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
485 | } | 493 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h index 64fb57a5ab43..f86c51065ed3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.h +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -162,6 +162,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm, | |||
162 | * that the vif type is NL80211_IFTYPE_P2P_DEVICE | 162 | * that the vif type is NL80211_IFTYPE_P2P_DEVICE |
163 | * @duration: the requested duration in millisecond for the fw to be on the | 163 | * @duration: the requested duration in millisecond for the fw to be on the |
164 | * channel that is bound to the vif. | 164 | * channel that is bound to the vif. |
165 | * @type: the remain on channel request type | ||
165 | * | 166 | * |
166 | * This function can be used to issue a remain on channel session, | 167 | * This function can be used to issue a remain on channel session, |
167 | * which means that the fw will stay in the channel for the request %duration | 168 | * which means that the fw will stay in the channel for the request %duration |
@@ -172,7 +173,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm, | |||
172 | * another notification to the driver. | 173 | * another notification to the driver. |
173 | */ | 174 | */ |
174 | int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 175 | int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
175 | int duration); | 176 | int duration, enum ieee80211_roc_type type); |
176 | 177 | ||
177 | /** | 178 | /** |
178 | * iwl_mvm_stop_p2p_roc - stop remain on channel for p2p device functionlity | 179 | * iwl_mvm_stop_p2p_roc - stop remain on channel for p2p device functionlity |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 56df249b215e..479074303bd7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -205,7 +205,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, | |||
205 | rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx); | 205 | rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx); |
206 | 206 | ||
207 | mvm->mgmt_last_antenna_idx = | 207 | mvm->mgmt_last_antenna_idx = |
208 | iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant, | 208 | iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw), |
209 | mvm->mgmt_last_antenna_idx); | 209 | mvm->mgmt_last_antenna_idx); |
210 | rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; | 210 | rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; |
211 | 211 | ||
@@ -365,7 +365,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
365 | if (WARN_ON_ONCE(!mvmsta)) | 365 | if (WARN_ON_ONCE(!mvmsta)) |
366 | return -1; | 366 | return -1; |
367 | 367 | ||
368 | if (WARN_ON_ONCE(mvmsta->sta_id == IWL_INVALID_STATION)) | 368 | if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) |
369 | return -1; | 369 | return -1; |
370 | 370 | ||
371 | dev_cmd = iwl_mvm_set_tx_params(mvm, skb, sta, mvmsta->sta_id); | 371 | dev_cmd = iwl_mvm_set_tx_params(mvm, skb, sta, mvmsta->sta_id); |
@@ -417,7 +417,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
417 | spin_unlock(&mvmsta->lock); | 417 | spin_unlock(&mvmsta->lock); |
418 | 418 | ||
419 | if (mvmsta->vif->type == NL80211_IFTYPE_AP && | 419 | if (mvmsta->vif->type == NL80211_IFTYPE_AP && |
420 | txq_id < IWL_FIRST_AMPDU_QUEUE) | 420 | txq_id < IWL_MVM_FIRST_AGG_QUEUE) |
421 | atomic_inc(&mvmsta->pending_frames); | 421 | atomic_inc(&mvmsta->pending_frames); |
422 | 422 | ||
423 | return 0; | 423 | return 0; |
@@ -606,13 +606,9 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
606 | info); | 606 | info); |
607 | 607 | ||
608 | /* Single frame failure in an AMPDU queue => send BAR */ | 608 | /* Single frame failure in an AMPDU queue => send BAR */ |
609 | if (txq_id >= IWL_FIRST_AMPDU_QUEUE && | 609 | if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE && |
610 | !(info->flags & IEEE80211_TX_STAT_ACK)) { | 610 | !(info->flags & IEEE80211_TX_STAT_ACK)) |
611 | /* there must be only one skb in the skb_list */ | ||
612 | WARN_ON_ONCE(skb_freed > 1 || | ||
613 | !skb_queue_empty(&skbs)); | ||
614 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 611 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
615 | } | ||
616 | 612 | ||
617 | /* W/A FW bug: seq_ctl is wrong when the queue is flushed */ | 613 | /* W/A FW bug: seq_ctl is wrong when the queue is flushed */ |
618 | if (status == TX_STATUS_FAIL_FIFO_FLUSHED) { | 614 | if (status == TX_STATUS_FAIL_FIFO_FLUSHED) { |
@@ -623,7 +619,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
623 | ieee80211_tx_status_ni(mvm->hw, skb); | 619 | ieee80211_tx_status_ni(mvm->hw, skb); |
624 | } | 620 | } |
625 | 621 | ||
626 | if (txq_id >= IWL_FIRST_AMPDU_QUEUE) { | 622 | if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE) { |
627 | /* If this is an aggregation queue, we use the ssn since: | 623 | /* If this is an aggregation queue, we use the ssn since: |
628 | * ssn = wifi seq_num % 256. | 624 | * ssn = wifi seq_num % 256. |
629 | * The seq_ctl is the sequence control of the packet to which | 625 | * The seq_ctl is the sequence control of the packet to which |
@@ -645,10 +641,12 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
645 | } | 641 | } |
646 | 642 | ||
647 | IWL_DEBUG_TX_REPLY(mvm, | 643 | IWL_DEBUG_TX_REPLY(mvm, |
648 | "TXQ %d status %s (0x%08x)\n\t\t\t\tinitial_rate 0x%x " | 644 | "TXQ %d status %s (0x%08x)\n", |
649 | "retries %d, idx=%d ssn=%d next_reclaimed=0x%x seq_ctl=0x%x\n", | 645 | txq_id, iwl_mvm_get_tx_fail_reason(status), status); |
650 | txq_id, iwl_mvm_get_tx_fail_reason(status), | 646 | |
651 | status, le32_to_cpu(tx_resp->initial_rate), | 647 | IWL_DEBUG_TX_REPLY(mvm, |
648 | "\t\t\t\tinitial_rate 0x%x retries %d, idx=%d ssn=%d next_reclaimed=0x%x seq_ctl=0x%x\n", | ||
649 | le32_to_cpu(tx_resp->initial_rate), | ||
652 | tx_resp->failure_frame, SEQ_TO_INDEX(sequence), | 650 | tx_resp->failure_frame, SEQ_TO_INDEX(sequence), |
653 | ssn, next_reclaimed, seq_ctl); | 651 | ssn, next_reclaimed, seq_ctl); |
654 | 652 | ||
@@ -685,7 +683,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
685 | * If there are no pending frames for this STA, notify mac80211 that | 683 | * If there are no pending frames for this STA, notify mac80211 that |
686 | * this station can go to sleep in its STA table. | 684 | * this station can go to sleep in its STA table. |
687 | */ | 685 | */ |
688 | if (txq_id < IWL_FIRST_AMPDU_QUEUE && mvmsta && | 686 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && mvmsta && |
689 | !WARN_ON(skb_freed > 1) && | 687 | !WARN_ON(skb_freed > 1) && |
690 | mvmsta->vif->type == NL80211_IFTYPE_AP && | 688 | mvmsta->vif->type == NL80211_IFTYPE_AP && |
691 | atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) { | 689 | atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) { |
@@ -754,7 +752,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, | |||
754 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 752 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
755 | struct ieee80211_sta *sta; | 753 | struct ieee80211_sta *sta; |
756 | 754 | ||
757 | if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_FIRST_AMPDU_QUEUE)) | 755 | if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_MVM_FIRST_AGG_QUEUE)) |
758 | return; | 756 | return; |
759 | 757 | ||
760 | if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS)) | 758 | if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS)) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 000e842c2edd..0cc8d8c0d393 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -462,7 +462,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, | |||
462 | .data = { lq, }, | 462 | .data = { lq, }, |
463 | }; | 463 | }; |
464 | 464 | ||
465 | if (WARN_ON(lq->sta_id == IWL_INVALID_STATION)) | 465 | if (WARN_ON(lq->sta_id == IWL_MVM_STATION_COUNT)) |
466 | return -EINVAL; | 466 | return -EINVAL; |
467 | 467 | ||
468 | if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) | 468 | if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) |
diff --git a/drivers/net/wireless/iwlwifi/pcie/cfg.h b/drivers/net/wireless/iwlwifi/pcie/cfg.h deleted file mode 100644 index c6f8e83c3551..000000000000 --- a/drivers/net/wireless/iwlwifi/pcie/cfg.h +++ /dev/null | |||
@@ -1,115 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | #ifndef __iwl_pci_h__ | ||
64 | #define __iwl_pci_h__ | ||
65 | |||
66 | |||
67 | /* | ||
68 | * This file declares the config structures for all devices. | ||
69 | */ | ||
70 | |||
71 | extern const struct iwl_cfg iwl5300_agn_cfg; | ||
72 | extern const struct iwl_cfg iwl5100_agn_cfg; | ||
73 | extern const struct iwl_cfg iwl5350_agn_cfg; | ||
74 | extern const struct iwl_cfg iwl5100_bgn_cfg; | ||
75 | extern const struct iwl_cfg iwl5100_abg_cfg; | ||
76 | extern const struct iwl_cfg iwl5150_agn_cfg; | ||
77 | extern const struct iwl_cfg iwl5150_abg_cfg; | ||
78 | extern const struct iwl_cfg iwl6005_2agn_cfg; | ||
79 | extern const struct iwl_cfg iwl6005_2abg_cfg; | ||
80 | extern const struct iwl_cfg iwl6005_2bg_cfg; | ||
81 | extern const struct iwl_cfg iwl6005_2agn_sff_cfg; | ||
82 | extern const struct iwl_cfg iwl6005_2agn_d_cfg; | ||
83 | extern const struct iwl_cfg iwl6005_2agn_mow1_cfg; | ||
84 | extern const struct iwl_cfg iwl6005_2agn_mow2_cfg; | ||
85 | extern const struct iwl_cfg iwl1030_bgn_cfg; | ||
86 | extern const struct iwl_cfg iwl1030_bg_cfg; | ||
87 | extern const struct iwl_cfg iwl6030_2agn_cfg; | ||
88 | extern const struct iwl_cfg iwl6030_2abg_cfg; | ||
89 | extern const struct iwl_cfg iwl6030_2bgn_cfg; | ||
90 | extern const struct iwl_cfg iwl6030_2bg_cfg; | ||
91 | extern const struct iwl_cfg iwl6000i_2agn_cfg; | ||
92 | extern const struct iwl_cfg iwl6000i_2abg_cfg; | ||
93 | extern const struct iwl_cfg iwl6000i_2bg_cfg; | ||
94 | extern const struct iwl_cfg iwl6000_3agn_cfg; | ||
95 | extern const struct iwl_cfg iwl6050_2agn_cfg; | ||
96 | extern const struct iwl_cfg iwl6050_2abg_cfg; | ||
97 | extern const struct iwl_cfg iwl6150_bgn_cfg; | ||
98 | extern const struct iwl_cfg iwl6150_bg_cfg; | ||
99 | extern const struct iwl_cfg iwl1000_bgn_cfg; | ||
100 | extern const struct iwl_cfg iwl1000_bg_cfg; | ||
101 | extern const struct iwl_cfg iwl100_bgn_cfg; | ||
102 | extern const struct iwl_cfg iwl100_bg_cfg; | ||
103 | extern const struct iwl_cfg iwl130_bgn_cfg; | ||
104 | extern const struct iwl_cfg iwl130_bg_cfg; | ||
105 | extern const struct iwl_cfg iwl2000_2bgn_cfg; | ||
106 | extern const struct iwl_cfg iwl2000_2bgn_d_cfg; | ||
107 | extern const struct iwl_cfg iwl2030_2bgn_cfg; | ||
108 | extern const struct iwl_cfg iwl6035_2agn_cfg; | ||
109 | extern const struct iwl_cfg iwl105_bgn_cfg; | ||
110 | extern const struct iwl_cfg iwl105_bgn_d_cfg; | ||
111 | extern const struct iwl_cfg iwl135_bgn_cfg; | ||
112 | extern const struct iwl_cfg iwl7260_2ac_cfg; | ||
113 | extern const struct iwl_cfg iwl3160_ac_cfg; | ||
114 | |||
115 | #endif /* __iwl_pci_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 7bc0fb9128dd..0016bb24b3d7 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -69,8 +69,6 @@ | |||
69 | 69 | ||
70 | #include "iwl-trans.h" | 70 | #include "iwl-trans.h" |
71 | #include "iwl-drv.h" | 71 | #include "iwl-drv.h" |
72 | |||
73 | #include "cfg.h" | ||
74 | #include "internal.h" | 72 | #include "internal.h" |
75 | 73 | ||
76 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | 74 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ |
@@ -243,6 +241,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
243 | {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)}, | 241 | {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)}, |
244 | {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)}, | 242 | {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)}, |
245 | {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)}, | 243 | {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)}, |
244 | {IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)}, | ||
246 | 245 | ||
247 | /* 105 Series */ | 246 | /* 105 Series */ |
248 | {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)}, | 247 | {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)}, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index aa2a39a637dd..148843e7f34f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -137,10 +137,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) | |||
137 | struct iwl_cmd_meta { | 137 | struct iwl_cmd_meta { |
138 | /* only for SYNC commands, iff the reply skb is wanted */ | 138 | /* only for SYNC commands, iff the reply skb is wanted */ |
139 | struct iwl_host_cmd *source; | 139 | struct iwl_host_cmd *source; |
140 | |||
141 | DEFINE_DMA_UNMAP_ADDR(mapping); | ||
142 | DEFINE_DMA_UNMAP_LEN(len); | ||
143 | |||
144 | u32 flags; | 140 | u32 flags; |
145 | }; | 141 | }; |
146 | 142 | ||
@@ -182,19 +178,39 @@ struct iwl_queue { | |||
182 | #define TFD_TX_CMD_SLOTS 256 | 178 | #define TFD_TX_CMD_SLOTS 256 |
183 | #define TFD_CMD_SLOTS 32 | 179 | #define TFD_CMD_SLOTS 32 |
184 | 180 | ||
181 | /* | ||
182 | * The FH will write back to the first TB only, so we need | ||
183 | * to copy some data into the buffer regardless of whether | ||
184 | * it should be mapped or not. This indicates how big the | ||
185 | * first TB must be to include the scratch buffer. Since | ||
186 | * the scratch is 4 bytes at offset 12, it's 16 now. If we | ||
187 | * make it bigger then allocations will be bigger and copy | ||
188 | * slower, so that's probably not useful. | ||
189 | */ | ||
190 | #define IWL_HCMD_SCRATCHBUF_SIZE 16 | ||
191 | |||
185 | struct iwl_pcie_txq_entry { | 192 | struct iwl_pcie_txq_entry { |
186 | struct iwl_device_cmd *cmd; | 193 | struct iwl_device_cmd *cmd; |
187 | struct iwl_device_cmd *copy_cmd; | ||
188 | struct sk_buff *skb; | 194 | struct sk_buff *skb; |
189 | /* buffer to free after command completes */ | 195 | /* buffer to free after command completes */ |
190 | const void *free_buf; | 196 | const void *free_buf; |
191 | struct iwl_cmd_meta meta; | 197 | struct iwl_cmd_meta meta; |
192 | }; | 198 | }; |
193 | 199 | ||
200 | struct iwl_pcie_txq_scratch_buf { | ||
201 | struct iwl_cmd_header hdr; | ||
202 | u8 buf[8]; | ||
203 | __le32 scratch; | ||
204 | }; | ||
205 | |||
194 | /** | 206 | /** |
195 | * struct iwl_txq - Tx Queue for DMA | 207 | * struct iwl_txq - Tx Queue for DMA |
196 | * @q: generic Rx/Tx queue descriptor | 208 | * @q: generic Rx/Tx queue descriptor |
197 | * @tfds: transmit frame descriptors (DMA memory) | 209 | * @tfds: transmit frame descriptors (DMA memory) |
210 | * @scratchbufs: start of command headers, including scratch buffers, for | ||
211 | * the writeback -- this is DMA memory and an array holding one buffer | ||
212 | * for each command on the queue | ||
213 | * @scratchbufs_dma: DMA address for the scratchbufs start | ||
198 | * @entries: transmit entries (driver state) | 214 | * @entries: transmit entries (driver state) |
199 | * @lock: queue lock | 215 | * @lock: queue lock |
200 | * @stuck_timer: timer that fires if queue gets stuck | 216 | * @stuck_timer: timer that fires if queue gets stuck |
@@ -208,6 +224,8 @@ struct iwl_pcie_txq_entry { | |||
208 | struct iwl_txq { | 224 | struct iwl_txq { |
209 | struct iwl_queue q; | 225 | struct iwl_queue q; |
210 | struct iwl_tfd *tfds; | 226 | struct iwl_tfd *tfds; |
227 | struct iwl_pcie_txq_scratch_buf *scratchbufs; | ||
228 | dma_addr_t scratchbufs_dma; | ||
211 | struct iwl_pcie_txq_entry *entries; | 229 | struct iwl_pcie_txq_entry *entries; |
212 | spinlock_t lock; | 230 | spinlock_t lock; |
213 | struct timer_list stuck_timer; | 231 | struct timer_list stuck_timer; |
@@ -216,6 +234,13 @@ struct iwl_txq { | |||
216 | u8 active; | 234 | u8 active; |
217 | }; | 235 | }; |
218 | 236 | ||
237 | static inline dma_addr_t | ||
238 | iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) | ||
239 | { | ||
240 | return txq->scratchbufs_dma + | ||
241 | sizeof(struct iwl_pcie_txq_scratch_buf) * idx; | ||
242 | } | ||
243 | |||
219 | /** | 244 | /** |
220 | * struct iwl_trans_pcie - PCIe transport specific data | 245 | * struct iwl_trans_pcie - PCIe transport specific data |
221 | * @rxq: all the RX queue data | 246 | * @rxq: all the RX queue data |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index b0ae06d2456f..567e67ad1f61 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -637,22 +637,14 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, | |||
637 | index = SEQ_TO_INDEX(sequence); | 637 | index = SEQ_TO_INDEX(sequence); |
638 | cmd_index = get_cmd_index(&txq->q, index); | 638 | cmd_index = get_cmd_index(&txq->q, index); |
639 | 639 | ||
640 | if (reclaim) { | 640 | if (reclaim) |
641 | struct iwl_pcie_txq_entry *ent; | 641 | cmd = txq->entries[cmd_index].cmd; |
642 | ent = &txq->entries[cmd_index]; | 642 | else |
643 | cmd = ent->copy_cmd; | ||
644 | WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD); | ||
645 | } else { | ||
646 | cmd = NULL; | 643 | cmd = NULL; |
647 | } | ||
648 | 644 | ||
649 | err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); | 645 | err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); |
650 | 646 | ||
651 | if (reclaim) { | 647 | if (reclaim) { |
652 | /* The original command isn't needed any more */ | ||
653 | kfree(txq->entries[cmd_index].copy_cmd); | ||
654 | txq->entries[cmd_index].copy_cmd = NULL; | ||
655 | /* nor is the duplicated part of the command */ | ||
656 | kfree(txq->entries[cmd_index].free_buf); | 648 | kfree(txq->entries[cmd_index].free_buf); |
657 | txq->entries[cmd_index].free_buf = NULL; | 649 | txq->entries[cmd_index].free_buf = NULL; |
658 | } | 650 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 17bedc50e753..50ba0a468f94 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -475,6 +475,10 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | |||
475 | 475 | ||
476 | /* If platform's RF_KILL switch is NOT set to KILL */ | 476 | /* If platform's RF_KILL switch is NOT set to KILL */ |
477 | hw_rfkill = iwl_is_rfkill_set(trans); | 477 | hw_rfkill = iwl_is_rfkill_set(trans); |
478 | if (hw_rfkill) | ||
479 | set_bit(STATUS_RFKILL, &trans_pcie->status); | ||
480 | else | ||
481 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | ||
478 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 482 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); |
479 | if (hw_rfkill && !run_in_rfkill) | 483 | if (hw_rfkill && !run_in_rfkill) |
480 | return -ERFKILL; | 484 | return -ERFKILL; |
@@ -641,6 +645,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | |||
641 | 645 | ||
642 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | 646 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) |
643 | { | 647 | { |
648 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
644 | bool hw_rfkill; | 649 | bool hw_rfkill; |
645 | int err; | 650 | int err; |
646 | 651 | ||
@@ -656,6 +661,10 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | |||
656 | iwl_enable_rfkill_int(trans); | 661 | iwl_enable_rfkill_int(trans); |
657 | 662 | ||
658 | hw_rfkill = iwl_is_rfkill_set(trans); | 663 | hw_rfkill = iwl_is_rfkill_set(trans); |
664 | if (hw_rfkill) | ||
665 | set_bit(STATUS_RFKILL, &trans_pcie->status); | ||
666 | else | ||
667 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | ||
659 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 668 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); |
660 | 669 | ||
661 | return 0; | 670 | return 0; |
@@ -694,6 +703,10 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, | |||
694 | * op_mode. | 703 | * op_mode. |
695 | */ | 704 | */ |
696 | hw_rfkill = iwl_is_rfkill_set(trans); | 705 | hw_rfkill = iwl_is_rfkill_set(trans); |
706 | if (hw_rfkill) | ||
707 | set_bit(STATUS_RFKILL, &trans_pcie->status); | ||
708 | else | ||
709 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | ||
697 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 710 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); |
698 | } | 711 | } |
699 | } | 712 | } |
@@ -715,7 +728,8 @@ static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs) | |||
715 | 728 | ||
716 | static u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg) | 729 | static u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg) |
717 | { | 730 | { |
718 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); | 731 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_RADDR, |
732 | ((reg & 0x000FFFFF) | (3 << 24))); | ||
719 | return iwl_trans_pcie_read32(trans, HBUS_TARG_PRPH_RDAT); | 733 | return iwl_trans_pcie_read32(trans, HBUS_TARG_PRPH_RDAT); |
720 | } | 734 | } |
721 | 735 | ||
@@ -723,7 +737,7 @@ static void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, | |||
723 | u32 val) | 737 | u32 val) |
724 | { | 738 | { |
725 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WADDR, | 739 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WADDR, |
726 | ((addr & 0x0000FFFF) | (3 << 24))); | 740 | ((addr & 0x000FFFFF) | (3 << 24))); |
727 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); | 741 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); |
728 | } | 742 | } |
729 | 743 | ||
@@ -1370,28 +1384,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | |||
1370 | return ret; | 1384 | return ret; |
1371 | } | 1385 | } |
1372 | 1386 | ||
1373 | static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | ||
1374 | const char __user *user_buf, | ||
1375 | size_t count, loff_t *ppos) | ||
1376 | { | ||
1377 | struct iwl_trans *trans = file->private_data; | ||
1378 | |||
1379 | if (!trans->op_mode) | ||
1380 | return -EAGAIN; | ||
1381 | |||
1382 | local_bh_disable(); | ||
1383 | iwl_op_mode_nic_error(trans->op_mode); | ||
1384 | local_bh_enable(); | ||
1385 | |||
1386 | return count; | ||
1387 | } | ||
1388 | |||
1389 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | 1387 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); |
1390 | DEBUGFS_READ_FILE_OPS(fh_reg); | 1388 | DEBUGFS_READ_FILE_OPS(fh_reg); |
1391 | DEBUGFS_READ_FILE_OPS(rx_queue); | 1389 | DEBUGFS_READ_FILE_OPS(rx_queue); |
1392 | DEBUGFS_READ_FILE_OPS(tx_queue); | 1390 | DEBUGFS_READ_FILE_OPS(tx_queue); |
1393 | DEBUGFS_WRITE_FILE_OPS(csr); | 1391 | DEBUGFS_WRITE_FILE_OPS(csr); |
1394 | DEBUGFS_WRITE_FILE_OPS(fw_restart); | ||
1395 | 1392 | ||
1396 | /* | 1393 | /* |
1397 | * Create the debugfs files and directories | 1394 | * Create the debugfs files and directories |
@@ -1405,7 +1402,6 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | |||
1405 | DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); | 1402 | DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); |
1406 | DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); | 1403 | DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); |
1407 | DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); | 1404 | DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); |
1408 | DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR); | ||
1409 | return 0; | 1405 | return 0; |
1410 | 1406 | ||
1411 | err: | 1407 | err: |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index ad7441dfa6fb..d97c1fad7bc3 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -191,12 +191,9 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
191 | } | 191 | } |
192 | 192 | ||
193 | for (i = q->read_ptr; i != q->write_ptr; | 193 | for (i = q->read_ptr; i != q->write_ptr; |
194 | i = iwl_queue_inc_wrap(i, q->n_bd)) { | 194 | i = iwl_queue_inc_wrap(i, q->n_bd)) |
195 | struct iwl_tx_cmd *tx_cmd = | ||
196 | (struct iwl_tx_cmd *)txq->entries[i].cmd->payload; | ||
197 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, | 195 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, |
198 | get_unaligned_le32(&tx_cmd->scratch)); | 196 | le32_to_cpu(txq->scratchbufs[i].scratch)); |
199 | } | ||
200 | 197 | ||
201 | iwl_op_mode_nic_error(trans->op_mode); | 198 | iwl_op_mode_nic_error(trans->op_mode); |
202 | } | 199 | } |
@@ -367,8 +364,8 @@ static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_tfd *tfd) | |||
367 | } | 364 | } |
368 | 365 | ||
369 | static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, | 366 | static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, |
370 | struct iwl_cmd_meta *meta, struct iwl_tfd *tfd, | 367 | struct iwl_cmd_meta *meta, |
371 | enum dma_data_direction dma_dir) | 368 | struct iwl_tfd *tfd) |
372 | { | 369 | { |
373 | int i; | 370 | int i; |
374 | int num_tbs; | 371 | int num_tbs; |
@@ -382,17 +379,12 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, | |||
382 | return; | 379 | return; |
383 | } | 380 | } |
384 | 381 | ||
385 | /* Unmap tx_cmd */ | 382 | /* first TB is never freed - it's the scratchbuf data */ |
386 | if (num_tbs) | ||
387 | dma_unmap_single(trans->dev, | ||
388 | dma_unmap_addr(meta, mapping), | ||
389 | dma_unmap_len(meta, len), | ||
390 | DMA_BIDIRECTIONAL); | ||
391 | 383 | ||
392 | /* Unmap chunks, if any. */ | ||
393 | for (i = 1; i < num_tbs; i++) | 384 | for (i = 1; i < num_tbs; i++) |
394 | dma_unmap_single(trans->dev, iwl_pcie_tfd_tb_get_addr(tfd, i), | 385 | dma_unmap_single(trans->dev, iwl_pcie_tfd_tb_get_addr(tfd, i), |
395 | iwl_pcie_tfd_tb_get_len(tfd, i), dma_dir); | 386 | iwl_pcie_tfd_tb_get_len(tfd, i), |
387 | DMA_TO_DEVICE); | ||
396 | 388 | ||
397 | tfd->num_tbs = 0; | 389 | tfd->num_tbs = 0; |
398 | } | 390 | } |
@@ -406,8 +398,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, | |||
406 | * Does NOT advance any TFD circular buffer read/write indexes | 398 | * Does NOT advance any TFD circular buffer read/write indexes |
407 | * Does NOT free the TFD itself (which is within circular buffer) | 399 | * Does NOT free the TFD itself (which is within circular buffer) |
408 | */ | 400 | */ |
409 | static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq, | 401 | static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq) |
410 | enum dma_data_direction dma_dir) | ||
411 | { | 402 | { |
412 | struct iwl_tfd *tfd_tmp = txq->tfds; | 403 | struct iwl_tfd *tfd_tmp = txq->tfds; |
413 | 404 | ||
@@ -418,8 +409,7 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq, | |||
418 | lockdep_assert_held(&txq->lock); | 409 | lockdep_assert_held(&txq->lock); |
419 | 410 | ||
420 | /* We have only q->n_window txq->entries, but we use q->n_bd tfds */ | 411 | /* We have only q->n_window txq->entries, but we use q->n_bd tfds */ |
421 | iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr], | 412 | iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]); |
422 | dma_dir); | ||
423 | 413 | ||
424 | /* free SKB */ | 414 | /* free SKB */ |
425 | if (txq->entries) { | 415 | if (txq->entries) { |
@@ -479,6 +469,7 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans, | |||
479 | { | 469 | { |
480 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 470 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
481 | size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; | 471 | size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; |
472 | size_t scratchbuf_sz; | ||
482 | int i; | 473 | int i; |
483 | 474 | ||
484 | if (WARN_ON(txq->entries || txq->tfds)) | 475 | if (WARN_ON(txq->entries || txq->tfds)) |
@@ -514,9 +505,25 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans, | |||
514 | IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); | 505 | IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); |
515 | goto error; | 506 | goto error; |
516 | } | 507 | } |
508 | |||
509 | BUILD_BUG_ON(IWL_HCMD_SCRATCHBUF_SIZE != sizeof(*txq->scratchbufs)); | ||
510 | BUILD_BUG_ON(offsetof(struct iwl_pcie_txq_scratch_buf, scratch) != | ||
511 | sizeof(struct iwl_cmd_header) + | ||
512 | offsetof(struct iwl_tx_cmd, scratch)); | ||
513 | |||
514 | scratchbuf_sz = sizeof(*txq->scratchbufs) * slots_num; | ||
515 | |||
516 | txq->scratchbufs = dma_alloc_coherent(trans->dev, scratchbuf_sz, | ||
517 | &txq->scratchbufs_dma, | ||
518 | GFP_KERNEL); | ||
519 | if (!txq->scratchbufs) | ||
520 | goto err_free_tfds; | ||
521 | |||
517 | txq->q.id = txq_id; | 522 | txq->q.id = txq_id; |
518 | 523 | ||
519 | return 0; | 524 | return 0; |
525 | err_free_tfds: | ||
526 | dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->q.dma_addr); | ||
520 | error: | 527 | error: |
521 | if (txq->entries && txq_id == trans_pcie->cmd_queue) | 528 | if (txq->entries && txq_id == trans_pcie->cmd_queue) |
522 | for (i = 0; i < slots_num; i++) | 529 | for (i = 0; i < slots_num; i++) |
@@ -565,22 +572,13 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) | |||
565 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 572 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
566 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; | 573 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; |
567 | struct iwl_queue *q = &txq->q; | 574 | struct iwl_queue *q = &txq->q; |
568 | enum dma_data_direction dma_dir; | ||
569 | 575 | ||
570 | if (!q->n_bd) | 576 | if (!q->n_bd) |
571 | return; | 577 | return; |
572 | 578 | ||
573 | /* In the command queue, all the TBs are mapped as BIDI | ||
574 | * so unmap them as such. | ||
575 | */ | ||
576 | if (txq_id == trans_pcie->cmd_queue) | ||
577 | dma_dir = DMA_BIDIRECTIONAL; | ||
578 | else | ||
579 | dma_dir = DMA_TO_DEVICE; | ||
580 | |||
581 | spin_lock_bh(&txq->lock); | 579 | spin_lock_bh(&txq->lock); |
582 | while (q->write_ptr != q->read_ptr) { | 580 | while (q->write_ptr != q->read_ptr) { |
583 | iwl_pcie_txq_free_tfd(trans, txq, dma_dir); | 581 | iwl_pcie_txq_free_tfd(trans, txq); |
584 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | 582 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); |
585 | } | 583 | } |
586 | spin_unlock_bh(&txq->lock); | 584 | spin_unlock_bh(&txq->lock); |
@@ -610,7 +608,6 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) | |||
610 | if (txq_id == trans_pcie->cmd_queue) | 608 | if (txq_id == trans_pcie->cmd_queue) |
611 | for (i = 0; i < txq->q.n_window; i++) { | 609 | for (i = 0; i < txq->q.n_window; i++) { |
612 | kfree(txq->entries[i].cmd); | 610 | kfree(txq->entries[i].cmd); |
613 | kfree(txq->entries[i].copy_cmd); | ||
614 | kfree(txq->entries[i].free_buf); | 611 | kfree(txq->entries[i].free_buf); |
615 | } | 612 | } |
616 | 613 | ||
@@ -619,6 +616,10 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) | |||
619 | dma_free_coherent(dev, sizeof(struct iwl_tfd) * | 616 | dma_free_coherent(dev, sizeof(struct iwl_tfd) * |
620 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 617 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); |
621 | txq->q.dma_addr = 0; | 618 | txq->q.dma_addr = 0; |
619 | |||
620 | dma_free_coherent(dev, | ||
621 | sizeof(*txq->scratchbufs) * txq->q.n_window, | ||
622 | txq->scratchbufs, txq->scratchbufs_dma); | ||
622 | } | 623 | } |
623 | 624 | ||
624 | kfree(txq->entries); | 625 | kfree(txq->entries); |
@@ -962,7 +963,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
962 | 963 | ||
963 | iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq); | 964 | iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq); |
964 | 965 | ||
965 | iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE); | 966 | iwl_pcie_txq_free_tfd(trans, txq); |
966 | } | 967 | } |
967 | 968 | ||
968 | iwl_pcie_txq_progress(trans_pcie, txq); | 969 | iwl_pcie_txq_progress(trans_pcie, txq); |
@@ -1062,7 +1063,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, | |||
1062 | iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); | 1063 | iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); |
1063 | 1064 | ||
1064 | /* If this queue is mapped to a certain station: it is an AGG queue */ | 1065 | /* If this queue is mapped to a certain station: it is an AGG queue */ |
1065 | if (sta_id != IWL_INVALID_STATION) { | 1066 | if (sta_id >= 0) { |
1066 | u16 ra_tid = BUILD_RAxTID(sta_id, tid); | 1067 | u16 ra_tid = BUILD_RAxTID(sta_id, tid); |
1067 | 1068 | ||
1068 | /* Map receiver-address / traffic-ID to this queue */ | 1069 | /* Map receiver-address / traffic-ID to this queue */ |
@@ -1152,20 +1153,37 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1152 | void *dup_buf = NULL; | 1153 | void *dup_buf = NULL; |
1153 | dma_addr_t phys_addr; | 1154 | dma_addr_t phys_addr; |
1154 | int idx; | 1155 | int idx; |
1155 | u16 copy_size, cmd_size; | 1156 | u16 copy_size, cmd_size, scratch_size; |
1156 | bool had_nocopy = false; | 1157 | bool had_nocopy = false; |
1157 | int i; | 1158 | int i; |
1158 | u32 cmd_pos; | 1159 | u32 cmd_pos; |
1160 | const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD]; | ||
1161 | u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD]; | ||
1159 | 1162 | ||
1160 | copy_size = sizeof(out_cmd->hdr); | 1163 | copy_size = sizeof(out_cmd->hdr); |
1161 | cmd_size = sizeof(out_cmd->hdr); | 1164 | cmd_size = sizeof(out_cmd->hdr); |
1162 | 1165 | ||
1163 | /* need one for the header if the first is NOCOPY */ | 1166 | /* need one for the header if the first is NOCOPY */ |
1164 | BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1); | 1167 | BUILD_BUG_ON(IWL_MAX_CMD_TBS_PER_TFD > IWL_NUM_OF_TBS - 1); |
1168 | |||
1169 | for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { | ||
1170 | cmddata[i] = cmd->data[i]; | ||
1171 | cmdlen[i] = cmd->len[i]; | ||
1165 | 1172 | ||
1166 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | ||
1167 | if (!cmd->len[i]) | 1173 | if (!cmd->len[i]) |
1168 | continue; | 1174 | continue; |
1175 | |||
1176 | /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */ | ||
1177 | if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) { | ||
1178 | int copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size; | ||
1179 | |||
1180 | if (copy > cmdlen[i]) | ||
1181 | copy = cmdlen[i]; | ||
1182 | cmdlen[i] -= copy; | ||
1183 | cmddata[i] += copy; | ||
1184 | copy_size += copy; | ||
1185 | } | ||
1186 | |||
1169 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { | 1187 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { |
1170 | had_nocopy = true; | 1188 | had_nocopy = true; |
1171 | if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { | 1189 | if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { |
@@ -1185,7 +1203,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1185 | goto free_dup_buf; | 1203 | goto free_dup_buf; |
1186 | } | 1204 | } |
1187 | 1205 | ||
1188 | dup_buf = kmemdup(cmd->data[i], cmd->len[i], | 1206 | dup_buf = kmemdup(cmddata[i], cmdlen[i], |
1189 | GFP_ATOMIC); | 1207 | GFP_ATOMIC); |
1190 | if (!dup_buf) | 1208 | if (!dup_buf) |
1191 | return -ENOMEM; | 1209 | return -ENOMEM; |
@@ -1195,7 +1213,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1195 | idx = -EINVAL; | 1213 | idx = -EINVAL; |
1196 | goto free_dup_buf; | 1214 | goto free_dup_buf; |
1197 | } | 1215 | } |
1198 | copy_size += cmd->len[i]; | 1216 | copy_size += cmdlen[i]; |
1199 | } | 1217 | } |
1200 | cmd_size += cmd->len[i]; | 1218 | cmd_size += cmd->len[i]; |
1201 | } | 1219 | } |
@@ -1242,30 +1260,30 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1242 | 1260 | ||
1243 | /* and copy the data that needs to be copied */ | 1261 | /* and copy the data that needs to be copied */ |
1244 | cmd_pos = offsetof(struct iwl_device_cmd, payload); | 1262 | cmd_pos = offsetof(struct iwl_device_cmd, payload); |
1245 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 1263 | copy_size = sizeof(out_cmd->hdr); |
1264 | for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { | ||
1265 | int copy = 0; | ||
1266 | |||
1246 | if (!cmd->len[i]) | 1267 | if (!cmd->len[i]) |
1247 | continue; | 1268 | continue; |
1248 | if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | | ||
1249 | IWL_HCMD_DFL_DUP)) | ||
1250 | break; | ||
1251 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]); | ||
1252 | cmd_pos += cmd->len[i]; | ||
1253 | } | ||
1254 | 1269 | ||
1255 | WARN_ON_ONCE(txq->entries[idx].copy_cmd); | 1270 | /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */ |
1271 | if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) { | ||
1272 | copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size; | ||
1256 | 1273 | ||
1257 | /* | 1274 | if (copy > cmd->len[i]) |
1258 | * since out_cmd will be the source address of the FH, it will write | 1275 | copy = cmd->len[i]; |
1259 | * the retry count there. So when the user needs to receivce the HCMD | 1276 | } |
1260 | * that corresponds to the response in the response handler, it needs | 1277 | |
1261 | * to set CMD_WANT_HCMD. | 1278 | /* copy everything if not nocopy/dup */ |
1262 | */ | 1279 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | |
1263 | if (cmd->flags & CMD_WANT_HCMD) { | 1280 | IWL_HCMD_DFL_DUP))) |
1264 | txq->entries[idx].copy_cmd = | 1281 | copy = cmd->len[i]; |
1265 | kmemdup(out_cmd, cmd_pos, GFP_ATOMIC); | 1282 | |
1266 | if (unlikely(!txq->entries[idx].copy_cmd)) { | 1283 | if (copy) { |
1267 | idx = -ENOMEM; | 1284 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); |
1268 | goto out; | 1285 | cmd_pos += copy; |
1286 | copy_size += copy; | ||
1269 | } | 1287 | } |
1270 | } | 1288 | } |
1271 | 1289 | ||
@@ -1275,22 +1293,35 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1275 | out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), | 1293 | out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), |
1276 | cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue); | 1294 | cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue); |
1277 | 1295 | ||
1278 | phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, | 1296 | /* start the TFD with the scratchbuf */ |
1279 | DMA_BIDIRECTIONAL); | 1297 | scratch_size = min_t(int, copy_size, IWL_HCMD_SCRATCHBUF_SIZE); |
1280 | if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { | 1298 | memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size); |
1281 | idx = -ENOMEM; | 1299 | iwl_pcie_txq_build_tfd(trans, txq, |
1282 | goto out; | 1300 | iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr), |
1283 | } | 1301 | scratch_size, 1); |
1284 | 1302 | ||
1285 | dma_unmap_addr_set(out_meta, mapping, phys_addr); | 1303 | /* map first command fragment, if any remains */ |
1286 | dma_unmap_len_set(out_meta, len, copy_size); | 1304 | if (copy_size > scratch_size) { |
1305 | phys_addr = dma_map_single(trans->dev, | ||
1306 | ((u8 *)&out_cmd->hdr) + scratch_size, | ||
1307 | copy_size - scratch_size, | ||
1308 | DMA_TO_DEVICE); | ||
1309 | if (dma_mapping_error(trans->dev, phys_addr)) { | ||
1310 | iwl_pcie_tfd_unmap(trans, out_meta, | ||
1311 | &txq->tfds[q->write_ptr]); | ||
1312 | idx = -ENOMEM; | ||
1313 | goto out; | ||
1314 | } | ||
1287 | 1315 | ||
1288 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1); | 1316 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, |
1317 | copy_size - scratch_size, 0); | ||
1318 | } | ||
1289 | 1319 | ||
1290 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 1320 | /* map the remaining (adjusted) nocopy/dup fragments */ |
1291 | const void *data = cmd->data[i]; | 1321 | for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { |
1322 | const void *data = cmddata[i]; | ||
1292 | 1323 | ||
1293 | if (!cmd->len[i]) | 1324 | if (!cmdlen[i]) |
1294 | continue; | 1325 | continue; |
1295 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | | 1326 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | |
1296 | IWL_HCMD_DFL_DUP))) | 1327 | IWL_HCMD_DFL_DUP))) |
@@ -1298,16 +1329,15 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1298 | if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) | 1329 | if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) |
1299 | data = dup_buf; | 1330 | data = dup_buf; |
1300 | phys_addr = dma_map_single(trans->dev, (void *)data, | 1331 | phys_addr = dma_map_single(trans->dev, (void *)data, |
1301 | cmd->len[i], DMA_BIDIRECTIONAL); | 1332 | cmdlen[i], DMA_TO_DEVICE); |
1302 | if (dma_mapping_error(trans->dev, phys_addr)) { | 1333 | if (dma_mapping_error(trans->dev, phys_addr)) { |
1303 | iwl_pcie_tfd_unmap(trans, out_meta, | 1334 | iwl_pcie_tfd_unmap(trans, out_meta, |
1304 | &txq->tfds[q->write_ptr], | 1335 | &txq->tfds[q->write_ptr]); |
1305 | DMA_BIDIRECTIONAL); | ||
1306 | idx = -ENOMEM; | 1336 | idx = -ENOMEM; |
1307 | goto out; | 1337 | goto out; |
1308 | } | 1338 | } |
1309 | 1339 | ||
1310 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0); | 1340 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0); |
1311 | } | 1341 | } |
1312 | 1342 | ||
1313 | out_meta->flags = cmd->flags; | 1343 | out_meta->flags = cmd->flags; |
@@ -1317,8 +1347,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1317 | 1347 | ||
1318 | txq->need_update = 1; | 1348 | txq->need_update = 1; |
1319 | 1349 | ||
1320 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, | 1350 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); |
1321 | &out_cmd->hdr, copy_size); | ||
1322 | 1351 | ||
1323 | /* start timer if queue currently empty */ | 1352 | /* start timer if queue currently empty */ |
1324 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) | 1353 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) |
@@ -1377,7 +1406,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, | |||
1377 | cmd = txq->entries[cmd_index].cmd; | 1406 | cmd = txq->entries[cmd_index].cmd; |
1378 | meta = &txq->entries[cmd_index].meta; | 1407 | meta = &txq->entries[cmd_index].meta; |
1379 | 1408 | ||
1380 | iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); | 1409 | iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index]); |
1381 | 1410 | ||
1382 | /* Input error checking is done when commands are added to queue. */ | 1411 | /* Input error checking is done when commands are added to queue. */ |
1383 | if (meta->flags & CMD_WANT_SKB) { | 1412 | if (meta->flags & CMD_WANT_SKB) { |
@@ -1537,8 +1566,11 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
1537 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) | 1566 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) |
1538 | return -EIO; | 1567 | return -EIO; |
1539 | 1568 | ||
1540 | if (test_bit(STATUS_RFKILL, &trans_pcie->status)) | 1569 | if (test_bit(STATUS_RFKILL, &trans_pcie->status)) { |
1570 | IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n", | ||
1571 | cmd->id); | ||
1541 | return -ERFKILL; | 1572 | return -ERFKILL; |
1573 | } | ||
1542 | 1574 | ||
1543 | if (cmd->flags & CMD_ASYNC) | 1575 | if (cmd->flags & CMD_ASYNC) |
1544 | return iwl_pcie_send_hcmd_async(trans, cmd); | 1576 | return iwl_pcie_send_hcmd_async(trans, cmd); |
@@ -1556,10 +1588,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1556 | struct iwl_cmd_meta *out_meta; | 1588 | struct iwl_cmd_meta *out_meta; |
1557 | struct iwl_txq *txq; | 1589 | struct iwl_txq *txq; |
1558 | struct iwl_queue *q; | 1590 | struct iwl_queue *q; |
1559 | dma_addr_t phys_addr = 0; | 1591 | dma_addr_t tb0_phys, tb1_phys, scratch_phys; |
1560 | dma_addr_t txcmd_phys; | 1592 | void *tb1_addr; |
1561 | dma_addr_t scratch_phys; | 1593 | u16 len, tb1_len, tb2_len; |
1562 | u16 len, firstlen, secondlen; | ||
1563 | u8 wait_write_ptr = 0; | 1594 | u8 wait_write_ptr = 0; |
1564 | __le16 fc = hdr->frame_control; | 1595 | __le16 fc = hdr->frame_control; |
1565 | u8 hdr_len = ieee80211_hdrlen(fc); | 1596 | u8 hdr_len = ieee80211_hdrlen(fc); |
@@ -1597,85 +1628,80 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1597 | cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | 1628 | cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | |
1598 | INDEX_TO_SEQ(q->write_ptr))); | 1629 | INDEX_TO_SEQ(q->write_ptr))); |
1599 | 1630 | ||
1631 | tb0_phys = iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr); | ||
1632 | scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) + | ||
1633 | offsetof(struct iwl_tx_cmd, scratch); | ||
1634 | |||
1635 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
1636 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
1637 | |||
1600 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | 1638 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ |
1601 | out_meta = &txq->entries[q->write_ptr].meta; | 1639 | out_meta = &txq->entries[q->write_ptr].meta; |
1602 | 1640 | ||
1603 | /* | 1641 | /* |
1604 | * Use the first empty entry in this queue's command buffer array | 1642 | * The second TB (tb1) points to the remainder of the TX command |
1605 | * to contain the Tx command and MAC header concatenated together | 1643 | * and the 802.11 header - dword aligned size |
1606 | * (payload data will be in another buffer). | 1644 | * (This calculation modifies the TX command, so do it before the |
1607 | * Size of this varies, due to varying MAC header length. | 1645 | * setup of the first TB) |
1608 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
1609 | * of the MAC header (device reads on dword boundaries). | ||
1610 | * We'll tell device about this padding later. | ||
1611 | */ | 1646 | */ |
1612 | len = sizeof(struct iwl_tx_cmd) + | 1647 | len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) + |
1613 | sizeof(struct iwl_cmd_header) + hdr_len; | 1648 | hdr_len - IWL_HCMD_SCRATCHBUF_SIZE; |
1614 | firstlen = (len + 3) & ~3; | 1649 | tb1_len = (len + 3) & ~3; |
1615 | 1650 | ||
1616 | /* Tell NIC about any 2-byte padding after MAC header */ | 1651 | /* Tell NIC about any 2-byte padding after MAC header */ |
1617 | if (firstlen != len) | 1652 | if (tb1_len != len) |
1618 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | 1653 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; |
1619 | 1654 | ||
1620 | /* Physical address of this Tx command's header (not MAC header!), | 1655 | /* The first TB points to the scratchbuf data - min_copy bytes */ |
1621 | * within command buffer array. */ | 1656 | memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr, |
1622 | txcmd_phys = dma_map_single(trans->dev, | 1657 | IWL_HCMD_SCRATCHBUF_SIZE); |
1623 | &dev_cmd->hdr, firstlen, | 1658 | iwl_pcie_txq_build_tfd(trans, txq, tb0_phys, |
1624 | DMA_BIDIRECTIONAL); | 1659 | IWL_HCMD_SCRATCHBUF_SIZE, 1); |
1625 | if (unlikely(dma_mapping_error(trans->dev, txcmd_phys))) | ||
1626 | goto out_err; | ||
1627 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
1628 | dma_unmap_len_set(out_meta, len, firstlen); | ||
1629 | 1660 | ||
1630 | if (!ieee80211_has_morefrags(fc)) { | 1661 | /* there must be data left over for TB1 or this code must be changed */ |
1631 | txq->need_update = 1; | 1662 | BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE); |
1632 | } else { | 1663 | |
1633 | wait_write_ptr = 1; | 1664 | /* map the data for TB1 */ |
1634 | txq->need_update = 0; | 1665 | tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_HCMD_SCRATCHBUF_SIZE; |
1635 | } | 1666 | tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE); |
1667 | if (unlikely(dma_mapping_error(trans->dev, tb1_phys))) | ||
1668 | goto out_err; | ||
1669 | iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 0); | ||
1636 | 1670 | ||
1637 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | 1671 | /* |
1638 | * if any (802.11 null frames have no payload). */ | 1672 | * Set up TFD's third entry to point directly to remainder |
1639 | secondlen = skb->len - hdr_len; | 1673 | * of skb, if any (802.11 null frames have no payload). |
1640 | if (secondlen > 0) { | 1674 | */ |
1641 | phys_addr = dma_map_single(trans->dev, skb->data + hdr_len, | 1675 | tb2_len = skb->len - hdr_len; |
1642 | secondlen, DMA_TO_DEVICE); | 1676 | if (tb2_len > 0) { |
1643 | if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { | 1677 | dma_addr_t tb2_phys = dma_map_single(trans->dev, |
1644 | dma_unmap_single(trans->dev, | 1678 | skb->data + hdr_len, |
1645 | dma_unmap_addr(out_meta, mapping), | 1679 | tb2_len, DMA_TO_DEVICE); |
1646 | dma_unmap_len(out_meta, len), | 1680 | if (unlikely(dma_mapping_error(trans->dev, tb2_phys))) { |
1647 | DMA_BIDIRECTIONAL); | 1681 | iwl_pcie_tfd_unmap(trans, out_meta, |
1682 | &txq->tfds[q->write_ptr]); | ||
1648 | goto out_err; | 1683 | goto out_err; |
1649 | } | 1684 | } |
1685 | iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 0); | ||
1650 | } | 1686 | } |
1651 | 1687 | ||
1652 | /* Attach buffers to TFD */ | ||
1653 | iwl_pcie_txq_build_tfd(trans, txq, txcmd_phys, firstlen, 1); | ||
1654 | if (secondlen > 0) | ||
1655 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, secondlen, 0); | ||
1656 | |||
1657 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
1658 | offsetof(struct iwl_tx_cmd, scratch); | ||
1659 | |||
1660 | /* take back ownership of DMA buffer to enable update */ | ||
1661 | dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen, | ||
1662 | DMA_BIDIRECTIONAL); | ||
1663 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
1664 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
1665 | |||
1666 | /* Set up entry for this TFD in Tx byte-count array */ | 1688 | /* Set up entry for this TFD in Tx byte-count array */ |
1667 | iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); | 1689 | iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); |
1668 | 1690 | ||
1669 | dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, | ||
1670 | DMA_BIDIRECTIONAL); | ||
1671 | |||
1672 | trace_iwlwifi_dev_tx(trans->dev, skb, | 1691 | trace_iwlwifi_dev_tx(trans->dev, skb, |
1673 | &txq->tfds[txq->q.write_ptr], | 1692 | &txq->tfds[txq->q.write_ptr], |
1674 | sizeof(struct iwl_tfd), | 1693 | sizeof(struct iwl_tfd), |
1675 | &dev_cmd->hdr, firstlen, | 1694 | &dev_cmd->hdr, IWL_HCMD_SCRATCHBUF_SIZE + tb1_len, |
1676 | skb->data + hdr_len, secondlen); | 1695 | skb->data + hdr_len, tb2_len); |
1677 | trace_iwlwifi_dev_tx_data(trans->dev, skb, | 1696 | trace_iwlwifi_dev_tx_data(trans->dev, skb, |
1678 | skb->data + hdr_len, secondlen); | 1697 | skb->data + hdr_len, tb2_len); |
1698 | |||
1699 | if (!ieee80211_has_morefrags(fc)) { | ||
1700 | txq->need_update = 1; | ||
1701 | } else { | ||
1702 | wait_write_ptr = 1; | ||
1703 | txq->need_update = 0; | ||
1704 | } | ||
1679 | 1705 | ||
1680 | /* start timer if queue currently empty */ | 1706 | /* start timer if queue currently empty */ |
1681 | if (txq->need_update && q->read_ptr == q->write_ptr && | 1707 | if (txq->need_update && q->read_ptr == q->write_ptr && |
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/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c index cf43b3c29250..966a78f8e21a 100644 --- a/drivers/net/wireless/mwifiex/11ac.c +++ b/drivers/net/wireless/mwifiex/11ac.c | |||
@@ -259,3 +259,44 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, | |||
259 | 259 | ||
260 | return ret_len; | 260 | return ret_len; |
261 | } | 261 | } |
262 | |||
263 | int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv, | ||
264 | struct host_cmd_ds_command *cmd, u16 cmd_action, | ||
265 | struct mwifiex_11ac_vht_cfg *cfg) | ||
266 | { | ||
267 | struct host_cmd_11ac_vht_cfg *vhtcfg = &cmd->params.vht_cfg; | ||
268 | |||
269 | cmd->command = cpu_to_le16(HostCmd_CMD_11AC_CFG); | ||
270 | cmd->size = cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) + | ||
271 | S_DS_GEN); | ||
272 | vhtcfg->action = cpu_to_le16(cmd_action); | ||
273 | vhtcfg->band_config = cfg->band_config; | ||
274 | vhtcfg->misc_config = cfg->misc_config; | ||
275 | vhtcfg->cap_info = cpu_to_le32(cfg->cap_info); | ||
276 | vhtcfg->mcs_tx_set = cpu_to_le32(cfg->mcs_tx_set); | ||
277 | vhtcfg->mcs_rx_set = cpu_to_le32(cfg->mcs_rx_set); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | /* This function initializes the BlockACK setup information for given | ||
283 | * mwifiex_private structure for 11ac enabled networks. | ||
284 | */ | ||
285 | void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv) | ||
286 | { | ||
287 | priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; | ||
288 | |||
289 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | ||
290 | priv->add_ba_param.tx_win_size = | ||
291 | MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE; | ||
292 | priv->add_ba_param.rx_win_size = | ||
293 | MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE; | ||
294 | } else { | ||
295 | priv->add_ba_param.tx_win_size = | ||
296 | MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE; | ||
297 | priv->add_ba_param.rx_win_size = | ||
298 | MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE; | ||
299 | } | ||
300 | |||
301 | return; | ||
302 | } | ||
diff --git a/drivers/net/wireless/mwifiex/11ac.h b/drivers/net/wireless/mwifiex/11ac.h index 80fd1ba46200..7c2c69b5b3eb 100644 --- a/drivers/net/wireless/mwifiex/11ac.h +++ b/drivers/net/wireless/mwifiex/11ac.h | |||
@@ -20,7 +20,24 @@ | |||
20 | #ifndef _MWIFIEX_11AC_H_ | 20 | #ifndef _MWIFIEX_11AC_H_ |
21 | #define _MWIFIEX_11AC_H_ | 21 | #define _MWIFIEX_11AC_H_ |
22 | 22 | ||
23 | #define VHT_CFG_2GHZ BIT(0) | ||
24 | #define VHT_CFG_5GHZ BIT(1) | ||
25 | |||
26 | enum vht_cfg_misc_config { | ||
27 | VHT_CAP_TX_OPERATION = 1, | ||
28 | VHT_CAP_ASSOCIATION, | ||
29 | VHT_CAP_UAP_ONLY | ||
30 | }; | ||
31 | |||
32 | #define DEFAULT_VHT_MCS_SET 0xfffa | ||
33 | #define DISABLE_VHT_MCS_SET 0xffff | ||
34 | |||
35 | #define VHT_BW_80_160_80P80 BIT(2) | ||
36 | |||
23 | int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, | 37 | int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, |
24 | struct mwifiex_bssdescriptor *bss_desc, | 38 | struct mwifiex_bssdescriptor *bss_desc, |
25 | u8 **buffer); | 39 | u8 **buffer); |
40 | int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv, | ||
41 | struct host_cmd_ds_command *cmd, u16 cmd_action, | ||
42 | struct mwifiex_11ac_vht_cfg *cfg); | ||
26 | #endif /* _MWIFIEX_11AC_H_ */ | 43 | #endif /* _MWIFIEX_11AC_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 45f19716687e..41e9d25a2d8e 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -679,3 +679,25 @@ void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra) | |||
679 | 679 | ||
680 | return; | 680 | return; |
681 | } | 681 | } |
682 | |||
683 | /* This function initializes the BlockACK setup information for given | ||
684 | * mwifiex_private structure. | ||
685 | */ | ||
686 | void mwifiex_set_ba_params(struct mwifiex_private *priv) | ||
687 | { | ||
688 | priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; | ||
689 | |||
690 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | ||
691 | priv->add_ba_param.tx_win_size = | ||
692 | MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE; | ||
693 | priv->add_ba_param.rx_win_size = | ||
694 | MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE; | ||
695 | } else { | ||
696 | priv->add_ba_param.tx_win_size = | ||
697 | MWIFIEX_STA_AMPDU_DEF_TXWINSIZE; | ||
698 | priv->add_ba_param.rx_win_size = | ||
699 | MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; | ||
700 | } | ||
701 | |||
702 | return; | ||
703 | } | ||
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..47012947a447 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1374,6 +1374,18 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1374 | } | 1374 | } |
1375 | 1375 | ||
1376 | mwifiex_set_ht_params(priv, bss_cfg, params); | 1376 | mwifiex_set_ht_params(priv, bss_cfg, params); |
1377 | |||
1378 | if (priv->adapter->is_hw_11ac_capable) { | ||
1379 | mwifiex_set_vht_params(priv, bss_cfg, params); | ||
1380 | mwifiex_set_vht_width(priv, params->chandef.width, | ||
1381 | priv->ap_11ac_enabled); | ||
1382 | } | ||
1383 | |||
1384 | if (priv->ap_11ac_enabled) | ||
1385 | mwifiex_set_11ac_ba_params(priv); | ||
1386 | else | ||
1387 | mwifiex_set_ba_params(priv); | ||
1388 | |||
1377 | mwifiex_set_wmm_params(priv, bss_cfg, params); | 1389 | mwifiex_set_wmm_params(priv, bss_cfg, params); |
1378 | 1390 | ||
1379 | if (params->inactivity_timeout > 0) { | 1391 | if (params->inactivity_timeout > 0) { |
@@ -1892,7 +1904,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, | |||
1892 | } | 1904 | } |
1893 | } | 1905 | } |
1894 | 1906 | ||
1895 | for (i = 0; i < request->n_channels; i++) { | 1907 | for (i = 0; i < min_t(u32, request->n_channels, |
1908 | MWIFIEX_USER_SCAN_CHAN_MAX); i++) { | ||
1896 | chan = request->channels[i]; | 1909 | chan = request->channels[i]; |
1897 | priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value; | 1910 | priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value; |
1898 | priv->user_scan_cfg->chan_list[i].radio_type = chan->band; | 1911 | priv->user_scan_cfg->chan_list[i].radio_type = chan->band; |
@@ -1932,66 +1945,10 @@ static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info, | |||
1932 | struct mwifiex_private *priv) | 1945 | struct mwifiex_private *priv) |
1933 | { | 1946 | { |
1934 | struct mwifiex_adapter *adapter = priv->adapter; | 1947 | struct mwifiex_adapter *adapter = priv->adapter; |
1935 | u32 vht_cap = 0, cap = adapter->hw_dot_11ac_dev_cap; | ||
1936 | 1948 | ||
1937 | vht_info->vht_supported = true; | 1949 | vht_info->vht_supported = true; |
1938 | 1950 | ||
1939 | switch (GET_VHTCAP_MAXMPDULEN(cap)) { | 1951 | 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 */ | 1952 | /* Update MCS support for VHT */ |
1996 | vht_info->vht_mcs.rx_mcs_map = cpu_to_le16( | 1953 | vht_info->vht_mcs.rx_mcs_map = cpu_to_le16( |
1997 | adapter->hw_dot_11ac_mcs_support & 0xFFFF); | 1954 | adapter->hw_dot_11ac_mcs_support & 0xFFFF); |
@@ -2235,6 +2192,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2235 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | 2192 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; |
2236 | dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; | 2193 | dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; |
2237 | dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; | 2194 | dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; |
2195 | dev->ethtool_ops = &mwifiex_ethtool_ops; | ||
2238 | 2196 | ||
2239 | mdev_priv = netdev_priv(dev); | 2197 | mdev_priv = netdev_priv(dev); |
2240 | *((unsigned long *) mdev_priv) = (unsigned long) priv; | 2198 | *((unsigned long *) mdev_priv) = (unsigned long) priv; |
@@ -2293,6 +2251,152 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2293 | } | 2251 | } |
2294 | EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); | 2252 | EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); |
2295 | 2253 | ||
2254 | #ifdef CONFIG_PM | ||
2255 | static bool | ||
2256 | mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat, | ||
2257 | s8 *byte_seq) | ||
2258 | { | ||
2259 | int j, k, valid_byte_cnt = 0; | ||
2260 | bool dont_care_byte = false; | ||
2261 | |||
2262 | for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) { | ||
2263 | for (k = 0; k < 8; k++) { | ||
2264 | if (pat->mask[j] & 1 << k) { | ||
2265 | memcpy(byte_seq + valid_byte_cnt, | ||
2266 | &pat->pattern[j * 8 + k], 1); | ||
2267 | valid_byte_cnt++; | ||
2268 | if (dont_care_byte) | ||
2269 | return false; | ||
2270 | } else { | ||
2271 | if (valid_byte_cnt) | ||
2272 | dont_care_byte = true; | ||
2273 | } | ||
2274 | |||
2275 | if (valid_byte_cnt > MAX_BYTESEQ) | ||
2276 | return false; | ||
2277 | } | ||
2278 | } | ||
2279 | |||
2280 | byte_seq[MAX_BYTESEQ] = valid_byte_cnt; | ||
2281 | |||
2282 | return true; | ||
2283 | } | ||
2284 | |||
2285 | static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, | ||
2286 | struct cfg80211_wowlan *wowlan) | ||
2287 | { | ||
2288 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | ||
2289 | struct mwifiex_ds_mef_cfg mef_cfg; | ||
2290 | struct mwifiex_mef_entry *mef_entry; | ||
2291 | int i, filt_num = 0, ret; | ||
2292 | bool first_pat = true; | ||
2293 | u8 byte_seq[MAX_BYTESEQ + 1]; | ||
2294 | const u8 ipv4_mc_mac[] = {0x33, 0x33}; | ||
2295 | const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; | ||
2296 | struct mwifiex_private *priv = | ||
2297 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | ||
2298 | |||
2299 | if (!wowlan) { | ||
2300 | dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n"); | ||
2301 | return 0; | ||
2302 | } | ||
2303 | |||
2304 | if (!priv->media_connected) { | ||
2305 | dev_warn(adapter->dev, | ||
2306 | "Can not configure WOWLAN in disconnected state\n"); | ||
2307 | return 0; | ||
2308 | } | ||
2309 | |||
2310 | mef_entry = kzalloc(sizeof(*mef_entry), GFP_KERNEL); | ||
2311 | if (!mef_entry) | ||
2312 | return -ENOMEM; | ||
2313 | |||
2314 | memset(&mef_cfg, 0, sizeof(mef_cfg)); | ||
2315 | mef_cfg.num_entries = 1; | ||
2316 | mef_cfg.mef_entry = mef_entry; | ||
2317 | mef_entry->mode = MEF_MODE_HOST_SLEEP; | ||
2318 | mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST; | ||
2319 | |||
2320 | for (i = 0; i < wowlan->n_patterns; i++) { | ||
2321 | memset(byte_seq, 0, sizeof(byte_seq)); | ||
2322 | if (!mwifiex_is_pattern_supported(&wowlan->patterns[i], | ||
2323 | byte_seq)) { | ||
2324 | wiphy_err(wiphy, "Pattern not supported\n"); | ||
2325 | kfree(mef_entry); | ||
2326 | return -EOPNOTSUPP; | ||
2327 | } | ||
2328 | |||
2329 | if (!wowlan->patterns[i].pkt_offset) { | ||
2330 | if (!(byte_seq[0] & 0x01) && | ||
2331 | (byte_seq[MAX_BYTESEQ] == 1)) { | ||
2332 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | ||
2333 | continue; | ||
2334 | } else if (is_broadcast_ether_addr(byte_seq)) { | ||
2335 | mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST; | ||
2336 | continue; | ||
2337 | } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && | ||
2338 | (byte_seq[MAX_BYTESEQ] == 2)) || | ||
2339 | (!memcmp(byte_seq, ipv6_mc_mac, 3) && | ||
2340 | (byte_seq[MAX_BYTESEQ] == 3))) { | ||
2341 | mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST; | ||
2342 | continue; | ||
2343 | } | ||
2344 | } | ||
2345 | |||
2346 | mef_entry->filter[filt_num].repeat = 1; | ||
2347 | mef_entry->filter[filt_num].offset = | ||
2348 | wowlan->patterns[i].pkt_offset; | ||
2349 | memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq, | ||
2350 | sizeof(byte_seq)); | ||
2351 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2352 | |||
2353 | if (first_pat) | ||
2354 | first_pat = false; | ||
2355 | else | ||
2356 | mef_entry->filter[filt_num].filt_action = TYPE_AND; | ||
2357 | |||
2358 | filt_num++; | ||
2359 | } | ||
2360 | |||
2361 | if (wowlan->magic_pkt) { | ||
2362 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | ||
2363 | mef_entry->filter[filt_num].repeat = 16; | ||
2364 | memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, | ||
2365 | ETH_ALEN); | ||
2366 | mef_entry->filter[filt_num].byte_seq[MAX_BYTESEQ] = ETH_ALEN; | ||
2367 | mef_entry->filter[filt_num].offset = 14; | ||
2368 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2369 | if (filt_num) | ||
2370 | mef_entry->filter[filt_num].filt_action = TYPE_OR; | ||
2371 | } | ||
2372 | |||
2373 | if (!mef_cfg.criteria) | ||
2374 | mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | | ||
2375 | MWIFIEX_CRITERIA_UNICAST | | ||
2376 | MWIFIEX_CRITERIA_MULTICAST; | ||
2377 | |||
2378 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MEF_CFG, | ||
2379 | HostCmd_ACT_GEN_SET, 0, | ||
2380 | &mef_cfg); | ||
2381 | |||
2382 | kfree(mef_entry); | ||
2383 | return ret; | ||
2384 | } | ||
2385 | |||
2386 | static int mwifiex_cfg80211_resume(struct wiphy *wiphy) | ||
2387 | { | ||
2388 | return 0; | ||
2389 | } | ||
2390 | |||
2391 | static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy, | ||
2392 | bool enabled) | ||
2393 | { | ||
2394 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | ||
2395 | |||
2396 | device_set_wakeup_enable(adapter->dev, enabled); | ||
2397 | } | ||
2398 | #endif | ||
2399 | |||
2296 | /* station cfg80211 operations */ | 2400 | /* station cfg80211 operations */ |
2297 | static struct cfg80211_ops mwifiex_cfg80211_ops = { | 2401 | static struct cfg80211_ops mwifiex_cfg80211_ops = { |
2298 | .add_virtual_intf = mwifiex_add_virtual_intf, | 2402 | .add_virtual_intf = mwifiex_add_virtual_intf, |
@@ -2321,6 +2425,11 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
2321 | .change_beacon = mwifiex_cfg80211_change_beacon, | 2425 | .change_beacon = mwifiex_cfg80211_change_beacon, |
2322 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, | 2426 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, |
2323 | .set_antenna = mwifiex_cfg80211_set_antenna, | 2427 | .set_antenna = mwifiex_cfg80211_set_antenna, |
2428 | #ifdef CONFIG_PM | ||
2429 | .suspend = mwifiex_cfg80211_suspend, | ||
2430 | .resume = mwifiex_cfg80211_resume, | ||
2431 | .set_wakeup = mwifiex_cfg80211_set_wakeup, | ||
2432 | #endif | ||
2324 | }; | 2433 | }; |
2325 | 2434 | ||
2326 | /* | 2435 | /* |
@@ -2379,6 +2488,14 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2379 | 2488 | ||
2380 | wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); | 2489 | wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); |
2381 | 2490 | ||
2491 | #ifdef CONFIG_PM | ||
2492 | wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; | ||
2493 | wiphy->wowlan.n_patterns = MWIFIEX_MAX_FILTERS; | ||
2494 | wiphy->wowlan.pattern_min_len = 1; | ||
2495 | wiphy->wowlan.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN; | ||
2496 | wiphy->wowlan.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN; | ||
2497 | #endif | ||
2498 | |||
2382 | wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | 2499 | wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | |
2383 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | 2500 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | |
2384 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | 2501 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 20a6c5555873..da469c336aa1 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -153,7 +153,21 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
153 | " or cmd size is 0, not sending\n"); | 153 | " or cmd size is 0, not sending\n"); |
154 | if (cmd_node->wait_q_enabled) | 154 | if (cmd_node->wait_q_enabled) |
155 | adapter->cmd_wait_q.status = -1; | 155 | adapter->cmd_wait_q.status = -1; |
156 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 156 | mwifiex_recycle_cmd_node(adapter, cmd_node); |
157 | return -1; | ||
158 | } | ||
159 | |||
160 | cmd_code = le16_to_cpu(host_cmd->command); | ||
161 | cmd_size = le16_to_cpu(host_cmd->size); | ||
162 | |||
163 | if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET && | ||
164 | cmd_code != HostCmd_CMD_FUNC_SHUTDOWN && | ||
165 | cmd_code != HostCmd_CMD_FUNC_INIT) { | ||
166 | dev_err(adapter->dev, | ||
167 | "DNLD_CMD: FW in reset state, ignore cmd %#x\n", | ||
168 | cmd_code); | ||
169 | mwifiex_complete_cmd(adapter, cmd_node); | ||
170 | mwifiex_recycle_cmd_node(adapter, cmd_node); | ||
157 | return -1; | 171 | return -1; |
158 | } | 172 | } |
159 | 173 | ||
@@ -168,9 +182,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
168 | adapter->curr_cmd = cmd_node; | 182 | adapter->curr_cmd = cmd_node; |
169 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 183 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
170 | 184 | ||
171 | cmd_code = le16_to_cpu(host_cmd->command); | ||
172 | cmd_size = le16_to_cpu(host_cmd->size); | ||
173 | |||
174 | /* Adjust skb length */ | 185 | /* Adjust skb length */ |
175 | if (cmd_node->cmd_skb->len > cmd_size) | 186 | if (cmd_node->cmd_skb->len > cmd_size) |
176 | /* | 187 | /* |
@@ -217,7 +228,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
217 | adapter->cmd_sent = false; | 228 | adapter->cmd_sent = false; |
218 | if (cmd_node->wait_q_enabled) | 229 | if (cmd_node->wait_q_enabled) |
219 | adapter->cmd_wait_q.status = -1; | 230 | adapter->cmd_wait_q.status = -1; |
220 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | 231 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
221 | 232 | ||
222 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 233 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
223 | adapter->curr_cmd = NULL; | 234 | adapter->curr_cmd = NULL; |
@@ -484,8 +495,6 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, | |||
484 | 495 | ||
485 | ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, | 496 | ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, |
486 | data_buf); | 497 | data_buf); |
487 | if (!ret) | ||
488 | ret = mwifiex_wait_queue_complete(adapter); | ||
489 | 498 | ||
490 | return ret; | 499 | return ret; |
491 | } | 500 | } |
@@ -588,9 +597,10 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | |||
588 | if (cmd_no == HostCmd_CMD_802_11_SCAN) { | 597 | if (cmd_no == HostCmd_CMD_802_11_SCAN) { |
589 | mwifiex_queue_scan_cmd(priv, cmd_node); | 598 | mwifiex_queue_scan_cmd(priv, cmd_node); |
590 | } else { | 599 | } else { |
591 | adapter->cmd_queued = cmd_node; | ||
592 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); | 600 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); |
593 | queue_work(adapter->workqueue, &adapter->main_work); | 601 | queue_work(adapter->workqueue, &adapter->main_work); |
602 | if (cmd_node->wait_q_enabled) | ||
603 | ret = mwifiex_wait_queue_complete(adapter, cmd_node); | ||
594 | } | 604 | } |
595 | 605 | ||
596 | return ret; | 606 | return ret; |
@@ -622,6 +632,20 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, | |||
622 | spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); | 632 | spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); |
623 | } | 633 | } |
624 | 634 | ||
635 | /* This function reuses a command node. */ | ||
636 | void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, | ||
637 | struct cmd_ctrl_node *cmd_node) | ||
638 | { | ||
639 | struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data; | ||
640 | |||
641 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | ||
642 | |||
643 | atomic_dec(&adapter->cmd_pending); | ||
644 | dev_dbg(adapter->dev, "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n", | ||
645 | le16_to_cpu(host_cmd->command), | ||
646 | atomic_read(&adapter->cmd_pending)); | ||
647 | } | ||
648 | |||
625 | /* | 649 | /* |
626 | * This function queues a command to the command pending queue. | 650 | * This function queues a command to the command pending queue. |
627 | * | 651 | * |
@@ -663,7 +687,9 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, | |||
663 | list_add(&cmd_node->list, &adapter->cmd_pending_q); | 687 | list_add(&cmd_node->list, &adapter->cmd_pending_q); |
664 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); | 688 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); |
665 | 689 | ||
666 | dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x is queued\n", command); | 690 | atomic_inc(&adapter->cmd_pending); |
691 | dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n", | ||
692 | command, atomic_read(&adapter->cmd_pending)); | ||
667 | } | 693 | } |
668 | 694 | ||
669 | /* | 695 | /* |
@@ -773,7 +799,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
773 | if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { | 799 | if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { |
774 | dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n", | 800 | dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n", |
775 | le16_to_cpu(resp->command)); | 801 | le16_to_cpu(resp->command)); |
776 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | 802 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
777 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 803 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
778 | adapter->curr_cmd = NULL; | 804 | adapter->curr_cmd = NULL; |
779 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 805 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
@@ -823,7 +849,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
823 | if (adapter->curr_cmd->wait_q_enabled) | 849 | if (adapter->curr_cmd->wait_q_enabled) |
824 | adapter->cmd_wait_q.status = -1; | 850 | adapter->cmd_wait_q.status = -1; |
825 | 851 | ||
826 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | 852 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
827 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 853 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
828 | adapter->curr_cmd = NULL; | 854 | adapter->curr_cmd = NULL; |
829 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 855 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
@@ -855,8 +881,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
855 | if (adapter->curr_cmd->wait_q_enabled) | 881 | if (adapter->curr_cmd->wait_q_enabled) |
856 | adapter->cmd_wait_q.status = ret; | 882 | adapter->cmd_wait_q.status = ret; |
857 | 883 | ||
858 | /* Clean up and put current command back to cmd_free_q */ | 884 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
859 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | ||
860 | 885 | ||
861 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 886 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
862 | adapter->curr_cmd = NULL; | 887 | adapter->curr_cmd = NULL; |
@@ -983,7 +1008,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) | |||
983 | mwifiex_complete_cmd(adapter, cmd_node); | 1008 | mwifiex_complete_cmd(adapter, cmd_node); |
984 | cmd_node->wait_q_enabled = false; | 1009 | cmd_node->wait_q_enabled = false; |
985 | } | 1010 | } |
986 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 1011 | mwifiex_recycle_cmd_node(adapter, cmd_node); |
987 | spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); | 1012 | spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); |
988 | } | 1013 | } |
989 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); | 1014 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); |
@@ -1030,7 +1055,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
1030 | cmd_node = adapter->curr_cmd; | 1055 | cmd_node = adapter->curr_cmd; |
1031 | cmd_node->wait_q_enabled = false; | 1056 | cmd_node->wait_q_enabled = false; |
1032 | cmd_node->cmd_flag |= CMD_F_CANCELED; | 1057 | cmd_node->cmd_flag |= CMD_F_CANCELED; |
1033 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 1058 | mwifiex_recycle_cmd_node(adapter, cmd_node); |
1034 | mwifiex_complete_cmd(adapter, adapter->curr_cmd); | 1059 | mwifiex_complete_cmd(adapter, adapter->curr_cmd); |
1035 | adapter->curr_cmd = NULL; | 1060 | adapter->curr_cmd = NULL; |
1036 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); | 1061 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); |
@@ -1139,7 +1164,7 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, | |||
1139 | phs_cfg->params.hs_config.gpio, | 1164 | phs_cfg->params.hs_config.gpio, |
1140 | phs_cfg->params.hs_config.gap); | 1165 | phs_cfg->params.hs_config.gap); |
1141 | } | 1166 | } |
1142 | if (conditions != HOST_SLEEP_CFG_CANCEL) { | 1167 | if (conditions != HS_CFG_CANCEL) { |
1143 | adapter->is_hs_configured = true; | 1168 | adapter->is_hs_configured = true; |
1144 | if (adapter->iface_type == MWIFIEX_USB || | 1169 | if (adapter->iface_type == MWIFIEX_USB || |
1145 | adapter->iface_type == MWIFIEX_PCIE) | 1170 | adapter->iface_type == MWIFIEX_PCIE) |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index e8a569aaa2e8..94cc09d48444 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -41,8 +41,15 @@ | |||
41 | #define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2 | 41 | #define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2 |
42 | #define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16 | 42 | #define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16 |
43 | 43 | ||
44 | #define MWIFIEX_AMPDU_DEF_TXWINSIZE 32 | 44 | #define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE 16 |
45 | #define MWIFIEX_AMPDU_DEF_RXWINSIZE 16 | 45 | #define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE 32 |
46 | #define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE 32 | ||
47 | #define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE 16 | ||
48 | #define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE 32 | ||
49 | #define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE 48 | ||
50 | #define MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE 48 | ||
51 | #define MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE 32 | ||
52 | |||
46 | #define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff | 53 | #define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff |
47 | 54 | ||
48 | #define MWIFIEX_RATE_BITMAP_MCS0 32 | 55 | #define MWIFIEX_RATE_BITMAP_MCS0 32 |
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..1f7578d553ec 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 |
@@ -322,6 +295,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
322 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa | 295 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa |
323 | #define HostCmd_CMD_MGMT_FRAME_REG 0x010c | 296 | #define HostCmd_CMD_MGMT_FRAME_REG 0x010c |
324 | #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d | 297 | #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d |
298 | #define HostCmd_CMD_11AC_CFG 0x0112 | ||
325 | 299 | ||
326 | #define PROTOCOL_NO_SECURITY 0x01 | 300 | #define PROTOCOL_NO_SECURITY 0x01 |
327 | #define PROTOCOL_STATIC_WEP 0x02 | 301 | #define PROTOCOL_STATIC_WEP 0x02 |
@@ -376,10 +350,14 @@ enum P2P_MODES { | |||
376 | #define HostCmd_SCAN_RADIO_TYPE_BG 0 | 350 | #define HostCmd_SCAN_RADIO_TYPE_BG 0 |
377 | #define HostCmd_SCAN_RADIO_TYPE_A 1 | 351 | #define HostCmd_SCAN_RADIO_TYPE_A 1 |
378 | 352 | ||
379 | #define HOST_SLEEP_CFG_CANCEL 0xffffffff | 353 | #define HS_CFG_CANCEL 0xffffffff |
380 | #define HOST_SLEEP_CFG_COND_DEF 0x00000000 | 354 | #define HS_CFG_COND_DEF 0x00000000 |
381 | #define HOST_SLEEP_CFG_GPIO_DEF 0xff | 355 | #define HS_CFG_GPIO_DEF 0xff |
382 | #define HOST_SLEEP_CFG_GAP_DEF 0 | 356 | #define HS_CFG_GAP_DEF 0 |
357 | #define HS_CFG_COND_BROADCAST_DATA 0x00000001 | ||
358 | #define HS_CFG_COND_UNICAST_DATA 0x00000002 | ||
359 | #define HS_CFG_COND_MAC_EVENT 0x00000004 | ||
360 | #define HS_CFG_COND_MULTICAST_DATA 0x00000008 | ||
383 | 361 | ||
384 | #define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc | 362 | #define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc |
385 | #define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2 | 363 | #define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2 |
@@ -469,6 +447,23 @@ enum P2P_MODES { | |||
469 | #define EVENT_GET_BSS_TYPE(event_cause) \ | 447 | #define EVENT_GET_BSS_TYPE(event_cause) \ |
470 | (((event_cause) >> 24) & 0x00ff) | 448 | (((event_cause) >> 24) & 0x00ff) |
471 | 449 | ||
450 | #define MWIFIEX_MAX_PATTERN_LEN 20 | ||
451 | #define MWIFIEX_MAX_OFFSET_LEN 50 | ||
452 | #define STACK_NBYTES 100 | ||
453 | #define TYPE_DNUM 1 | ||
454 | #define TYPE_BYTESEQ 2 | ||
455 | #define MAX_OPERAND 0x40 | ||
456 | #define TYPE_EQ (MAX_OPERAND+1) | ||
457 | #define TYPE_EQ_DNUM (MAX_OPERAND+2) | ||
458 | #define TYPE_EQ_BIT (MAX_OPERAND+3) | ||
459 | #define TYPE_AND (MAX_OPERAND+4) | ||
460 | #define TYPE_OR (MAX_OPERAND+5) | ||
461 | #define MEF_MODE_HOST_SLEEP 1 | ||
462 | #define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 | ||
463 | #define MWIFIEX_CRITERIA_BROADCAST BIT(0) | ||
464 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) | ||
465 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) | ||
466 | |||
472 | struct mwifiex_ie_types_header { | 467 | struct mwifiex_ie_types_header { |
473 | __le16 type; | 468 | __le16 type; |
474 | __le16 len; | 469 | __le16 len; |
@@ -1369,6 +1364,15 @@ struct host_cmd_ds_sys_config { | |||
1369 | u8 tlv[0]; | 1364 | u8 tlv[0]; |
1370 | }; | 1365 | }; |
1371 | 1366 | ||
1367 | struct host_cmd_11ac_vht_cfg { | ||
1368 | __le16 action; | ||
1369 | u8 band_config; | ||
1370 | u8 misc_config; | ||
1371 | __le32 cap_info; | ||
1372 | __le32 mcs_tx_set; | ||
1373 | __le32 mcs_rx_set; | ||
1374 | } __packed; | ||
1375 | |||
1372 | struct host_cmd_tlv_akmp { | 1376 | struct host_cmd_tlv_akmp { |
1373 | struct host_cmd_tlv tlv; | 1377 | struct host_cmd_tlv tlv; |
1374 | __le16 key_mgmt; | 1378 | __le16 key_mgmt; |
@@ -1499,6 +1503,19 @@ struct host_cmd_ds_802_11_ibss_status { | |||
1499 | __le16 use_g_rate_protect; | 1503 | __le16 use_g_rate_protect; |
1500 | } __packed; | 1504 | } __packed; |
1501 | 1505 | ||
1506 | struct mwifiex_fw_mef_entry { | ||
1507 | u8 mode; | ||
1508 | u8 action; | ||
1509 | __le16 exprsize; | ||
1510 | u8 expr[0]; | ||
1511 | } __packed; | ||
1512 | |||
1513 | struct host_cmd_ds_mef_cfg { | ||
1514 | __le32 criteria; | ||
1515 | __le16 num_entries; | ||
1516 | struct mwifiex_fw_mef_entry mef_entry[0]; | ||
1517 | } __packed; | ||
1518 | |||
1502 | #define CONNECTION_TYPE_INFRA 0 | 1519 | #define CONNECTION_TYPE_INFRA 0 |
1503 | #define CONNECTION_TYPE_ADHOC 1 | 1520 | #define CONNECTION_TYPE_ADHOC 1 |
1504 | #define CONNECTION_TYPE_AP 2 | 1521 | #define CONNECTION_TYPE_AP 2 |
@@ -1603,6 +1620,7 @@ struct host_cmd_ds_command { | |||
1603 | struct host_cmd_ds_remain_on_chan roc_cfg; | 1620 | struct host_cmd_ds_remain_on_chan roc_cfg; |
1604 | struct host_cmd_ds_p2p_mode_cfg mode_cfg; | 1621 | struct host_cmd_ds_p2p_mode_cfg mode_cfg; |
1605 | struct host_cmd_ds_802_11_ibss_status ibss_coalescing; | 1622 | struct host_cmd_ds_802_11_ibss_status ibss_coalescing; |
1623 | struct host_cmd_ds_mef_cfg mef_cfg; | ||
1606 | struct host_cmd_ds_mac_reg_access mac_reg; | 1624 | struct host_cmd_ds_mac_reg_access mac_reg; |
1607 | struct host_cmd_ds_bbp_reg_access bbp_reg; | 1625 | struct host_cmd_ds_bbp_reg_access bbp_reg; |
1608 | struct host_cmd_ds_rf_reg_access rf_reg; | 1626 | struct host_cmd_ds_rf_reg_access rf_reg; |
@@ -1612,6 +1630,7 @@ struct host_cmd_ds_command { | |||
1612 | struct host_cmd_ds_802_11_eeprom_access eeprom; | 1630 | struct host_cmd_ds_802_11_eeprom_access eeprom; |
1613 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; | 1631 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; |
1614 | struct host_cmd_ds_sys_config uap_sys_config; | 1632 | struct host_cmd_ds_sys_config uap_sys_config; |
1633 | struct host_cmd_11ac_vht_cfg vht_cfg; | ||
1615 | } params; | 1634 | } params; |
1616 | } __packed; | 1635 | } __packed; |
1617 | 1636 | ||
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index e38aa9b3663d..42d7f0adf9bd 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)); |
@@ -533,10 +533,8 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
533 | if (!adapter->priv[i]) | 533 | if (!adapter->priv[i]) |
534 | continue; | 534 | continue; |
535 | priv = adapter->priv[i]; | 535 | priv = adapter->priv[i]; |
536 | for (j = 0; j < MAX_NUM_TID; ++j) { | 536 | for (j = 0; j < MAX_NUM_TID; ++j) |
537 | INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); | 537 | INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); |
538 | spin_lock_init(&priv->wmm.tid_tbl_ptr[j].tid_tbl_lock); | ||
539 | } | ||
540 | INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); | 538 | INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); |
541 | INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); | 539 | INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); |
542 | INIT_LIST_HEAD(&priv->sta_list); | 540 | INIT_LIST_HEAD(&priv->sta_list); |
@@ -709,6 +707,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
709 | return ret; | 707 | return ret; |
710 | } | 708 | } |
711 | 709 | ||
710 | /* cancel current command */ | ||
711 | if (adapter->curr_cmd) { | ||
712 | dev_warn(adapter->dev, "curr_cmd is still in processing\n"); | ||
713 | del_timer(&adapter->cmd_timer); | ||
714 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); | ||
715 | adapter->curr_cmd = NULL; | ||
716 | } | ||
717 | |||
712 | /* shut down mwifiex */ | 718 | /* shut down mwifiex */ |
713 | dev_dbg(adapter->dev, "info: shutdown mwifiex...\n"); | 719 | dev_dbg(adapter->dev, "info: shutdown mwifiex...\n"); |
714 | 720 | ||
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index d85e6eb1f58a..7f27e45680b5 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -272,6 +272,14 @@ struct mwifiex_ds_pm_cfg { | |||
272 | } param; | 272 | } param; |
273 | }; | 273 | }; |
274 | 274 | ||
275 | struct mwifiex_11ac_vht_cfg { | ||
276 | u8 band_config; | ||
277 | u8 misc_config; | ||
278 | u32 cap_info; | ||
279 | u32 mcs_tx_set; | ||
280 | u32 mcs_rx_set; | ||
281 | }; | ||
282 | |||
275 | struct mwifiex_ds_11n_tx_cfg { | 283 | struct mwifiex_ds_11n_tx_cfg { |
276 | u16 tx_htcap; | 284 | u16 tx_htcap; |
277 | u16 tx_htinfo; | 285 | u16 tx_htinfo; |
@@ -354,6 +362,29 @@ struct mwifiex_ds_misc_subsc_evt { | |||
354 | struct subsc_evt_cfg bcn_h_rssi_cfg; | 362 | struct subsc_evt_cfg bcn_h_rssi_cfg; |
355 | }; | 363 | }; |
356 | 364 | ||
365 | #define MAX_BYTESEQ 6 /* non-adjustable */ | ||
366 | #define MWIFIEX_MAX_FILTERS 10 | ||
367 | |||
368 | struct mwifiex_mef_filter { | ||
369 | u16 repeat; | ||
370 | u16 offset; | ||
371 | s8 byte_seq[MAX_BYTESEQ + 1]; | ||
372 | u8 filt_type; | ||
373 | u8 filt_action; | ||
374 | }; | ||
375 | |||
376 | struct mwifiex_mef_entry { | ||
377 | u8 mode; | ||
378 | u8 action; | ||
379 | struct mwifiex_mef_filter filter[MWIFIEX_MAX_FILTERS]; | ||
380 | }; | ||
381 | |||
382 | struct mwifiex_ds_mef_cfg { | ||
383 | u32 criteria; | ||
384 | u16 num_entries; | ||
385 | struct mwifiex_mef_entry *mef_entry; | ||
386 | }; | ||
387 | |||
357 | #define MWIFIEX_MAX_VSIE_LEN (256) | 388 | #define MWIFIEX_MAX_VSIE_LEN (256) |
358 | #define MWIFIEX_MAX_VSIE_NUM (8) | 389 | #define MWIFIEX_MAX_VSIE_NUM (8) |
359 | #define MWIFIEX_VSIE_MASK_CLEAR 0x00 | 390 | #define MWIFIEX_VSIE_MASK_CLEAR 0x00 |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 246aa62a4817..6bcb66e6e97c 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 */ |
@@ -1296,6 +1295,14 @@ int mwifiex_associate(struct mwifiex_private *priv, | |||
1296 | (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) | 1295 | (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) |
1297 | return -1; | 1296 | return -1; |
1298 | 1297 | ||
1298 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | ||
1299 | !bss_desc->disable_11n && !bss_desc->disable_11ac && | ||
1300 | (priv->adapter->config_bands & BAND_GAC || | ||
1301 | priv->adapter->config_bands & BAND_AAC)) | ||
1302 | mwifiex_set_11ac_ba_params(priv); | ||
1303 | else | ||
1304 | mwifiex_set_ba_params(priv); | ||
1305 | |||
1299 | memcpy(¤t_bssid, | 1306 | memcpy(¤t_bssid, |
1300 | &priv->curr_bss_params.bss_descriptor.mac_address, | 1307 | &priv->curr_bss_params.bss_descriptor.mac_address, |
1301 | sizeof(current_bssid)); | 1308 | sizeof(current_bssid)); |
@@ -1324,6 +1331,13 @@ mwifiex_adhoc_start(struct mwifiex_private *priv, | |||
1324 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", | 1331 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", |
1325 | priv->curr_bss_params.band); | 1332 | priv->curr_bss_params.band); |
1326 | 1333 | ||
1334 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | ||
1335 | (priv->adapter->config_bands & BAND_GAC || | ||
1336 | priv->adapter->config_bands & BAND_AAC)) | ||
1337 | mwifiex_set_11ac_ba_params(priv); | ||
1338 | else | ||
1339 | mwifiex_set_ba_params(priv); | ||
1340 | |||
1327 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, | 1341 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, |
1328 | HostCmd_ACT_GEN_SET, 0, adhoc_ssid); | 1342 | HostCmd_ACT_GEN_SET, 0, adhoc_ssid); |
1329 | } | 1343 | } |
@@ -1357,6 +1371,14 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv, | |||
1357 | return -1; | 1371 | return -1; |
1358 | } | 1372 | } |
1359 | 1373 | ||
1374 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | ||
1375 | !bss_desc->disable_11n && !bss_desc->disable_11ac && | ||
1376 | (priv->adapter->config_bands & BAND_GAC || | ||
1377 | priv->adapter->config_bands & BAND_AAC)) | ||
1378 | mwifiex_set_11ac_ba_params(priv); | ||
1379 | else | ||
1380 | mwifiex_set_ba_params(priv); | ||
1381 | |||
1360 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", | 1382 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", |
1361 | priv->curr_bss_params.bss_descriptor.channel); | 1383 | priv->curr_bss_params.bss_descriptor.channel); |
1362 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", | 1384 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", |
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..b7484efc9443 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; |
@@ -210,15 +213,12 @@ struct mwifiex_ra_list_tbl { | |||
210 | 213 | ||
211 | struct mwifiex_tid_tbl { | 214 | struct mwifiex_tid_tbl { |
212 | struct list_head ra_list; | 215 | struct list_head ra_list; |
213 | /* spin lock for tid table */ | ||
214 | spinlock_t tid_tbl_lock; | ||
215 | struct mwifiex_ra_list_tbl *ra_list_curr; | 216 | struct mwifiex_ra_list_tbl *ra_list_curr; |
216 | }; | 217 | }; |
217 | 218 | ||
218 | #define WMM_HIGHEST_PRIORITY 7 | 219 | #define WMM_HIGHEST_PRIORITY 7 |
219 | #define HIGH_PRIO_TID 7 | 220 | #define HIGH_PRIO_TID 7 |
220 | #define LOW_PRIO_TID 0 | 221 | #define LOW_PRIO_TID 0 |
221 | #define NO_PKT_PRIO_TID (-1) | ||
222 | 222 | ||
223 | struct mwifiex_wmm_desc { | 223 | struct mwifiex_wmm_desc { |
224 | struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; | 224 | struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; |
@@ -394,6 +394,8 @@ struct mwifiex_private { | |||
394 | u8 curr_addr[ETH_ALEN]; | 394 | u8 curr_addr[ETH_ALEN]; |
395 | u8 media_connected; | 395 | u8 media_connected; |
396 | u32 num_tx_timeout; | 396 | u32 num_tx_timeout; |
397 | /* track consecutive timeout */ | ||
398 | u8 tx_timeout_cnt; | ||
397 | struct net_device *netdev; | 399 | struct net_device *netdev; |
398 | struct net_device_stats stats; | 400 | struct net_device_stats stats; |
399 | u16 curr_pkt_filter; | 401 | u16 curr_pkt_filter; |
@@ -723,7 +725,6 @@ struct mwifiex_adapter { | |||
723 | u16 cmd_wait_q_required; | 725 | u16 cmd_wait_q_required; |
724 | struct mwifiex_wait_queue cmd_wait_q; | 726 | struct mwifiex_wait_queue cmd_wait_q; |
725 | u8 scan_wait_q_woken; | 727 | u8 scan_wait_q_woken; |
726 | struct cmd_ctrl_node *cmd_queued; | ||
727 | spinlock_t queue_lock; /* lock for tx queues */ | 728 | spinlock_t queue_lock; /* lock for tx queues */ |
728 | struct completion fw_load; | 729 | struct completion fw_load; |
729 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | 730 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; |
@@ -794,6 +795,8 @@ void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); | |||
794 | 795 | ||
795 | void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, | 796 | void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, |
796 | struct cmd_ctrl_node *cmd_node); | 797 | struct cmd_ctrl_node *cmd_node); |
798 | void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, | ||
799 | struct cmd_ctrl_node *cmd_node); | ||
797 | 800 | ||
798 | void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, | 801 | void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, |
799 | struct cmd_ctrl_node *cmd_node, | 802 | struct cmd_ctrl_node *cmd_node, |
@@ -908,12 +911,20 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv, | |||
908 | void mwifiex_set_ht_params(struct mwifiex_private *priv, | 911 | void mwifiex_set_ht_params(struct mwifiex_private *priv, |
909 | struct mwifiex_uap_bss_param *bss_cfg, | 912 | struct mwifiex_uap_bss_param *bss_cfg, |
910 | struct cfg80211_ap_settings *params); | 913 | struct cfg80211_ap_settings *params); |
914 | void mwifiex_set_vht_params(struct mwifiex_private *priv, | ||
915 | struct mwifiex_uap_bss_param *bss_cfg, | ||
916 | struct cfg80211_ap_settings *params); | ||
911 | void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, | 917 | void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, |
912 | struct cfg80211_ap_settings *params); | 918 | struct cfg80211_ap_settings *params); |
919 | void mwifiex_set_vht_width(struct mwifiex_private *priv, | ||
920 | enum nl80211_chan_width width, | ||
921 | bool ap_11ac_disable); | ||
913 | void | 922 | void |
914 | mwifiex_set_wmm_params(struct mwifiex_private *priv, | 923 | mwifiex_set_wmm_params(struct mwifiex_private *priv, |
915 | struct mwifiex_uap_bss_param *bss_cfg, | 924 | struct mwifiex_uap_bss_param *bss_cfg, |
916 | struct cfg80211_ap_settings *params); | 925 | struct cfg80211_ap_settings *params); |
926 | void mwifiex_set_ba_params(struct mwifiex_private *priv); | ||
927 | void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); | ||
917 | 928 | ||
918 | /* | 929 | /* |
919 | * This function checks if the queuing is RA based or not. | 930 | * This function checks if the queuing is RA based or not. |
@@ -1018,7 +1029,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
1018 | struct mwifiex_multicast_list *mcast_list); | 1029 | struct mwifiex_multicast_list *mcast_list); |
1019 | int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, | 1030 | int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, |
1020 | struct net_device *dev); | 1031 | struct net_device *dev); |
1021 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter); | 1032 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, |
1033 | struct cmd_ctrl_node *cmd_queued); | ||
1022 | int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | 1034 | int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, |
1023 | struct cfg80211_ssid *req_ssid); | 1035 | struct cfg80211_ssid *req_ssid); |
1024 | int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); | 1036 | int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); |
@@ -1098,11 +1110,15 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev); | |||
1098 | 1110 | ||
1099 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); | 1111 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); |
1100 | 1112 | ||
1113 | int mwifiex_add_wowlan_magic_pkt_filter(struct mwifiex_adapter *adapter); | ||
1114 | |||
1101 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | 1115 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, |
1102 | struct cfg80211_beacon_data *data); | 1116 | struct cfg80211_beacon_data *data); |
1103 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); | 1117 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); |
1104 | u8 *mwifiex_11d_code_2_region(u8 code); | 1118 | u8 *mwifiex_11d_code_2_region(u8 code); |
1105 | 1119 | ||
1120 | extern const struct ethtool_ops mwifiex_ethtool_ops; | ||
1121 | |||
1106 | #ifdef CONFIG_DEBUG_FS | 1122 | #ifdef CONFIG_DEBUG_FS |
1107 | void mwifiex_debugfs_init(void); | 1123 | void mwifiex_debugfs_init(void); |
1108 | void mwifiex_debugfs_remove(void); | 1124 | void mwifiex_debugfs_remove(void); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 35c79722c361..856959b64bc7 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, |
@@ -287,35 +287,46 @@ static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data) | |||
287 | } | 287 | } |
288 | 288 | ||
289 | /* | 289 | /* |
290 | * This function wakes up the card. | 290 | * This function adds delay loop to ensure FW is awake before proceeding. |
291 | * | ||
292 | * A host power up command is written to the card configuration | ||
293 | * register to wake up the card. | ||
294 | */ | 291 | */ |
295 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | 292 | static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter) |
296 | { | 293 | { |
297 | int i = 0; | 294 | int i = 0; |
298 | struct pcie_service_card *card = adapter->card; | ||
299 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; | ||
300 | 295 | ||
301 | while (reg->sleep_cookie && mwifiex_pcie_ok_to_access_hw(adapter)) { | 296 | while (mwifiex_pcie_ok_to_access_hw(adapter)) { |
302 | i++; | 297 | i++; |
303 | usleep_range(10, 20); | 298 | usleep_range(10, 20); |
304 | /* 50ms max wait */ | 299 | /* 50ms max wait */ |
305 | if (i == 50000) | 300 | if (i == 5000) |
306 | break; | 301 | break; |
307 | } | 302 | } |
308 | 303 | ||
304 | return; | ||
305 | } | ||
306 | |||
307 | /* This function wakes up the card by reading fw_status register. */ | ||
308 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | ||
309 | { | ||
310 | u32 fw_status; | ||
311 | struct pcie_service_card *card = adapter->card; | ||
312 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; | ||
313 | |||
309 | dev_dbg(adapter->dev, "event: Wakeup device...\n"); | 314 | dev_dbg(adapter->dev, "event: Wakeup device...\n"); |
310 | 315 | ||
311 | /* Enable interrupts or any chip access will wakeup device */ | 316 | if (reg->sleep_cookie) |
312 | if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, HOST_INTR_MASK)) { | 317 | mwifiex_pcie_dev_wakeup_delay(adapter); |
313 | dev_warn(adapter->dev, "Enable host interrupt failed\n"); | 318 | |
319 | /* Reading fw_status register will wakeup device */ | ||
320 | if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) { | ||
321 | dev_warn(adapter->dev, "Reading fw_status register failed\n"); | ||
314 | return -1; | 322 | return -1; |
315 | } | 323 | } |
316 | 324 | ||
317 | dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n"); | 325 | if (reg->sleep_cookie) { |
318 | adapter->ps_state = PS_STATE_AWAKE; | 326 | mwifiex_pcie_dev_wakeup_delay(adapter); |
327 | dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n"); | ||
328 | adapter->ps_state = PS_STATE_AWAKE; | ||
329 | } | ||
319 | 330 | ||
320 | return 0; | 331 | return 0; |
321 | } | 332 | } |
@@ -1030,8 +1041,8 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, | |||
1030 | u32 wrindx, num_tx_buffs, rx_val; | 1041 | u32 wrindx, num_tx_buffs, rx_val; |
1031 | int ret; | 1042 | int ret; |
1032 | dma_addr_t buf_pa; | 1043 | dma_addr_t buf_pa; |
1033 | struct mwifiex_pcie_buf_desc *desc; | 1044 | struct mwifiex_pcie_buf_desc *desc = NULL; |
1034 | struct mwifiex_pfu_buf_desc *desc2; | 1045 | struct mwifiex_pfu_buf_desc *desc2 = NULL; |
1035 | __le16 *tmp; | 1046 | __le16 *tmp; |
1036 | 1047 | ||
1037 | if (!(skb->data && skb->len)) { | 1048 | if (!(skb->data && skb->len)) { |
@@ -1508,6 +1519,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | |||
1508 | } | 1519 | } |
1509 | memcpy(adapter->upld_buf, skb->data, | 1520 | memcpy(adapter->upld_buf, skb->data, |
1510 | min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len)); | 1521 | min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len)); |
1522 | skb_push(skb, INTF_HEADER_LEN); | ||
1511 | if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, | 1523 | if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, |
1512 | PCI_DMA_FROMDEVICE)) | 1524 | PCI_DMA_FROMDEVICE)) |
1513 | return -1; | 1525 | return -1; |
@@ -1983,12 +1995,13 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) | |||
1983 | } | 1995 | } |
1984 | } | 1996 | } |
1985 | } else if (!adapter->pps_uapsd_mode && | 1997 | } else if (!adapter->pps_uapsd_mode && |
1986 | adapter->ps_state == PS_STATE_SLEEP) { | 1998 | adapter->ps_state == PS_STATE_SLEEP && |
1999 | mwifiex_pcie_ok_to_access_hw(adapter)) { | ||
1987 | /* Potentially for PCIe we could get other | 2000 | /* Potentially for PCIe we could get other |
1988 | * interrupts like shared. Don't change power | 2001 | * interrupts like shared. Don't change power |
1989 | * state until cookie is set */ | 2002 | * state until cookie is set */ |
1990 | if (mwifiex_pcie_ok_to_access_hw(adapter)) | 2003 | adapter->ps_state = PS_STATE_AWAKE; |
1991 | adapter->ps_state = PS_STATE_AWAKE; | 2004 | adapter->pm_wakeup_fw_try = false; |
1992 | } | 2005 | } |
1993 | } | 2006 | } |
1994 | } | 2007 | } |
@@ -2111,7 +2124,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | |||
2111 | } | 2124 | } |
2112 | dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", | 2125 | dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", |
2113 | adapter->cmd_sent, adapter->data_sent); | 2126 | adapter->cmd_sent, adapter->data_sent); |
2114 | mwifiex_pcie_enable_host_int(adapter); | 2127 | if (adapter->ps_state != PS_STATE_SLEEP) |
2128 | mwifiex_pcie_enable_host_int(adapter); | ||
2115 | 2129 | ||
2116 | return 0; | 2130 | return 0; |
2117 | } | 2131 | } |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index bb60c2754a97..e7f6deaf715e 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1388,10 +1388,15 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, | |||
1388 | list_del(&cmd_node->list); | 1388 | list_del(&cmd_node->list); |
1389 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | 1389 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
1390 | flags); | 1390 | flags); |
1391 | adapter->cmd_queued = cmd_node; | ||
1392 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, | 1391 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, |
1393 | true); | 1392 | true); |
1394 | queue_work(adapter->workqueue, &adapter->main_work); | 1393 | queue_work(adapter->workqueue, &adapter->main_work); |
1394 | |||
1395 | /* Perform internal scan synchronously */ | ||
1396 | if (!priv->scan_request) { | ||
1397 | dev_dbg(adapter->dev, "wait internal scan\n"); | ||
1398 | mwifiex_wait_queue_complete(adapter, cmd_node); | ||
1399 | } | ||
1395 | } else { | 1400 | } else { |
1396 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | 1401 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
1397 | flags); | 1402 | flags); |
@@ -1790,7 +1795,12 @@ check_next_scan: | |||
1790 | /* Need to indicate IOCTL complete */ | 1795 | /* Need to indicate IOCTL complete */ |
1791 | if (adapter->curr_cmd->wait_q_enabled) { | 1796 | if (adapter->curr_cmd->wait_q_enabled) { |
1792 | adapter->cmd_wait_q.status = 0; | 1797 | adapter->cmd_wait_q.status = 0; |
1793 | mwifiex_complete_cmd(adapter, adapter->curr_cmd); | 1798 | if (!priv->scan_request) { |
1799 | dev_dbg(adapter->dev, | ||
1800 | "complete internal scan\n"); | ||
1801 | mwifiex_complete_cmd(adapter, | ||
1802 | adapter->curr_cmd); | ||
1803 | } | ||
1794 | } | 1804 | } |
1795 | if (priv->report_scan_result) | 1805 | if (priv->report_scan_result) |
1796 | priv->report_scan_result = false; | 1806 | priv->report_scan_result = false; |
@@ -1946,9 +1956,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv, | |||
1946 | /* Normal scan */ | 1956 | /* Normal scan */ |
1947 | ret = mwifiex_scan_networks(priv, NULL); | 1957 | ret = mwifiex_scan_networks(priv, NULL); |
1948 | 1958 | ||
1949 | if (!ret) | ||
1950 | ret = mwifiex_wait_queue_complete(priv->adapter); | ||
1951 | |||
1952 | up(&priv->async_sem); | 1959 | up(&priv->async_sem); |
1953 | 1960 | ||
1954 | return ret; | 1961 | return ret; |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index c55c5bb93134..b193e25977d2 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "main.h" | 24 | #include "main.h" |
25 | #include "wmm.h" | 25 | #include "wmm.h" |
26 | #include "11n.h" | 26 | #include "11n.h" |
27 | #include "11ac.h" | ||
27 | 28 | ||
28 | /* | 29 | /* |
29 | * This function prepares command to set/get RSSI information. | 30 | * This function prepares command to set/get RSSI information. |
@@ -334,7 +335,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, | |||
334 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); | 335 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); |
335 | 336 | ||
336 | if (!hs_activate && | 337 | if (!hs_activate && |
337 | (hscfg_param->conditions != cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) && | 338 | (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) && |
338 | ((adapter->arp_filter_size > 0) && | 339 | ((adapter->arp_filter_size > 0) && |
339 | (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { | 340 | (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { |
340 | dev_dbg(adapter->dev, | 341 | dev_dbg(adapter->dev, |
@@ -1059,6 +1060,80 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv, | |||
1059 | return 0; | 1060 | return 0; |
1060 | } | 1061 | } |
1061 | 1062 | ||
1063 | static int | ||
1064 | mwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv, | ||
1065 | struct mwifiex_mef_entry *mef_entry, | ||
1066 | u8 **buffer) | ||
1067 | { | ||
1068 | struct mwifiex_mef_filter *filter = mef_entry->filter; | ||
1069 | int i, byte_len; | ||
1070 | u8 *stack_ptr = *buffer; | ||
1071 | |||
1072 | for (i = 0; i < MWIFIEX_MAX_FILTERS; i++) { | ||
1073 | filter = &mef_entry->filter[i]; | ||
1074 | if (!filter->filt_type) | ||
1075 | break; | ||
1076 | *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->repeat); | ||
1077 | stack_ptr += 4; | ||
1078 | *stack_ptr = TYPE_DNUM; | ||
1079 | stack_ptr += 1; | ||
1080 | |||
1081 | byte_len = filter->byte_seq[MAX_BYTESEQ]; | ||
1082 | memcpy(stack_ptr, filter->byte_seq, byte_len); | ||
1083 | stack_ptr += byte_len; | ||
1084 | *stack_ptr = byte_len; | ||
1085 | stack_ptr += 1; | ||
1086 | *stack_ptr = TYPE_BYTESEQ; | ||
1087 | stack_ptr += 1; | ||
1088 | |||
1089 | *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->offset); | ||
1090 | stack_ptr += 4; | ||
1091 | *stack_ptr = TYPE_DNUM; | ||
1092 | stack_ptr += 1; | ||
1093 | |||
1094 | *stack_ptr = filter->filt_type; | ||
1095 | stack_ptr += 1; | ||
1096 | |||
1097 | if (filter->filt_action) { | ||
1098 | *stack_ptr = filter->filt_action; | ||
1099 | stack_ptr += 1; | ||
1100 | } | ||
1101 | |||
1102 | if (stack_ptr - *buffer > STACK_NBYTES) | ||
1103 | return -1; | ||
1104 | } | ||
1105 | |||
1106 | *buffer = stack_ptr; | ||
1107 | return 0; | ||
1108 | } | ||
1109 | |||
1110 | static int | ||
1111 | mwifiex_cmd_mef_cfg(struct mwifiex_private *priv, | ||
1112 | struct host_cmd_ds_command *cmd, | ||
1113 | struct mwifiex_ds_mef_cfg *mef) | ||
1114 | { | ||
1115 | struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; | ||
1116 | u8 *pos = (u8 *)mef_cfg; | ||
1117 | |||
1118 | cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); | ||
1119 | |||
1120 | mef_cfg->criteria = cpu_to_le32(mef->criteria); | ||
1121 | mef_cfg->num_entries = cpu_to_le16(mef->num_entries); | ||
1122 | pos += sizeof(*mef_cfg); | ||
1123 | mef_cfg->mef_entry->mode = mef->mef_entry->mode; | ||
1124 | mef_cfg->mef_entry->action = mef->mef_entry->action; | ||
1125 | pos += sizeof(*(mef_cfg->mef_entry)); | ||
1126 | |||
1127 | if (mwifiex_cmd_append_rpn_expression(priv, mef->mef_entry, &pos)) | ||
1128 | return -1; | ||
1129 | |||
1130 | mef_cfg->mef_entry->exprsize = | ||
1131 | cpu_to_le16(pos - mef_cfg->mef_entry->expr); | ||
1132 | cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); | ||
1133 | |||
1134 | return 0; | ||
1135 | } | ||
1136 | |||
1062 | /* | 1137 | /* |
1063 | * This function prepares the commands before sending them to the firmware. | 1138 | * This function prepares the commands before sending them to the firmware. |
1064 | * | 1139 | * |
@@ -1184,6 +1259,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1184 | cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + | 1259 | cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + |
1185 | S_DS_GEN); | 1260 | S_DS_GEN); |
1186 | break; | 1261 | break; |
1262 | case HostCmd_CMD_11AC_CFG: | ||
1263 | ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf); | ||
1264 | break; | ||
1187 | case HostCmd_CMD_P2P_MODE_CFG: | 1265 | case HostCmd_CMD_P2P_MODE_CFG: |
1188 | cmd_ptr->command = cpu_to_le16(cmd_no); | 1266 | cmd_ptr->command = cpu_to_le16(cmd_no); |
1189 | cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action); | 1267 | cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action); |
@@ -1273,6 +1351,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1273 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: | 1351 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: |
1274 | ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); | 1352 | ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); |
1275 | break; | 1353 | break; |
1354 | case HostCmd_CMD_MEF_CFG: | ||
1355 | ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf); | ||
1356 | break; | ||
1276 | default: | 1357 | default: |
1277 | dev_err(priv->adapter->dev, | 1358 | dev_err(priv->adapter->dev, |
1278 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1359 | "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..9f990e14966e 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -95,7 +95,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, | |||
95 | break; | 95 | break; |
96 | } | 96 | } |
97 | /* Handling errors here */ | 97 | /* Handling errors here */ |
98 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | 98 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
99 | 99 | ||
100 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 100 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
101 | adapter->curr_cmd = NULL; | 101 | adapter->curr_cmd = NULL; |
@@ -907,6 +907,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
907 | case HostCmd_CMD_REMAIN_ON_CHAN: | 907 | case HostCmd_CMD_REMAIN_ON_CHAN: |
908 | ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf); | 908 | ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf); |
909 | break; | 909 | break; |
910 | case HostCmd_CMD_11AC_CFG: | ||
911 | break; | ||
910 | case HostCmd_CMD_P2P_MODE_CFG: | 912 | case HostCmd_CMD_P2P_MODE_CFG: |
911 | ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf); | 913 | ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf); |
912 | break; | 914 | break; |
@@ -976,6 +978,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
976 | case HostCmd_CMD_UAP_BSS_STOP: | 978 | case HostCmd_CMD_UAP_BSS_STOP: |
977 | priv->bss_started = 0; | 979 | priv->bss_started = 0; |
978 | break; | 980 | break; |
981 | case HostCmd_CMD_MEF_CFG: | ||
982 | break; | ||
979 | default: | 983 | default: |
980 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 984 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
981 | resp->command); | 985 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 9f33c92c90f5..e6c9b2ae22ed 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -54,19 +54,10 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, | |||
54 | * This function waits on a cmd wait queue. It also cancels the pending | 54 | * This function waits on a cmd wait queue. It also cancels the pending |
55 | * request after waking up, in case of errors. | 55 | * request after waking up, in case of errors. |
56 | */ | 56 | */ |
57 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) | 57 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, |
58 | struct cmd_ctrl_node *cmd_queued) | ||
58 | { | 59 | { |
59 | int status; | 60 | int status; |
60 | struct cmd_ctrl_node *cmd_queued; | ||
61 | |||
62 | if (!adapter->cmd_queued) | ||
63 | return 0; | ||
64 | |||
65 | cmd_queued = adapter->cmd_queued; | ||
66 | adapter->cmd_queued = NULL; | ||
67 | |||
68 | dev_dbg(adapter->dev, "cmd pending\n"); | ||
69 | atomic_inc(&adapter->cmd_pending); | ||
70 | 61 | ||
71 | /* Wait for completion */ | 62 | /* Wait for completion */ |
72 | status = wait_event_interruptible(adapter->cmd_wait_q.wait, | 63 | status = wait_event_interruptible(adapter->cmd_wait_q.wait, |
@@ -388,7 +379,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
388 | break; | 379 | break; |
389 | } | 380 | } |
390 | if (hs_cfg->is_invoke_hostcmd) { | 381 | if (hs_cfg->is_invoke_hostcmd) { |
391 | if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) { | 382 | if (hs_cfg->conditions == HS_CFG_CANCEL) { |
392 | if (!adapter->is_hs_configured) | 383 | if (!adapter->is_hs_configured) |
393 | /* Already cancelled */ | 384 | /* Already cancelled */ |
394 | break; | 385 | break; |
@@ -403,8 +394,8 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
403 | adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; | 394 | adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; |
404 | if (hs_cfg->gap) | 395 | if (hs_cfg->gap) |
405 | adapter->hs_cfg.gap = (u8)hs_cfg->gap; | 396 | adapter->hs_cfg.gap = (u8)hs_cfg->gap; |
406 | } else if (adapter->hs_cfg.conditions | 397 | } else if (adapter->hs_cfg.conditions == |
407 | == cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) { | 398 | cpu_to_le32(HS_CFG_CANCEL)) { |
408 | /* Return failure if no parameters for HS | 399 | /* Return failure if no parameters for HS |
409 | enable */ | 400 | enable */ |
410 | status = -1; | 401 | status = -1; |
@@ -420,7 +411,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
420 | HostCmd_CMD_802_11_HS_CFG_ENH, | 411 | HostCmd_CMD_802_11_HS_CFG_ENH, |
421 | HostCmd_ACT_GEN_SET, 0, | 412 | HostCmd_ACT_GEN_SET, 0, |
422 | &adapter->hs_cfg); | 413 | &adapter->hs_cfg); |
423 | if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) | 414 | if (hs_cfg->conditions == HS_CFG_CANCEL) |
424 | /* Restore previous condition */ | 415 | /* Restore previous condition */ |
425 | adapter->hs_cfg.conditions = | 416 | adapter->hs_cfg.conditions = |
426 | cpu_to_le32(prev_cond); | 417 | cpu_to_le32(prev_cond); |
@@ -454,7 +445,7 @@ int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type) | |||
454 | { | 445 | { |
455 | struct mwifiex_ds_hs_cfg hscfg; | 446 | struct mwifiex_ds_hs_cfg hscfg; |
456 | 447 | ||
457 | hscfg.conditions = HOST_SLEEP_CFG_CANCEL; | 448 | hscfg.conditions = HS_CFG_CANCEL; |
458 | hscfg.is_invoke_hostcmd = true; | 449 | hscfg.is_invoke_hostcmd = true; |
459 | 450 | ||
460 | return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, | 451 | 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/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 6e76a15a8950..b04b1db29100 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "main.h" | 20 | #include "main.h" |
21 | #include "11ac.h" | ||
21 | 22 | ||
22 | /* This function parses security related parameters from cfg80211_ap_settings | 23 | /* This function parses security related parameters from cfg80211_ap_settings |
23 | * and sets into FW understandable bss_config structure. | 24 | * and sets into FW understandable bss_config structure. |
@@ -177,6 +178,60 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, | |||
177 | return; | 178 | return; |
178 | } | 179 | } |
179 | 180 | ||
181 | /* This function updates 11ac related parameters from IE | ||
182 | * and sets them into bss_config structure. | ||
183 | */ | ||
184 | void mwifiex_set_vht_params(struct mwifiex_private *priv, | ||
185 | struct mwifiex_uap_bss_param *bss_cfg, | ||
186 | struct cfg80211_ap_settings *params) | ||
187 | { | ||
188 | const u8 *vht_ie; | ||
189 | |||
190 | vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail, | ||
191 | params->beacon.tail_len); | ||
192 | if (vht_ie) { | ||
193 | memcpy(&bss_cfg->vht_cap, vht_ie + 2, | ||
194 | sizeof(struct ieee80211_vht_cap)); | ||
195 | priv->ap_11ac_enabled = 1; | ||
196 | } else { | ||
197 | priv->ap_11ac_enabled = 0; | ||
198 | } | ||
199 | |||
200 | return; | ||
201 | } | ||
202 | |||
203 | /* Enable VHT only when cfg80211_ap_settings has VHT IE. | ||
204 | * Otherwise disable VHT. | ||
205 | */ | ||
206 | void mwifiex_set_vht_width(struct mwifiex_private *priv, | ||
207 | enum nl80211_chan_width width, | ||
208 | bool ap_11ac_enable) | ||
209 | { | ||
210 | struct mwifiex_adapter *adapter = priv->adapter; | ||
211 | struct mwifiex_11ac_vht_cfg vht_cfg; | ||
212 | |||
213 | vht_cfg.band_config = VHT_CFG_5GHZ; | ||
214 | vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap; | ||
215 | |||
216 | if (!ap_11ac_enable) { | ||
217 | vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET; | ||
218 | vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET; | ||
219 | } else { | ||
220 | vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET; | ||
221 | vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET; | ||
222 | } | ||
223 | |||
224 | vht_cfg.misc_config = VHT_CAP_UAP_ONLY; | ||
225 | |||
226 | if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80) | ||
227 | vht_cfg.misc_config |= VHT_BW_80_160_80P80; | ||
228 | |||
229 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_11AC_CFG, | ||
230 | HostCmd_ACT_GEN_SET, 0, &vht_cfg); | ||
231 | |||
232 | return; | ||
233 | } | ||
234 | |||
180 | /* This function finds supported rates IE from beacon parameter and sets | 235 | /* This function finds supported rates IE from beacon parameter and sets |
181 | * these rates into bss_config structure. | 236 | * these rates into bss_config structure. |
182 | */ | 237 | */ |
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 21553976b550..e57ac0dd3ab5 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 | ||
@@ -238,7 +239,6 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) | |||
238 | int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, | 239 | int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, |
239 | struct cmd_ctrl_node *cmd_node) | 240 | struct cmd_ctrl_node *cmd_node) |
240 | { | 241 | { |
241 | atomic_dec(&adapter->cmd_pending); | ||
242 | dev_dbg(adapter->dev, "cmd completed: status=%d\n", | 242 | dev_dbg(adapter->dev, "cmd completed: status=%d\n", |
243 | adapter->cmd_wait_q.status); | 243 | adapter->cmd_wait_q.status); |
244 | 244 | ||
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 32adc878041d..2cc81ba590e3 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -436,10 +436,7 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) | |||
436 | = priv->aggr_prio_tbl[7].ampdu_user | 436 | = priv->aggr_prio_tbl[7].ampdu_user |
437 | = BA_STREAM_NOT_ALLOWED; | 437 | = BA_STREAM_NOT_ALLOWED; |
438 | 438 | ||
439 | priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; | 439 | mwifiex_set_ba_params(priv); |
440 | priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; | ||
441 | priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; | ||
442 | |||
443 | mwifiex_reset_11n_rx_seq_num(priv); | 440 | mwifiex_reset_11n_rx_seq_num(priv); |
444 | 441 | ||
445 | atomic_set(&priv->wmm.tx_pkts_queued, 0); | 442 | atomic_set(&priv->wmm.tx_pkts_queued, 0); |
@@ -688,13 +685,13 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | |||
688 | ra_list->total_pkts_size += skb->len; | 685 | ra_list->total_pkts_size += skb->len; |
689 | ra_list->pkt_count++; | 686 | ra_list->pkt_count++; |
690 | 687 | ||
691 | atomic_inc(&priv->wmm.tx_pkts_queued); | ||
692 | |||
693 | if (atomic_read(&priv->wmm.highest_queued_prio) < | 688 | if (atomic_read(&priv->wmm.highest_queued_prio) < |
694 | tos_to_tid_inv[tid_down]) | 689 | tos_to_tid_inv[tid_down]) |
695 | atomic_set(&priv->wmm.highest_queued_prio, | 690 | atomic_set(&priv->wmm.highest_queued_prio, |
696 | tos_to_tid_inv[tid_down]); | 691 | tos_to_tid_inv[tid_down]); |
697 | 692 | ||
693 | atomic_inc(&priv->wmm.tx_pkts_queued); | ||
694 | |||
698 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); | 695 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); |
699 | } | 696 | } |
700 | 697 | ||
@@ -890,19 +887,15 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
890 | struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head; | 887 | struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head; |
891 | struct mwifiex_tid_tbl *tid_ptr; | 888 | struct mwifiex_tid_tbl *tid_ptr; |
892 | atomic_t *hqp; | 889 | atomic_t *hqp; |
893 | int is_list_empty; | 890 | unsigned long flags_bss, flags_ra; |
894 | unsigned long flags; | ||
895 | int i, j; | 891 | int i, j; |
896 | 892 | ||
897 | for (j = adapter->priv_num - 1; j >= 0; --j) { | 893 | for (j = adapter->priv_num - 1; j >= 0; --j) { |
898 | spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, | 894 | spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, |
899 | flags); | 895 | flags_bss); |
900 | is_list_empty = list_empty(&adapter->bss_prio_tbl[j] | 896 | |
901 | .bss_prio_head); | 897 | if (list_empty(&adapter->bss_prio_tbl[j].bss_prio_head)) |
902 | spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, | 898 | goto skip_prio_tbl; |
903 | flags); | ||
904 | if (is_list_empty) | ||
905 | continue; | ||
906 | 899 | ||
907 | if (adapter->bss_prio_tbl[j].bss_prio_cur == | 900 | if (adapter->bss_prio_tbl[j].bss_prio_cur == |
908 | (struct mwifiex_bss_prio_node *) | 901 | (struct mwifiex_bss_prio_node *) |
@@ -919,26 +912,26 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
919 | 912 | ||
920 | do { | 913 | do { |
921 | priv_tmp = bssprio_node->priv; | 914 | priv_tmp = bssprio_node->priv; |
922 | hqp = &priv_tmp->wmm.highest_queued_prio; | ||
923 | 915 | ||
916 | if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0) | ||
917 | goto skip_bss; | ||
918 | |||
919 | /* iterate over the WMM queues of the BSS */ | ||
920 | hqp = &priv_tmp->wmm.highest_queued_prio; | ||
924 | for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { | 921 | for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { |
925 | 922 | ||
923 | spin_lock_irqsave(&priv_tmp->wmm. | ||
924 | ra_list_spinlock, flags_ra); | ||
925 | |||
926 | tid_ptr = &(priv_tmp)->wmm. | 926 | tid_ptr = &(priv_tmp)->wmm. |
927 | tid_tbl_ptr[tos_to_tid[i]]; | 927 | tid_tbl_ptr[tos_to_tid[i]]; |
928 | 928 | ||
929 | /* For non-STA ra_list_curr may be NULL */ | 929 | /* For non-STA ra_list_curr may be NULL */ |
930 | if (!tid_ptr->ra_list_curr) | 930 | if (!tid_ptr->ra_list_curr) |
931 | continue; | 931 | goto skip_wmm_queue; |
932 | 932 | ||
933 | spin_lock_irqsave(&tid_ptr->tid_tbl_lock, | 933 | if (list_empty(&tid_ptr->ra_list)) |
934 | flags); | 934 | goto skip_wmm_queue; |
935 | is_list_empty = | ||
936 | list_empty(&adapter->bss_prio_tbl[j] | ||
937 | .bss_prio_head); | ||
938 | spin_unlock_irqrestore(&tid_ptr->tid_tbl_lock, | ||
939 | flags); | ||
940 | if (is_list_empty) | ||
941 | continue; | ||
942 | 935 | ||
943 | /* | 936 | /* |
944 | * Always choose the next ra we transmitted | 937 | * Always choose the next ra we transmitted |
@@ -960,10 +953,8 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
960 | } | 953 | } |
961 | 954 | ||
962 | do { | 955 | do { |
963 | is_list_empty = | 956 | if (!skb_queue_empty(&ptr->skb_head)) |
964 | skb_queue_empty(&ptr->skb_head); | 957 | /* holds both locks */ |
965 | |||
966 | if (!is_list_empty) | ||
967 | goto found; | 958 | goto found; |
968 | 959 | ||
969 | /* Get next ra */ | 960 | /* Get next ra */ |
@@ -978,14 +969,14 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
978 | struct mwifiex_ra_list_tbl, | 969 | struct mwifiex_ra_list_tbl, |
979 | list); | 970 | list); |
980 | } while (ptr != head); | 971 | } while (ptr != head); |
981 | } | ||
982 | 972 | ||
983 | /* No packet at any TID for this priv. Mark as such | 973 | skip_wmm_queue: |
984 | * to skip checking TIDs for this priv (until pkt is | 974 | spin_unlock_irqrestore(&priv_tmp->wmm. |
985 | * added). | 975 | ra_list_spinlock, |
986 | */ | 976 | flags_ra); |
987 | atomic_set(hqp, NO_PKT_PRIO_TID); | 977 | } |
988 | 978 | ||
979 | skip_bss: | ||
989 | /* Get next bss priority node */ | 980 | /* Get next bss priority node */ |
990 | bssprio_node = list_first_entry(&bssprio_node->list, | 981 | bssprio_node = list_first_entry(&bssprio_node->list, |
991 | struct mwifiex_bss_prio_node, | 982 | struct mwifiex_bss_prio_node, |
@@ -1000,14 +991,21 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
1000 | struct mwifiex_bss_prio_node, | 991 | struct mwifiex_bss_prio_node, |
1001 | list); | 992 | list); |
1002 | } while (bssprio_node != bssprio_head); | 993 | } while (bssprio_node != bssprio_head); |
994 | |||
995 | skip_prio_tbl: | ||
996 | spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, | ||
997 | flags_bss); | ||
1003 | } | 998 | } |
999 | |||
1004 | return NULL; | 1000 | return NULL; |
1005 | 1001 | ||
1006 | found: | 1002 | found: |
1007 | spin_lock_irqsave(&priv_tmp->wmm.ra_list_spinlock, flags); | 1003 | /* holds bss_prio_lock / ra_list_spinlock */ |
1008 | if (atomic_read(hqp) > i) | 1004 | if (atomic_read(hqp) > i) |
1009 | atomic_set(hqp, i); | 1005 | atomic_set(hqp, i); |
1010 | spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags); | 1006 | spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra); |
1007 | spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, | ||
1008 | flags_bss); | ||
1011 | 1009 | ||
1012 | *priv = priv_tmp; | 1010 | *priv = priv_tmp; |
1013 | *tid = tos_to_tid[i]; | 1011 | *tid = tos_to_tid[i]; |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9f9a1449e812..ee1778cf270f 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) |
@@ -4796,16 +4811,14 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | |||
4796 | struct mwl8k_priv *priv = hw->priv; | 4811 | struct mwl8k_priv *priv = hw->priv; |
4797 | int rc; | 4812 | int rc; |
4798 | 4813 | ||
4799 | if (conf->flags & IEEE80211_CONF_IDLE) { | ||
4800 | mwl8k_cmd_radio_disable(hw); | ||
4801 | return 0; | ||
4802 | } | ||
4803 | |||
4804 | rc = mwl8k_fw_lock(hw); | 4814 | rc = mwl8k_fw_lock(hw); |
4805 | if (rc) | 4815 | if (rc) |
4806 | return rc; | 4816 | return rc; |
4807 | 4817 | ||
4808 | rc = mwl8k_cmd_radio_enable(hw); | 4818 | if (conf->flags & IEEE80211_CONF_IDLE) |
4819 | rc = mwl8k_cmd_radio_disable(hw); | ||
4820 | else | ||
4821 | rc = mwl8k_cmd_radio_enable(hw); | ||
4809 | if (rc) | 4822 | if (rc) |
4810 | goto out; | 4823 | goto out; |
4811 | 4824 | ||
@@ -5433,12 +5446,17 @@ enum { | |||
5433 | MWL8363 = 0, | 5446 | MWL8363 = 0, |
5434 | MWL8687, | 5447 | MWL8687, |
5435 | MWL8366, | 5448 | MWL8366, |
5449 | MWL8764, | ||
5436 | }; | 5450 | }; |
5437 | 5451 | ||
5438 | #define MWL8K_8366_AP_FW_API 3 | 5452 | #define MWL8K_8366_AP_FW_API 3 |
5439 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" | 5453 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" |
5440 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) | 5454 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) |
5441 | 5455 | ||
5456 | #define MWL8K_8764_AP_FW_API 1 | ||
5457 | #define _MWL8K_8764_AP_FW(api) "mwl8k/fmimage_8764_ap-" #api ".fw" | ||
5458 | #define MWL8K_8764_AP_FW(api) _MWL8K_8764_AP_FW(api) | ||
5459 | |||
5442 | static struct mwl8k_device_info mwl8k_info_tbl[] = { | 5460 | static struct mwl8k_device_info mwl8k_info_tbl[] = { |
5443 | [MWL8363] = { | 5461 | [MWL8363] = { |
5444 | .part_name = "88w8363", | 5462 | .part_name = "88w8363", |
@@ -5456,7 +5474,13 @@ static struct mwl8k_device_info mwl8k_info_tbl[] = { | |||
5456 | .fw_image_sta = "mwl8k/fmimage_8366.fw", | 5474 | .fw_image_sta = "mwl8k/fmimage_8366.fw", |
5457 | .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), | 5475 | .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), |
5458 | .fw_api_ap = MWL8K_8366_AP_FW_API, | 5476 | .fw_api_ap = MWL8K_8366_AP_FW_API, |
5459 | .ap_rxd_ops = &rxd_8366_ap_ops, | 5477 | .ap_rxd_ops = &rxd_ap_ops, |
5478 | }, | ||
5479 | [MWL8764] = { | ||
5480 | .part_name = "88w8764", | ||
5481 | .fw_image_ap = MWL8K_8764_AP_FW(MWL8K_8764_AP_FW_API), | ||
5482 | .fw_api_ap = MWL8K_8764_AP_FW_API, | ||
5483 | .ap_rxd_ops = &rxd_ap_ops, | ||
5460 | }, | 5484 | }, |
5461 | }; | 5485 | }; |
5462 | 5486 | ||
@@ -5478,6 +5502,7 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { | |||
5478 | { PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, }, | 5502 | { PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, }, |
5479 | { PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, }, | 5503 | { PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, }, |
5480 | { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, | 5504 | { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, |
5505 | { PCI_VDEVICE(MARVELL, 0x2b36), .driver_data = MWL8764, }, | ||
5481 | { }, | 5506 | { }, |
5482 | }; | 5507 | }; |
5483 | MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); | 5508 | MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); |
@@ -5999,6 +6024,8 @@ static int mwl8k_probe(struct pci_dev *pdev, | |||
5999 | priv->pdev = pdev; | 6024 | priv->pdev = pdev; |
6000 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; | 6025 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; |
6001 | 6026 | ||
6027 | if (id->driver_data == MWL8764) | ||
6028 | priv->is_8764 = true; | ||
6002 | 6029 | ||
6003 | priv->sram = pci_iomap(pdev, 0, 0x10000); | 6030 | priv->sram = pci_iomap(pdev, 0, 0x10000); |
6004 | if (priv->sram == NULL) { | 6031 | 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..9b915d3a44be 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -20,6 +20,7 @@ if RT2X00 | |||
20 | config RT2400PCI | 20 | config RT2400PCI |
21 | tristate "Ralink rt2400 (PCI/PCMCIA) support" | 21 | tristate "Ralink rt2400 (PCI/PCMCIA) support" |
22 | depends on PCI | 22 | depends on PCI |
23 | select RT2X00_LIB_MMIO | ||
23 | select RT2X00_LIB_PCI | 24 | select RT2X00_LIB_PCI |
24 | select EEPROM_93CX6 | 25 | select EEPROM_93CX6 |
25 | ---help--- | 26 | ---help--- |
@@ -31,6 +32,7 @@ config RT2400PCI | |||
31 | config RT2500PCI | 32 | config RT2500PCI |
32 | tristate "Ralink rt2500 (PCI/PCMCIA) support" | 33 | tristate "Ralink rt2500 (PCI/PCMCIA) support" |
33 | depends on PCI | 34 | depends on PCI |
35 | select RT2X00_LIB_MMIO | ||
34 | select RT2X00_LIB_PCI | 36 | select RT2X00_LIB_PCI |
35 | select EEPROM_93CX6 | 37 | select EEPROM_93CX6 |
36 | ---help--- | 38 | ---help--- |
@@ -43,6 +45,7 @@ config RT61PCI | |||
43 | tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support" | 45 | tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support" |
44 | depends on PCI | 46 | depends on PCI |
45 | select RT2X00_LIB_PCI | 47 | select RT2X00_LIB_PCI |
48 | select RT2X00_LIB_MMIO | ||
46 | select RT2X00_LIB_FIRMWARE | 49 | select RT2X00_LIB_FIRMWARE |
47 | select RT2X00_LIB_CRYPTO | 50 | select RT2X00_LIB_CRYPTO |
48 | select CRC_ITU_T | 51 | select CRC_ITU_T |
@@ -55,10 +58,11 @@ config RT61PCI | |||
55 | 58 | ||
56 | config RT2800PCI | 59 | config RT2800PCI |
57 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" | 60 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" |
58 | depends on PCI || RALINK_RT288X || RALINK_RT305X | 61 | depends on PCI || SOC_RT288X || SOC_RT305X |
59 | select RT2800_LIB | 62 | select RT2800_LIB |
63 | select RT2X00_LIB_MMIO | ||
60 | select RT2X00_LIB_PCI if PCI | 64 | select RT2X00_LIB_PCI if PCI |
61 | select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X | 65 | select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X |
62 | select RT2X00_LIB_FIRMWARE | 66 | select RT2X00_LIB_FIRMWARE |
63 | select RT2X00_LIB_CRYPTO | 67 | select RT2X00_LIB_CRYPTO |
64 | select CRC_CCITT | 68 | select CRC_CCITT |
@@ -169,6 +173,13 @@ config RT2800USB_RT53XX | |||
169 | rt2800usb driver. | 173 | rt2800usb driver. |
170 | Supported chips: RT5370 | 174 | Supported chips: RT5370 |
171 | 175 | ||
176 | config RT2800USB_RT55XX | ||
177 | bool "rt2800usb - Include support for rt55xx devices (EXPERIMENTAL)" | ||
178 | ---help--- | ||
179 | This adds support for rt55xx wireless chipset family to the | ||
180 | rt2800usb driver. | ||
181 | Supported chips: RT5572 | ||
182 | |||
172 | config RT2800USB_UNKNOWN | 183 | config RT2800USB_UNKNOWN |
173 | bool "rt2800usb - Include support for unknown (USB) devices" | 184 | bool "rt2800usb - Include support for unknown (USB) devices" |
174 | default n | 185 | default n |
@@ -185,6 +196,9 @@ endif | |||
185 | config RT2800_LIB | 196 | config RT2800_LIB |
186 | tristate | 197 | tristate |
187 | 198 | ||
199 | config RT2X00_LIB_MMIO | ||
200 | tristate | ||
201 | |||
188 | config RT2X00_LIB_PCI | 202 | config RT2X00_LIB_PCI |
189 | tristate | 203 | tristate |
190 | select RT2X00_LIB | 204 | select RT2X00_LIB |
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 349d5b8284a4..f069d8bc5b67 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile | |||
@@ -9,6 +9,7 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o | |||
9 | rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o | 9 | rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o |
10 | 10 | ||
11 | obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o | 11 | obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o |
12 | obj-$(CONFIG_RT2X00_LIB_MMIO) += rt2x00mmio.o | ||
12 | obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o | 13 | obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o |
13 | obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o | 14 | obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o |
14 | obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o | 15 | obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 221beaaa83f1..d1b10d457230 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -34,13 +34,14 @@ | |||
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | 35 | ||
36 | #include "rt2x00.h" | 36 | #include "rt2x00.h" |
37 | #include "rt2x00mmio.h" | ||
37 | #include "rt2x00pci.h" | 38 | #include "rt2x00pci.h" |
38 | #include "rt2400pci.h" | 39 | #include "rt2400pci.h" |
39 | 40 | ||
40 | /* | 41 | /* |
41 | * Register access. | 42 | * Register access. |
42 | * All access to the CSR registers will go through the methods | 43 | * All access to the CSR registers will go through the methods |
43 | * rt2x00pci_register_read and rt2x00pci_register_write. | 44 | * rt2x00mmio_register_read and rt2x00mmio_register_write. |
44 | * BBP and RF register require indirect register access, | 45 | * BBP and RF register require indirect register access, |
45 | * and use the CSR registers BBPCSR and RFCSR to achieve this. | 46 | * and use the CSR registers BBPCSR and RFCSR to achieve this. |
46 | * These indirect registers work with busy bits, | 47 | * These indirect registers work with busy bits, |
@@ -51,9 +52,9 @@ | |||
51 | * and we will print an error. | 52 | * and we will print an error. |
52 | */ | 53 | */ |
53 | #define WAIT_FOR_BBP(__dev, __reg) \ | 54 | #define WAIT_FOR_BBP(__dev, __reg) \ |
54 | rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) | 55 | rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) |
55 | #define WAIT_FOR_RF(__dev, __reg) \ | 56 | #define WAIT_FOR_RF(__dev, __reg) \ |
56 | rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) | 57 | rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) |
57 | 58 | ||
58 | static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, | 59 | static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, |
59 | const unsigned int word, const u8 value) | 60 | const unsigned int word, const u8 value) |
@@ -73,7 +74,7 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
73 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); | 74 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); |
74 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); | 75 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); |
75 | 76 | ||
76 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); | 77 | rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg); |
77 | } | 78 | } |
78 | 79 | ||
79 | mutex_unlock(&rt2x00dev->csr_mutex); | 80 | mutex_unlock(&rt2x00dev->csr_mutex); |
@@ -100,7 +101,7 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
100 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); | 101 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); |
101 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); | 102 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); |
102 | 103 | ||
103 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); | 104 | rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg); |
104 | 105 | ||
105 | WAIT_FOR_BBP(rt2x00dev, ®); | 106 | WAIT_FOR_BBP(rt2x00dev, ®); |
106 | } | 107 | } |
@@ -128,7 +129,7 @@ static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, | |||
128 | rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); | 129 | rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); |
129 | rt2x00_set_field32(®, RFCSR_BUSY, 1); | 130 | rt2x00_set_field32(®, RFCSR_BUSY, 1); |
130 | 131 | ||
131 | rt2x00pci_register_write(rt2x00dev, RFCSR, reg); | 132 | rt2x00mmio_register_write(rt2x00dev, RFCSR, reg); |
132 | rt2x00_rf_write(rt2x00dev, word, value); | 133 | rt2x00_rf_write(rt2x00dev, word, value); |
133 | } | 134 | } |
134 | 135 | ||
@@ -140,7 +141,7 @@ static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | |||
140 | struct rt2x00_dev *rt2x00dev = eeprom->data; | 141 | struct rt2x00_dev *rt2x00dev = eeprom->data; |
141 | u32 reg; | 142 | u32 reg; |
142 | 143 | ||
143 | rt2x00pci_register_read(rt2x00dev, CSR21, ®); | 144 | rt2x00mmio_register_read(rt2x00dev, CSR21, ®); |
144 | 145 | ||
145 | eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN); | 146 | eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN); |
146 | eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT); | 147 | eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT); |
@@ -162,15 +163,15 @@ static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom) | |||
162 | rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT, | 163 | rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT, |
163 | !!eeprom->reg_chip_select); | 164 | !!eeprom->reg_chip_select); |
164 | 165 | ||
165 | rt2x00pci_register_write(rt2x00dev, CSR21, reg); | 166 | rt2x00mmio_register_write(rt2x00dev, CSR21, reg); |
166 | } | 167 | } |
167 | 168 | ||
168 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 169 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
169 | static const struct rt2x00debug rt2400pci_rt2x00debug = { | 170 | static const struct rt2x00debug rt2400pci_rt2x00debug = { |
170 | .owner = THIS_MODULE, | 171 | .owner = THIS_MODULE, |
171 | .csr = { | 172 | .csr = { |
172 | .read = rt2x00pci_register_read, | 173 | .read = rt2x00mmio_register_read, |
173 | .write = rt2x00pci_register_write, | 174 | .write = rt2x00mmio_register_write, |
174 | .flags = RT2X00DEBUGFS_OFFSET, | 175 | .flags = RT2X00DEBUGFS_OFFSET, |
175 | .word_base = CSR_REG_BASE, | 176 | .word_base = CSR_REG_BASE, |
176 | .word_size = sizeof(u32), | 177 | .word_size = sizeof(u32), |
@@ -204,7 +205,7 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) | |||
204 | { | 205 | { |
205 | u32 reg; | 206 | u32 reg; |
206 | 207 | ||
207 | rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); | 208 | rt2x00mmio_register_read(rt2x00dev, GPIOCSR, ®); |
208 | return rt2x00_get_field32(reg, GPIOCSR_VAL0); | 209 | return rt2x00_get_field32(reg, GPIOCSR_VAL0); |
209 | } | 210 | } |
210 | 211 | ||
@@ -217,14 +218,14 @@ static void rt2400pci_brightness_set(struct led_classdev *led_cdev, | |||
217 | unsigned int enabled = brightness != LED_OFF; | 218 | unsigned int enabled = brightness != LED_OFF; |
218 | u32 reg; | 219 | u32 reg; |
219 | 220 | ||
220 | rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); | 221 | rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, ®); |
221 | 222 | ||
222 | if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) | 223 | if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) |
223 | rt2x00_set_field32(®, LEDCSR_LINK, enabled); | 224 | rt2x00_set_field32(®, LEDCSR_LINK, enabled); |
224 | else if (led->type == LED_TYPE_ACTIVITY) | 225 | else if (led->type == LED_TYPE_ACTIVITY) |
225 | rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); | 226 | rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); |
226 | 227 | ||
227 | rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); | 228 | rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg); |
228 | } | 229 | } |
229 | 230 | ||
230 | static int rt2400pci_blink_set(struct led_classdev *led_cdev, | 231 | static int rt2400pci_blink_set(struct led_classdev *led_cdev, |
@@ -235,10 +236,10 @@ static int rt2400pci_blink_set(struct led_classdev *led_cdev, | |||
235 | container_of(led_cdev, struct rt2x00_led, led_dev); | 236 | container_of(led_cdev, struct rt2x00_led, led_dev); |
236 | u32 reg; | 237 | u32 reg; |
237 | 238 | ||
238 | rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); | 239 | rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, ®); |
239 | rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on); | 240 | rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on); |
240 | rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); | 241 | rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); |
241 | rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); | 242 | rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg); |
242 | 243 | ||
243 | return 0; | 244 | return 0; |
244 | } | 245 | } |
@@ -268,7 +269,7 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev, | |||
268 | * Note that the version error will always be dropped | 269 | * Note that the version error will always be dropped |
269 | * since there is no filter for it at this time. | 270 | * since there is no filter for it at this time. |
270 | */ | 271 | */ |
271 | rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); | 272 | rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®); |
272 | rt2x00_set_field32(®, RXCSR0_DROP_CRC, | 273 | rt2x00_set_field32(®, RXCSR0_DROP_CRC, |
273 | !(filter_flags & FIF_FCSFAIL)); | 274 | !(filter_flags & FIF_FCSFAIL)); |
274 | rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, | 275 | rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, |
@@ -281,7 +282,7 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev, | |||
281 | !(filter_flags & FIF_PROMISC_IN_BSS) && | 282 | !(filter_flags & FIF_PROMISC_IN_BSS) && |
282 | !rt2x00dev->intf_ap_count); | 283 | !rt2x00dev->intf_ap_count); |
283 | rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); | 284 | rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); |
284 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | 285 | rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); |
285 | } | 286 | } |
286 | 287 | ||
287 | static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, | 288 | static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, |
@@ -297,25 +298,26 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
297 | * Enable beacon config | 298 | * Enable beacon config |
298 | */ | 299 | */ |
299 | bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); | 300 | bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); |
300 | rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); | 301 | rt2x00mmio_register_read(rt2x00dev, BCNCSR1, ®); |
301 | rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); | 302 | rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); |
302 | rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); | 303 | rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg); |
303 | 304 | ||
304 | /* | 305 | /* |
305 | * Enable synchronisation. | 306 | * Enable synchronisation. |
306 | */ | 307 | */ |
307 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 308 | rt2x00mmio_register_read(rt2x00dev, CSR14, ®); |
308 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); | 309 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); |
309 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 310 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
310 | } | 311 | } |
311 | 312 | ||
312 | if (flags & CONFIG_UPDATE_MAC) | 313 | if (flags & CONFIG_UPDATE_MAC) |
313 | rt2x00pci_register_multiwrite(rt2x00dev, CSR3, | 314 | rt2x00mmio_register_multiwrite(rt2x00dev, CSR3, |
314 | conf->mac, sizeof(conf->mac)); | 315 | conf->mac, sizeof(conf->mac)); |
315 | 316 | ||
316 | if (flags & CONFIG_UPDATE_BSSID) | 317 | if (flags & CONFIG_UPDATE_BSSID) |
317 | rt2x00pci_register_multiwrite(rt2x00dev, CSR5, | 318 | rt2x00mmio_register_multiwrite(rt2x00dev, CSR5, |
318 | conf->bssid, sizeof(conf->bssid)); | 319 | conf->bssid, |
320 | sizeof(conf->bssid)); | ||
319 | } | 321 | } |
320 | 322 | ||
321 | static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, | 323 | static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, |
@@ -331,68 +333,68 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, | |||
331 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 333 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
332 | preamble_mask = erp->short_preamble << 3; | 334 | preamble_mask = erp->short_preamble << 3; |
333 | 335 | ||
334 | rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); | 336 | rt2x00mmio_register_read(rt2x00dev, TXCSR1, ®); |
335 | rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x1ff); | 337 | rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x1ff); |
336 | rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0x13a); | 338 | rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0x13a); |
337 | rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); | 339 | rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); |
338 | rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); | 340 | rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); |
339 | rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); | 341 | rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg); |
340 | 342 | ||
341 | rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); | 343 | rt2x00mmio_register_read(rt2x00dev, ARCSR2, ®); |
342 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); | 344 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); |
343 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); | 345 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); |
344 | rt2x00_set_field32(®, ARCSR2_LENGTH, | 346 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
345 | GET_DURATION(ACK_SIZE, 10)); | 347 | GET_DURATION(ACK_SIZE, 10)); |
346 | rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); | 348 | rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg); |
347 | 349 | ||
348 | rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); | 350 | rt2x00mmio_register_read(rt2x00dev, ARCSR3, ®); |
349 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); | 351 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); |
350 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); | 352 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); |
351 | rt2x00_set_field32(®, ARCSR2_LENGTH, | 353 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
352 | GET_DURATION(ACK_SIZE, 20)); | 354 | GET_DURATION(ACK_SIZE, 20)); |
353 | rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); | 355 | rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg); |
354 | 356 | ||
355 | rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); | 357 | rt2x00mmio_register_read(rt2x00dev, ARCSR4, ®); |
356 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); | 358 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); |
357 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); | 359 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); |
358 | rt2x00_set_field32(®, ARCSR2_LENGTH, | 360 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
359 | GET_DURATION(ACK_SIZE, 55)); | 361 | GET_DURATION(ACK_SIZE, 55)); |
360 | rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); | 362 | rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg); |
361 | 363 | ||
362 | rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); | 364 | rt2x00mmio_register_read(rt2x00dev, ARCSR5, ®); |
363 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); | 365 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); |
364 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); | 366 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); |
365 | rt2x00_set_field32(®, ARCSR2_LENGTH, | 367 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
366 | GET_DURATION(ACK_SIZE, 110)); | 368 | GET_DURATION(ACK_SIZE, 110)); |
367 | rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); | 369 | rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg); |
368 | } | 370 | } |
369 | 371 | ||
370 | if (changed & BSS_CHANGED_BASIC_RATES) | 372 | if (changed & BSS_CHANGED_BASIC_RATES) |
371 | rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); | 373 | rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates); |
372 | 374 | ||
373 | if (changed & BSS_CHANGED_ERP_SLOT) { | 375 | if (changed & BSS_CHANGED_ERP_SLOT) { |
374 | rt2x00pci_register_read(rt2x00dev, CSR11, ®); | 376 | rt2x00mmio_register_read(rt2x00dev, CSR11, ®); |
375 | rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); | 377 | rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); |
376 | rt2x00pci_register_write(rt2x00dev, CSR11, reg); | 378 | rt2x00mmio_register_write(rt2x00dev, CSR11, reg); |
377 | 379 | ||
378 | rt2x00pci_register_read(rt2x00dev, CSR18, ®); | 380 | rt2x00mmio_register_read(rt2x00dev, CSR18, ®); |
379 | rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); | 381 | rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); |
380 | rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); | 382 | rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); |
381 | rt2x00pci_register_write(rt2x00dev, CSR18, reg); | 383 | rt2x00mmio_register_write(rt2x00dev, CSR18, reg); |
382 | 384 | ||
383 | rt2x00pci_register_read(rt2x00dev, CSR19, ®); | 385 | rt2x00mmio_register_read(rt2x00dev, CSR19, ®); |
384 | rt2x00_set_field32(®, CSR19_DIFS, erp->difs); | 386 | rt2x00_set_field32(®, CSR19_DIFS, erp->difs); |
385 | rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); | 387 | rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); |
386 | rt2x00pci_register_write(rt2x00dev, CSR19, reg); | 388 | rt2x00mmio_register_write(rt2x00dev, CSR19, reg); |
387 | } | 389 | } |
388 | 390 | ||
389 | if (changed & BSS_CHANGED_BEACON_INT) { | 391 | if (changed & BSS_CHANGED_BEACON_INT) { |
390 | rt2x00pci_register_read(rt2x00dev, CSR12, ®); | 392 | rt2x00mmio_register_read(rt2x00dev, CSR12, ®); |
391 | rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, | 393 | rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, |
392 | erp->beacon_int * 16); | 394 | erp->beacon_int * 16); |
393 | rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, | 395 | rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, |
394 | erp->beacon_int * 16); | 396 | erp->beacon_int * 16); |
395 | rt2x00pci_register_write(rt2x00dev, CSR12, reg); | 397 | rt2x00mmio_register_write(rt2x00dev, CSR12, reg); |
396 | } | 398 | } |
397 | } | 399 | } |
398 | 400 | ||
@@ -496,7 +498,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
496 | /* | 498 | /* |
497 | * Clear false CRC during channel switch. | 499 | * Clear false CRC during channel switch. |
498 | */ | 500 | */ |
499 | rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1); | 501 | rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1); |
500 | } | 502 | } |
501 | 503 | ||
502 | static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) | 504 | static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) |
@@ -509,12 +511,12 @@ static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |||
509 | { | 511 | { |
510 | u32 reg; | 512 | u32 reg; |
511 | 513 | ||
512 | rt2x00pci_register_read(rt2x00dev, CSR11, ®); | 514 | rt2x00mmio_register_read(rt2x00dev, CSR11, ®); |
513 | rt2x00_set_field32(®, CSR11_LONG_RETRY, | 515 | rt2x00_set_field32(®, CSR11_LONG_RETRY, |
514 | libconf->conf->long_frame_max_tx_count); | 516 | libconf->conf->long_frame_max_tx_count); |
515 | rt2x00_set_field32(®, CSR11_SHORT_RETRY, | 517 | rt2x00_set_field32(®, CSR11_SHORT_RETRY, |
516 | libconf->conf->short_frame_max_tx_count); | 518 | libconf->conf->short_frame_max_tx_count); |
517 | rt2x00pci_register_write(rt2x00dev, CSR11, reg); | 519 | rt2x00mmio_register_write(rt2x00dev, CSR11, reg); |
518 | } | 520 | } |
519 | 521 | ||
520 | static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, | 522 | static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, |
@@ -526,7 +528,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, | |||
526 | u32 reg; | 528 | u32 reg; |
527 | 529 | ||
528 | if (state == STATE_SLEEP) { | 530 | if (state == STATE_SLEEP) { |
529 | rt2x00pci_register_read(rt2x00dev, CSR20, ®); | 531 | rt2x00mmio_register_read(rt2x00dev, CSR20, ®); |
530 | rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, | 532 | rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, |
531 | (rt2x00dev->beacon_int - 20) * 16); | 533 | (rt2x00dev->beacon_int - 20) * 16); |
532 | rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, | 534 | rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, |
@@ -534,14 +536,14 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, | |||
534 | 536 | ||
535 | /* We must first disable autowake before it can be enabled */ | 537 | /* We must first disable autowake before it can be enabled */ |
536 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); | 538 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); |
537 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | 539 | rt2x00mmio_register_write(rt2x00dev, CSR20, reg); |
538 | 540 | ||
539 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); | 541 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); |
540 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | 542 | rt2x00mmio_register_write(rt2x00dev, CSR20, reg); |
541 | } else { | 543 | } else { |
542 | rt2x00pci_register_read(rt2x00dev, CSR20, ®); | 544 | rt2x00mmio_register_read(rt2x00dev, CSR20, ®); |
543 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); | 545 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); |
544 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | 546 | rt2x00mmio_register_write(rt2x00dev, CSR20, reg); |
545 | } | 547 | } |
546 | 548 | ||
547 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | 549 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); |
@@ -567,10 +569,10 @@ static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev, | |||
567 | { | 569 | { |
568 | u32 reg; | 570 | u32 reg; |
569 | 571 | ||
570 | rt2x00pci_register_read(rt2x00dev, CSR11, ®); | 572 | rt2x00mmio_register_read(rt2x00dev, CSR11, ®); |
571 | rt2x00_set_field32(®, CSR11_CWMIN, cw_min); | 573 | rt2x00_set_field32(®, CSR11_CWMIN, cw_min); |
572 | rt2x00_set_field32(®, CSR11_CWMAX, cw_max); | 574 | rt2x00_set_field32(®, CSR11_CWMAX, cw_max); |
573 | rt2x00pci_register_write(rt2x00dev, CSR11, reg); | 575 | rt2x00mmio_register_write(rt2x00dev, CSR11, reg); |
574 | } | 576 | } |
575 | 577 | ||
576 | /* | 578 | /* |
@@ -585,7 +587,7 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev, | |||
585 | /* | 587 | /* |
586 | * Update FCS error count from register. | 588 | * Update FCS error count from register. |
587 | */ | 589 | */ |
588 | rt2x00pci_register_read(rt2x00dev, CNT0, ®); | 590 | rt2x00mmio_register_read(rt2x00dev, CNT0, ®); |
589 | qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); | 591 | qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); |
590 | 592 | ||
591 | /* | 593 | /* |
@@ -640,16 +642,16 @@ static void rt2400pci_start_queue(struct data_queue *queue) | |||
640 | 642 | ||
641 | switch (queue->qid) { | 643 | switch (queue->qid) { |
642 | case QID_RX: | 644 | case QID_RX: |
643 | rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); | 645 | rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®); |
644 | rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); | 646 | rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); |
645 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | 647 | rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); |
646 | break; | 648 | break; |
647 | case QID_BEACON: | 649 | case QID_BEACON: |
648 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 650 | rt2x00mmio_register_read(rt2x00dev, CSR14, ®); |
649 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | 651 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); |
650 | rt2x00_set_field32(®, CSR14_TBCN, 1); | 652 | rt2x00_set_field32(®, CSR14_TBCN, 1); |
651 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); | 653 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); |
652 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 654 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
653 | break; | 655 | break; |
654 | default: | 656 | default: |
655 | break; | 657 | break; |
@@ -663,19 +665,19 @@ static void rt2400pci_kick_queue(struct data_queue *queue) | |||
663 | 665 | ||
664 | switch (queue->qid) { | 666 | switch (queue->qid) { |
665 | case QID_AC_VO: | 667 | case QID_AC_VO: |
666 | rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); | 668 | rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); |
667 | rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); | 669 | rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); |
668 | rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); | 670 | rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); |
669 | break; | 671 | break; |
670 | case QID_AC_VI: | 672 | case QID_AC_VI: |
671 | rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); | 673 | rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); |
672 | rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); | 674 | rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); |
673 | rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); | 675 | rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); |
674 | break; | 676 | break; |
675 | case QID_ATIM: | 677 | case QID_ATIM: |
676 | rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); | 678 | rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); |
677 | rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); | 679 | rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); |
678 | rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); | 680 | rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); |
679 | break; | 681 | break; |
680 | default: | 682 | default: |
681 | break; | 683 | break; |
@@ -691,21 +693,21 @@ static void rt2400pci_stop_queue(struct data_queue *queue) | |||
691 | case QID_AC_VO: | 693 | case QID_AC_VO: |
692 | case QID_AC_VI: | 694 | case QID_AC_VI: |
693 | case QID_ATIM: | 695 | case QID_ATIM: |
694 | rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); | 696 | rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); |
695 | rt2x00_set_field32(®, TXCSR0_ABORT, 1); | 697 | rt2x00_set_field32(®, TXCSR0_ABORT, 1); |
696 | rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); | 698 | rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); |
697 | break; | 699 | break; |
698 | case QID_RX: | 700 | case QID_RX: |
699 | rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); | 701 | rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®); |
700 | rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); | 702 | rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); |
701 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | 703 | rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); |
702 | break; | 704 | break; |
703 | case QID_BEACON: | 705 | case QID_BEACON: |
704 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 706 | rt2x00mmio_register_read(rt2x00dev, CSR14, ®); |
705 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); | 707 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); |
706 | rt2x00_set_field32(®, CSR14_TBCN, 0); | 708 | rt2x00_set_field32(®, CSR14_TBCN, 0); |
707 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 709 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
708 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 710 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
709 | 711 | ||
710 | /* | 712 | /* |
711 | * Wait for possibly running tbtt tasklets. | 713 | * Wait for possibly running tbtt tasklets. |
@@ -722,7 +724,7 @@ static void rt2400pci_stop_queue(struct data_queue *queue) | |||
722 | */ | 724 | */ |
723 | static bool rt2400pci_get_entry_state(struct queue_entry *entry) | 725 | static bool rt2400pci_get_entry_state(struct queue_entry *entry) |
724 | { | 726 | { |
725 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 727 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
726 | u32 word; | 728 | u32 word; |
727 | 729 | ||
728 | if (entry->queue->qid == QID_RX) { | 730 | if (entry->queue->qid == QID_RX) { |
@@ -739,7 +741,7 @@ static bool rt2400pci_get_entry_state(struct queue_entry *entry) | |||
739 | 741 | ||
740 | static void rt2400pci_clear_entry(struct queue_entry *entry) | 742 | static void rt2400pci_clear_entry(struct queue_entry *entry) |
741 | { | 743 | { |
742 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 744 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
743 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 745 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
744 | u32 word; | 746 | u32 word; |
745 | 747 | ||
@@ -765,53 +767,53 @@ static void rt2400pci_clear_entry(struct queue_entry *entry) | |||
765 | 767 | ||
766 | static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) | 768 | static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) |
767 | { | 769 | { |
768 | struct queue_entry_priv_pci *entry_priv; | 770 | struct queue_entry_priv_mmio *entry_priv; |
769 | u32 reg; | 771 | u32 reg; |
770 | 772 | ||
771 | /* | 773 | /* |
772 | * Initialize registers. | 774 | * Initialize registers. |
773 | */ | 775 | */ |
774 | rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); | 776 | rt2x00mmio_register_read(rt2x00dev, TXCSR2, ®); |
775 | rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); | 777 | rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); |
776 | rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); | 778 | rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); |
777 | rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit); | 779 | rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit); |
778 | rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); | 780 | rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); |
779 | rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); | 781 | rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg); |
780 | 782 | ||
781 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; | 783 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; |
782 | rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); | 784 | rt2x00mmio_register_read(rt2x00dev, TXCSR3, ®); |
783 | rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, | 785 | rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, |
784 | entry_priv->desc_dma); | 786 | entry_priv->desc_dma); |
785 | rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); | 787 | rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg); |
786 | 788 | ||
787 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; | 789 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; |
788 | rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); | 790 | rt2x00mmio_register_read(rt2x00dev, TXCSR5, ®); |
789 | rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, | 791 | rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, |
790 | entry_priv->desc_dma); | 792 | entry_priv->desc_dma); |
791 | rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); | 793 | rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg); |
792 | 794 | ||
793 | entry_priv = rt2x00dev->atim->entries[0].priv_data; | 795 | entry_priv = rt2x00dev->atim->entries[0].priv_data; |
794 | rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); | 796 | rt2x00mmio_register_read(rt2x00dev, TXCSR4, ®); |
795 | rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, | 797 | rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, |
796 | entry_priv->desc_dma); | 798 | entry_priv->desc_dma); |
797 | rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); | 799 | rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg); |
798 | 800 | ||
799 | entry_priv = rt2x00dev->bcn->entries[0].priv_data; | 801 | entry_priv = rt2x00dev->bcn->entries[0].priv_data; |
800 | rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); | 802 | rt2x00mmio_register_read(rt2x00dev, TXCSR6, ®); |
801 | rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, | 803 | rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, |
802 | entry_priv->desc_dma); | 804 | entry_priv->desc_dma); |
803 | rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); | 805 | rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg); |
804 | 806 | ||
805 | rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); | 807 | rt2x00mmio_register_read(rt2x00dev, RXCSR1, ®); |
806 | rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); | 808 | rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); |
807 | rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); | 809 | rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); |
808 | rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); | 810 | rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg); |
809 | 811 | ||
810 | entry_priv = rt2x00dev->rx->entries[0].priv_data; | 812 | entry_priv = rt2x00dev->rx->entries[0].priv_data; |
811 | rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); | 813 | rt2x00mmio_register_read(rt2x00dev, RXCSR2, ®); |
812 | rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, | 814 | rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, |
813 | entry_priv->desc_dma); | 815 | entry_priv->desc_dma); |
814 | rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); | 816 | rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg); |
815 | 817 | ||
816 | return 0; | 818 | return 0; |
817 | } | 819 | } |
@@ -820,23 +822,23 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
820 | { | 822 | { |
821 | u32 reg; | 823 | u32 reg; |
822 | 824 | ||
823 | rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002); | 825 | rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002); |
824 | rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002); | 826 | rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002); |
825 | rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00023f20); | 827 | rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00023f20); |
826 | rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002); | 828 | rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002); |
827 | 829 | ||
828 | rt2x00pci_register_read(rt2x00dev, TIMECSR, ®); | 830 | rt2x00mmio_register_read(rt2x00dev, TIMECSR, ®); |
829 | rt2x00_set_field32(®, TIMECSR_US_COUNT, 33); | 831 | rt2x00_set_field32(®, TIMECSR_US_COUNT, 33); |
830 | rt2x00_set_field32(®, TIMECSR_US_64_COUNT, 63); | 832 | rt2x00_set_field32(®, TIMECSR_US_64_COUNT, 63); |
831 | rt2x00_set_field32(®, TIMECSR_BEACON_EXPECT, 0); | 833 | rt2x00_set_field32(®, TIMECSR_BEACON_EXPECT, 0); |
832 | rt2x00pci_register_write(rt2x00dev, TIMECSR, reg); | 834 | rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg); |
833 | 835 | ||
834 | rt2x00pci_register_read(rt2x00dev, CSR9, ®); | 836 | rt2x00mmio_register_read(rt2x00dev, CSR9, ®); |
835 | rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT, | 837 | rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT, |
836 | (rt2x00dev->rx->data_size / 128)); | 838 | (rt2x00dev->rx->data_size / 128)); |
837 | rt2x00pci_register_write(rt2x00dev, CSR9, reg); | 839 | rt2x00mmio_register_write(rt2x00dev, CSR9, reg); |
838 | 840 | ||
839 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 841 | rt2x00mmio_register_read(rt2x00dev, CSR14, ®); |
840 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); | 842 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); |
841 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); | 843 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); |
842 | rt2x00_set_field32(®, CSR14_TBCN, 0); | 844 | rt2x00_set_field32(®, CSR14_TBCN, 0); |
@@ -845,63 +847,63 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
845 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 847 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
846 | rt2x00_set_field32(®, CSR14_CFP_COUNT_PRELOAD, 0); | 848 | rt2x00_set_field32(®, CSR14_CFP_COUNT_PRELOAD, 0); |
847 | rt2x00_set_field32(®, CSR14_TBCM_PRELOAD, 0); | 849 | rt2x00_set_field32(®, CSR14_TBCM_PRELOAD, 0); |
848 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 850 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
849 | 851 | ||
850 | rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000); | 852 | rt2x00mmio_register_write(rt2x00dev, CNT3, 0x3f080000); |
851 | 853 | ||
852 | rt2x00pci_register_read(rt2x00dev, ARCSR0, ®); | 854 | rt2x00mmio_register_read(rt2x00dev, ARCSR0, ®); |
853 | rt2x00_set_field32(®, ARCSR0_AR_BBP_DATA0, 133); | 855 | rt2x00_set_field32(®, ARCSR0_AR_BBP_DATA0, 133); |
854 | rt2x00_set_field32(®, ARCSR0_AR_BBP_ID0, 134); | 856 | rt2x00_set_field32(®, ARCSR0_AR_BBP_ID0, 134); |
855 | rt2x00_set_field32(®, ARCSR0_AR_BBP_DATA1, 136); | 857 | rt2x00_set_field32(®, ARCSR0_AR_BBP_DATA1, 136); |
856 | rt2x00_set_field32(®, ARCSR0_AR_BBP_ID1, 135); | 858 | rt2x00_set_field32(®, ARCSR0_AR_BBP_ID1, 135); |
857 | rt2x00pci_register_write(rt2x00dev, ARCSR0, reg); | 859 | rt2x00mmio_register_write(rt2x00dev, ARCSR0, reg); |
858 | 860 | ||
859 | rt2x00pci_register_read(rt2x00dev, RXCSR3, ®); | 861 | rt2x00mmio_register_read(rt2x00dev, RXCSR3, ®); |
860 | rt2x00_set_field32(®, RXCSR3_BBP_ID0, 3); /* Tx power.*/ | 862 | rt2x00_set_field32(®, RXCSR3_BBP_ID0, 3); /* Tx power.*/ |
861 | rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1); | 863 | rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1); |
862 | rt2x00_set_field32(®, RXCSR3_BBP_ID1, 32); /* Signal */ | 864 | rt2x00_set_field32(®, RXCSR3_BBP_ID1, 32); /* Signal */ |
863 | rt2x00_set_field32(®, RXCSR3_BBP_ID1_VALID, 1); | 865 | rt2x00_set_field32(®, RXCSR3_BBP_ID1_VALID, 1); |
864 | rt2x00_set_field32(®, RXCSR3_BBP_ID2, 36); /* Rssi */ | 866 | rt2x00_set_field32(®, RXCSR3_BBP_ID2, 36); /* Rssi */ |
865 | rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1); | 867 | rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1); |
866 | rt2x00pci_register_write(rt2x00dev, RXCSR3, reg); | 868 | rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg); |
867 | 869 | ||
868 | rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); | 870 | rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); |
869 | 871 | ||
870 | if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) | 872 | if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) |
871 | return -EBUSY; | 873 | return -EBUSY; |
872 | 874 | ||
873 | rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00217223); | 875 | rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00217223); |
874 | rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518); | 876 | rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518); |
875 | 877 | ||
876 | rt2x00pci_register_read(rt2x00dev, MACCSR2, ®); | 878 | rt2x00mmio_register_read(rt2x00dev, MACCSR2, ®); |
877 | rt2x00_set_field32(®, MACCSR2_DELAY, 64); | 879 | rt2x00_set_field32(®, MACCSR2_DELAY, 64); |
878 | rt2x00pci_register_write(rt2x00dev, MACCSR2, reg); | 880 | rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg); |
879 | 881 | ||
880 | rt2x00pci_register_read(rt2x00dev, RALINKCSR, ®); | 882 | rt2x00mmio_register_read(rt2x00dev, RALINKCSR, ®); |
881 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17); | 883 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17); |
882 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 154); | 884 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 154); |
883 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA1, 0); | 885 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA1, 0); |
884 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 154); | 886 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 154); |
885 | rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg); | 887 | rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg); |
886 | 888 | ||
887 | rt2x00pci_register_read(rt2x00dev, CSR1, ®); | 889 | rt2x00mmio_register_read(rt2x00dev, CSR1, ®); |
888 | rt2x00_set_field32(®, CSR1_SOFT_RESET, 1); | 890 | rt2x00_set_field32(®, CSR1_SOFT_RESET, 1); |
889 | rt2x00_set_field32(®, CSR1_BBP_RESET, 0); | 891 | rt2x00_set_field32(®, CSR1_BBP_RESET, 0); |
890 | rt2x00_set_field32(®, CSR1_HOST_READY, 0); | 892 | rt2x00_set_field32(®, CSR1_HOST_READY, 0); |
891 | rt2x00pci_register_write(rt2x00dev, CSR1, reg); | 893 | rt2x00mmio_register_write(rt2x00dev, CSR1, reg); |
892 | 894 | ||
893 | rt2x00pci_register_read(rt2x00dev, CSR1, ®); | 895 | rt2x00mmio_register_read(rt2x00dev, CSR1, ®); |
894 | rt2x00_set_field32(®, CSR1_SOFT_RESET, 0); | 896 | rt2x00_set_field32(®, CSR1_SOFT_RESET, 0); |
895 | rt2x00_set_field32(®, CSR1_HOST_READY, 1); | 897 | rt2x00_set_field32(®, CSR1_HOST_READY, 1); |
896 | rt2x00pci_register_write(rt2x00dev, CSR1, reg); | 898 | rt2x00mmio_register_write(rt2x00dev, CSR1, reg); |
897 | 899 | ||
898 | /* | 900 | /* |
899 | * We must clear the FCS and FIFO error count. | 901 | * We must clear the FCS and FIFO error count. |
900 | * These registers are cleared on read, | 902 | * These registers are cleared on read, |
901 | * so we may pass a useless variable to store the value. | 903 | * so we may pass a useless variable to store the value. |
902 | */ | 904 | */ |
903 | rt2x00pci_register_read(rt2x00dev, CNT0, ®); | 905 | rt2x00mmio_register_read(rt2x00dev, CNT0, ®); |
904 | rt2x00pci_register_read(rt2x00dev, CNT4, ®); | 906 | rt2x00mmio_register_read(rt2x00dev, CNT4, ®); |
905 | 907 | ||
906 | return 0; | 908 | return 0; |
907 | } | 909 | } |
@@ -975,8 +977,8 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
975 | * should clear the register to assure a clean state. | 977 | * should clear the register to assure a clean state. |
976 | */ | 978 | */ |
977 | if (state == STATE_RADIO_IRQ_ON) { | 979 | if (state == STATE_RADIO_IRQ_ON) { |
978 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | 980 | rt2x00mmio_register_read(rt2x00dev, CSR7, ®); |
979 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | 981 | rt2x00mmio_register_write(rt2x00dev, CSR7, reg); |
980 | } | 982 | } |
981 | 983 | ||
982 | /* | 984 | /* |
@@ -985,13 +987,13 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
985 | */ | 987 | */ |
986 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | 988 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
987 | 989 | ||
988 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 990 | rt2x00mmio_register_read(rt2x00dev, CSR8, ®); |
989 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); | 991 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); |
990 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); | 992 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); |
991 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, mask); | 993 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, mask); |
992 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); | 994 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); |
993 | rt2x00_set_field32(®, CSR8_RXDONE, mask); | 995 | rt2x00_set_field32(®, CSR8_RXDONE, mask); |
994 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 996 | rt2x00mmio_register_write(rt2x00dev, CSR8, reg); |
995 | 997 | ||
996 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | 998 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
997 | 999 | ||
@@ -1024,7 +1026,7 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
1024 | /* | 1026 | /* |
1025 | * Disable power | 1027 | * Disable power |
1026 | */ | 1028 | */ |
1027 | rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); | 1029 | rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0); |
1028 | } | 1030 | } |
1029 | 1031 | ||
1030 | static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, | 1032 | static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, |
@@ -1038,12 +1040,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, | |||
1038 | 1040 | ||
1039 | put_to_sleep = (state != STATE_AWAKE); | 1041 | put_to_sleep = (state != STATE_AWAKE); |
1040 | 1042 | ||
1041 | rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); | 1043 | rt2x00mmio_register_read(rt2x00dev, PWRCSR1, ®); |
1042 | rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1); | 1044 | rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1); |
1043 | rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state); | 1045 | rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state); |
1044 | rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state); | 1046 | rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state); |
1045 | rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep); | 1047 | rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep); |
1046 | rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); | 1048 | rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg); |
1047 | 1049 | ||
1048 | /* | 1050 | /* |
1049 | * Device is not guaranteed to be in the requested state yet. | 1051 | * Device is not guaranteed to be in the requested state yet. |
@@ -1051,12 +1053,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, | |||
1051 | * device has entered the correct state. | 1053 | * device has entered the correct state. |
1052 | */ | 1054 | */ |
1053 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 1055 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
1054 | rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2); | 1056 | rt2x00mmio_register_read(rt2x00dev, PWRCSR1, ®2); |
1055 | bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE); | 1057 | bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE); |
1056 | rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE); | 1058 | rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE); |
1057 | if (bbp_state == state && rf_state == state) | 1059 | if (bbp_state == state && rf_state == state) |
1058 | return 0; | 1060 | return 0; |
1059 | rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); | 1061 | rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg); |
1060 | msleep(10); | 1062 | msleep(10); |
1061 | } | 1063 | } |
1062 | 1064 | ||
@@ -1104,7 +1106,7 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry, | |||
1104 | struct txentry_desc *txdesc) | 1106 | struct txentry_desc *txdesc) |
1105 | { | 1107 | { |
1106 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1108 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
1107 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1109 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
1108 | __le32 *txd = entry_priv->desc; | 1110 | __le32 *txd = entry_priv->desc; |
1109 | u32 word; | 1111 | u32 word; |
1110 | 1112 | ||
@@ -1181,9 +1183,9 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, | |||
1181 | * Disable beaconing while we are reloading the beacon data, | 1183 | * Disable beaconing while we are reloading the beacon data, |
1182 | * otherwise we might be sending out invalid data. | 1184 | * otherwise we might be sending out invalid data. |
1183 | */ | 1185 | */ |
1184 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 1186 | rt2x00mmio_register_read(rt2x00dev, CSR14, ®); |
1185 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 1187 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
1186 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 1188 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
1187 | 1189 | ||
1188 | if (rt2x00queue_map_txskb(entry)) { | 1190 | if (rt2x00queue_map_txskb(entry)) { |
1189 | ERROR(rt2x00dev, "Fail to map beacon, aborting\n"); | 1191 | ERROR(rt2x00dev, "Fail to map beacon, aborting\n"); |
@@ -1207,7 +1209,7 @@ out: | |||
1207 | * Enable beaconing again. | 1209 | * Enable beaconing again. |
1208 | */ | 1210 | */ |
1209 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); | 1211 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); |
1210 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 1212 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
1211 | } | 1213 | } |
1212 | 1214 | ||
1213 | /* | 1215 | /* |
@@ -1217,7 +1219,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, | |||
1217 | struct rxdone_entry_desc *rxdesc) | 1219 | struct rxdone_entry_desc *rxdesc) |
1218 | { | 1220 | { |
1219 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 1221 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
1220 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1222 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
1221 | u32 word0; | 1223 | u32 word0; |
1222 | u32 word2; | 1224 | u32 word2; |
1223 | u32 word3; | 1225 | u32 word3; |
@@ -1275,7 +1277,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1275 | const enum data_queue_qid queue_idx) | 1277 | const enum data_queue_qid queue_idx) |
1276 | { | 1278 | { |
1277 | struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx); | 1279 | struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx); |
1278 | struct queue_entry_priv_pci *entry_priv; | 1280 | struct queue_entry_priv_mmio *entry_priv; |
1279 | struct queue_entry *entry; | 1281 | struct queue_entry *entry; |
1280 | struct txdone_entry_desc txdesc; | 1282 | struct txdone_entry_desc txdesc; |
1281 | u32 word; | 1283 | u32 word; |
@@ -1321,9 +1323,9 @@ static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, | |||
1321 | */ | 1323 | */ |
1322 | spin_lock_irq(&rt2x00dev->irqmask_lock); | 1324 | spin_lock_irq(&rt2x00dev->irqmask_lock); |
1323 | 1325 | ||
1324 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 1326 | rt2x00mmio_register_read(rt2x00dev, CSR8, ®); |
1325 | rt2x00_set_field32(®, irq_field, 0); | 1327 | rt2x00_set_field32(®, irq_field, 0); |
1326 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1328 | rt2x00mmio_register_write(rt2x00dev, CSR8, reg); |
1327 | 1329 | ||
1328 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | 1330 | spin_unlock_irq(&rt2x00dev->irqmask_lock); |
1329 | } | 1331 | } |
@@ -1346,11 +1348,11 @@ static void rt2400pci_txstatus_tasklet(unsigned long data) | |||
1346 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) { | 1348 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) { |
1347 | spin_lock_irq(&rt2x00dev->irqmask_lock); | 1349 | spin_lock_irq(&rt2x00dev->irqmask_lock); |
1348 | 1350 | ||
1349 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 1351 | rt2x00mmio_register_read(rt2x00dev, CSR8, ®); |
1350 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); | 1352 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); |
1351 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); | 1353 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); |
1352 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); | 1354 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); |
1353 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1355 | rt2x00mmio_register_write(rt2x00dev, CSR8, reg); |
1354 | 1356 | ||
1355 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | 1357 | spin_unlock_irq(&rt2x00dev->irqmask_lock); |
1356 | } | 1358 | } |
@@ -1367,7 +1369,7 @@ static void rt2400pci_tbtt_tasklet(unsigned long data) | |||
1367 | static void rt2400pci_rxdone_tasklet(unsigned long data) | 1369 | static void rt2400pci_rxdone_tasklet(unsigned long data) |
1368 | { | 1370 | { |
1369 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | 1371 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
1370 | if (rt2x00pci_rxdone(rt2x00dev)) | 1372 | if (rt2x00mmio_rxdone(rt2x00dev)) |
1371 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | 1373 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); |
1372 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 1374 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
1373 | rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); | 1375 | rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); |
@@ -1382,8 +1384,8 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) | |||
1382 | * Get the interrupt sources & saved to local variable. | 1384 | * Get the interrupt sources & saved to local variable. |
1383 | * Write register value back to clear pending interrupts. | 1385 | * Write register value back to clear pending interrupts. |
1384 | */ | 1386 | */ |
1385 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | 1387 | rt2x00mmio_register_read(rt2x00dev, CSR7, ®); |
1386 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | 1388 | rt2x00mmio_register_write(rt2x00dev, CSR7, reg); |
1387 | 1389 | ||
1388 | if (!reg) | 1390 | if (!reg) |
1389 | return IRQ_NONE; | 1391 | return IRQ_NONE; |
@@ -1420,9 +1422,9 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) | |||
1420 | */ | 1422 | */ |
1421 | spin_lock(&rt2x00dev->irqmask_lock); | 1423 | spin_lock(&rt2x00dev->irqmask_lock); |
1422 | 1424 | ||
1423 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 1425 | rt2x00mmio_register_read(rt2x00dev, CSR8, ®); |
1424 | reg |= mask; | 1426 | reg |= mask; |
1425 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1427 | rt2x00mmio_register_write(rt2x00dev, CSR8, reg); |
1426 | 1428 | ||
1427 | spin_unlock(&rt2x00dev->irqmask_lock); | 1429 | spin_unlock(&rt2x00dev->irqmask_lock); |
1428 | 1430 | ||
@@ -1441,7 +1443,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1441 | u16 word; | 1443 | u16 word; |
1442 | u8 *mac; | 1444 | u8 *mac; |
1443 | 1445 | ||
1444 | rt2x00pci_register_read(rt2x00dev, CSR21, ®); | 1446 | rt2x00mmio_register_read(rt2x00dev, CSR21, ®); |
1445 | 1447 | ||
1446 | eeprom.data = rt2x00dev; | 1448 | eeprom.data = rt2x00dev; |
1447 | eeprom.register_read = rt2400pci_eepromregister_read; | 1449 | eeprom.register_read = rt2400pci_eepromregister_read; |
@@ -1489,7 +1491,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1489 | * Identify RF chipset. | 1491 | * Identify RF chipset. |
1490 | */ | 1492 | */ |
1491 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1493 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1492 | rt2x00pci_register_read(rt2x00dev, CSR0, ®); | 1494 | rt2x00mmio_register_read(rt2x00dev, CSR0, ®); |
1493 | rt2x00_set_chip(rt2x00dev, RT2460, value, | 1495 | rt2x00_set_chip(rt2x00dev, RT2460, value, |
1494 | rt2x00_get_field32(reg, CSR0_REVISION)); | 1496 | rt2x00_get_field32(reg, CSR0_REVISION)); |
1495 | 1497 | ||
@@ -1634,9 +1636,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1634 | * Enable rfkill polling by setting GPIO direction of the | 1636 | * Enable rfkill polling by setting GPIO direction of the |
1635 | * rfkill switch GPIO pin correctly. | 1637 | * rfkill switch GPIO pin correctly. |
1636 | */ | 1638 | */ |
1637 | rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); | 1639 | rt2x00mmio_register_read(rt2x00dev, GPIOCSR, ®); |
1638 | rt2x00_set_field32(®, GPIOCSR_DIR0, 1); | 1640 | rt2x00_set_field32(®, GPIOCSR_DIR0, 1); |
1639 | rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); | 1641 | rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg); |
1640 | 1642 | ||
1641 | /* | 1643 | /* |
1642 | * Initialize hw specifications. | 1644 | * Initialize hw specifications. |
@@ -1696,9 +1698,9 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw, | |||
1696 | u64 tsf; | 1698 | u64 tsf; |
1697 | u32 reg; | 1699 | u32 reg; |
1698 | 1700 | ||
1699 | rt2x00pci_register_read(rt2x00dev, CSR17, ®); | 1701 | rt2x00mmio_register_read(rt2x00dev, CSR17, ®); |
1700 | tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; | 1702 | tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; |
1701 | rt2x00pci_register_read(rt2x00dev, CSR16, ®); | 1703 | rt2x00mmio_register_read(rt2x00dev, CSR16, ®); |
1702 | tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER); | 1704 | tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER); |
1703 | 1705 | ||
1704 | return tsf; | 1706 | return tsf; |
@@ -1709,7 +1711,7 @@ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) | |||
1709 | struct rt2x00_dev *rt2x00dev = hw->priv; | 1711 | struct rt2x00_dev *rt2x00dev = hw->priv; |
1710 | u32 reg; | 1712 | u32 reg; |
1711 | 1713 | ||
1712 | rt2x00pci_register_read(rt2x00dev, CSR15, ®); | 1714 | rt2x00mmio_register_read(rt2x00dev, CSR15, ®); |
1713 | return rt2x00_get_field32(reg, CSR15_BEACON_SENT); | 1715 | return rt2x00_get_field32(reg, CSR15_BEACON_SENT); |
1714 | } | 1716 | } |
1715 | 1717 | ||
@@ -1742,8 +1744,8 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { | |||
1742 | .tbtt_tasklet = rt2400pci_tbtt_tasklet, | 1744 | .tbtt_tasklet = rt2400pci_tbtt_tasklet, |
1743 | .rxdone_tasklet = rt2400pci_rxdone_tasklet, | 1745 | .rxdone_tasklet = rt2400pci_rxdone_tasklet, |
1744 | .probe_hw = rt2400pci_probe_hw, | 1746 | .probe_hw = rt2400pci_probe_hw, |
1745 | .initialize = rt2x00pci_initialize, | 1747 | .initialize = rt2x00mmio_initialize, |
1746 | .uninitialize = rt2x00pci_uninitialize, | 1748 | .uninitialize = rt2x00mmio_uninitialize, |
1747 | .get_entry_state = rt2400pci_get_entry_state, | 1749 | .get_entry_state = rt2400pci_get_entry_state, |
1748 | .clear_entry = rt2400pci_clear_entry, | 1750 | .clear_entry = rt2400pci_clear_entry, |
1749 | .set_device_state = rt2400pci_set_device_state, | 1751 | .set_device_state = rt2400pci_set_device_state, |
@@ -1754,7 +1756,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { | |||
1754 | .start_queue = rt2400pci_start_queue, | 1756 | .start_queue = rt2400pci_start_queue, |
1755 | .kick_queue = rt2400pci_kick_queue, | 1757 | .kick_queue = rt2400pci_kick_queue, |
1756 | .stop_queue = rt2400pci_stop_queue, | 1758 | .stop_queue = rt2400pci_stop_queue, |
1757 | .flush_queue = rt2x00pci_flush_queue, | 1759 | .flush_queue = rt2x00mmio_flush_queue, |
1758 | .write_tx_desc = rt2400pci_write_tx_desc, | 1760 | .write_tx_desc = rt2400pci_write_tx_desc, |
1759 | .write_beacon = rt2400pci_write_beacon, | 1761 | .write_beacon = rt2400pci_write_beacon, |
1760 | .fill_rxdone = rt2400pci_fill_rxdone, | 1762 | .fill_rxdone = rt2400pci_fill_rxdone, |
@@ -1769,28 +1771,28 @@ static const struct data_queue_desc rt2400pci_queue_rx = { | |||
1769 | .entry_num = 24, | 1771 | .entry_num = 24, |
1770 | .data_size = DATA_FRAME_SIZE, | 1772 | .data_size = DATA_FRAME_SIZE, |
1771 | .desc_size = RXD_DESC_SIZE, | 1773 | .desc_size = RXD_DESC_SIZE, |
1772 | .priv_size = sizeof(struct queue_entry_priv_pci), | 1774 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
1773 | }; | 1775 | }; |
1774 | 1776 | ||
1775 | static const struct data_queue_desc rt2400pci_queue_tx = { | 1777 | static const struct data_queue_desc rt2400pci_queue_tx = { |
1776 | .entry_num = 24, | 1778 | .entry_num = 24, |
1777 | .data_size = DATA_FRAME_SIZE, | 1779 | .data_size = DATA_FRAME_SIZE, |
1778 | .desc_size = TXD_DESC_SIZE, | 1780 | .desc_size = TXD_DESC_SIZE, |
1779 | .priv_size = sizeof(struct queue_entry_priv_pci), | 1781 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
1780 | }; | 1782 | }; |
1781 | 1783 | ||
1782 | static const struct data_queue_desc rt2400pci_queue_bcn = { | 1784 | static const struct data_queue_desc rt2400pci_queue_bcn = { |
1783 | .entry_num = 1, | 1785 | .entry_num = 1, |
1784 | .data_size = MGMT_FRAME_SIZE, | 1786 | .data_size = MGMT_FRAME_SIZE, |
1785 | .desc_size = TXD_DESC_SIZE, | 1787 | .desc_size = TXD_DESC_SIZE, |
1786 | .priv_size = sizeof(struct queue_entry_priv_pci), | 1788 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
1787 | }; | 1789 | }; |
1788 | 1790 | ||
1789 | static const struct data_queue_desc rt2400pci_queue_atim = { | 1791 | static const struct data_queue_desc rt2400pci_queue_atim = { |
1790 | .entry_num = 8, | 1792 | .entry_num = 8, |
1791 | .data_size = DATA_FRAME_SIZE, | 1793 | .data_size = DATA_FRAME_SIZE, |
1792 | .desc_size = TXD_DESC_SIZE, | 1794 | .desc_size = TXD_DESC_SIZE, |
1793 | .priv_size = sizeof(struct queue_entry_priv_pci), | 1795 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
1794 | }; | 1796 | }; |
1795 | 1797 | ||
1796 | static const struct rt2x00_ops rt2400pci_ops = { | 1798 | static const struct rt2x00_ops rt2400pci_ops = { |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 39edc59e8d03..9ba14570fcfd 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -34,13 +34,14 @@ | |||
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | 35 | ||
36 | #include "rt2x00.h" | 36 | #include "rt2x00.h" |
37 | #include "rt2x00mmio.h" | ||
37 | #include "rt2x00pci.h" | 38 | #include "rt2x00pci.h" |
38 | #include "rt2500pci.h" | 39 | #include "rt2500pci.h" |
39 | 40 | ||
40 | /* | 41 | /* |
41 | * Register access. | 42 | * Register access. |
42 | * All access to the CSR registers will go through the methods | 43 | * All access to the CSR registers will go through the methods |
43 | * rt2x00pci_register_read and rt2x00pci_register_write. | 44 | * rt2x00mmio_register_read and rt2x00mmio_register_write. |
44 | * BBP and RF register require indirect register access, | 45 | * BBP and RF register require indirect register access, |
45 | * and use the CSR registers BBPCSR and RFCSR to achieve this. | 46 | * and use the CSR registers BBPCSR and RFCSR to achieve this. |
46 | * These indirect registers work with busy bits, | 47 | * These indirect registers work with busy bits, |
@@ -51,9 +52,9 @@ | |||
51 | * and we will print an error. | 52 | * and we will print an error. |
52 | */ | 53 | */ |
53 | #define WAIT_FOR_BBP(__dev, __reg) \ | 54 | #define WAIT_FOR_BBP(__dev, __reg) \ |
54 | rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) | 55 | rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) |
55 | #define WAIT_FOR_RF(__dev, __reg) \ | 56 | #define WAIT_FOR_RF(__dev, __reg) \ |
56 | rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) | 57 | rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) |
57 | 58 | ||
58 | static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, | 59 | static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, |
59 | const unsigned int word, const u8 value) | 60 | const unsigned int word, const u8 value) |
@@ -73,7 +74,7 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
73 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); | 74 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); |
74 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); | 75 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); |
75 | 76 | ||
76 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); | 77 | rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg); |
77 | } | 78 | } |
78 | 79 | ||
79 | mutex_unlock(&rt2x00dev->csr_mutex); | 80 | mutex_unlock(&rt2x00dev->csr_mutex); |
@@ -100,7 +101,7 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
100 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); | 101 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); |
101 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); | 102 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); |
102 | 103 | ||
103 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); | 104 | rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg); |
104 | 105 | ||
105 | WAIT_FOR_BBP(rt2x00dev, ®); | 106 | WAIT_FOR_BBP(rt2x00dev, ®); |
106 | } | 107 | } |
@@ -128,7 +129,7 @@ static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, | |||
128 | rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); | 129 | rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); |
129 | rt2x00_set_field32(®, RFCSR_BUSY, 1); | 130 | rt2x00_set_field32(®, RFCSR_BUSY, 1); |
130 | 131 | ||
131 | rt2x00pci_register_write(rt2x00dev, RFCSR, reg); | 132 | rt2x00mmio_register_write(rt2x00dev, RFCSR, reg); |
132 | rt2x00_rf_write(rt2x00dev, word, value); | 133 | rt2x00_rf_write(rt2x00dev, word, value); |
133 | } | 134 | } |
134 | 135 | ||
@@ -140,7 +141,7 @@ static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | |||
140 | struct rt2x00_dev *rt2x00dev = eeprom->data; | 141 | struct rt2x00_dev *rt2x00dev = eeprom->data; |
141 | u32 reg; | 142 | u32 reg; |
142 | 143 | ||
143 | rt2x00pci_register_read(rt2x00dev, CSR21, ®); | 144 | rt2x00mmio_register_read(rt2x00dev, CSR21, ®); |
144 | 145 | ||
145 | eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN); | 146 | eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN); |
146 | eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT); | 147 | eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT); |
@@ -162,15 +163,15 @@ static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom) | |||
162 | rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT, | 163 | rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT, |
163 | !!eeprom->reg_chip_select); | 164 | !!eeprom->reg_chip_select); |
164 | 165 | ||
165 | rt2x00pci_register_write(rt2x00dev, CSR21, reg); | 166 | rt2x00mmio_register_write(rt2x00dev, CSR21, reg); |
166 | } | 167 | } |
167 | 168 | ||
168 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 169 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
169 | static const struct rt2x00debug rt2500pci_rt2x00debug = { | 170 | static const struct rt2x00debug rt2500pci_rt2x00debug = { |
170 | .owner = THIS_MODULE, | 171 | .owner = THIS_MODULE, |
171 | .csr = { | 172 | .csr = { |
172 | .read = rt2x00pci_register_read, | 173 | .read = rt2x00mmio_register_read, |
173 | .write = rt2x00pci_register_write, | 174 | .write = rt2x00mmio_register_write, |
174 | .flags = RT2X00DEBUGFS_OFFSET, | 175 | .flags = RT2X00DEBUGFS_OFFSET, |
175 | .word_base = CSR_REG_BASE, | 176 | .word_base = CSR_REG_BASE, |
176 | .word_size = sizeof(u32), | 177 | .word_size = sizeof(u32), |
@@ -204,7 +205,7 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) | |||
204 | { | 205 | { |
205 | u32 reg; | 206 | u32 reg; |
206 | 207 | ||
207 | rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); | 208 | rt2x00mmio_register_read(rt2x00dev, GPIOCSR, ®); |
208 | return rt2x00_get_field32(reg, GPIOCSR_VAL0); | 209 | return rt2x00_get_field32(reg, GPIOCSR_VAL0); |
209 | } | 210 | } |
210 | 211 | ||
@@ -217,14 +218,14 @@ static void rt2500pci_brightness_set(struct led_classdev *led_cdev, | |||
217 | unsigned int enabled = brightness != LED_OFF; | 218 | unsigned int enabled = brightness != LED_OFF; |
218 | u32 reg; | 219 | u32 reg; |
219 | 220 | ||
220 | rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); | 221 | rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, ®); |
221 | 222 | ||
222 | if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) | 223 | if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) |
223 | rt2x00_set_field32(®, LEDCSR_LINK, enabled); | 224 | rt2x00_set_field32(®, LEDCSR_LINK, enabled); |
224 | else if (led->type == LED_TYPE_ACTIVITY) | 225 | else if (led->type == LED_TYPE_ACTIVITY) |
225 | rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); | 226 | rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); |
226 | 227 | ||
227 | rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); | 228 | rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg); |
228 | } | 229 | } |
229 | 230 | ||
230 | static int rt2500pci_blink_set(struct led_classdev *led_cdev, | 231 | static int rt2500pci_blink_set(struct led_classdev *led_cdev, |
@@ -235,10 +236,10 @@ static int rt2500pci_blink_set(struct led_classdev *led_cdev, | |||
235 | container_of(led_cdev, struct rt2x00_led, led_dev); | 236 | container_of(led_cdev, struct rt2x00_led, led_dev); |
236 | u32 reg; | 237 | u32 reg; |
237 | 238 | ||
238 | rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); | 239 | rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, ®); |
239 | rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on); | 240 | rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on); |
240 | rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); | 241 | rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); |
241 | rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); | 242 | rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg); |
242 | 243 | ||
243 | return 0; | 244 | return 0; |
244 | } | 245 | } |
@@ -269,7 +270,7 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev, | |||
269 | * and broadcast frames will always be accepted since | 270 | * and broadcast frames will always be accepted since |
270 | * there is no filter for it at this time. | 271 | * there is no filter for it at this time. |
271 | */ | 272 | */ |
272 | rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); | 273 | rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®); |
273 | rt2x00_set_field32(®, RXCSR0_DROP_CRC, | 274 | rt2x00_set_field32(®, RXCSR0_DROP_CRC, |
274 | !(filter_flags & FIF_FCSFAIL)); | 275 | !(filter_flags & FIF_FCSFAIL)); |
275 | rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, | 276 | rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, |
@@ -285,7 +286,7 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev, | |||
285 | rt2x00_set_field32(®, RXCSR0_DROP_MCAST, | 286 | rt2x00_set_field32(®, RXCSR0_DROP_MCAST, |
286 | !(filter_flags & FIF_ALLMULTI)); | 287 | !(filter_flags & FIF_ALLMULTI)); |
287 | rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); | 288 | rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); |
288 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | 289 | rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); |
289 | } | 290 | } |
290 | 291 | ||
291 | static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, | 292 | static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, |
@@ -302,25 +303,25 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
302 | * Enable beacon config | 303 | * Enable beacon config |
303 | */ | 304 | */ |
304 | bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); | 305 | bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); |
305 | rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); | 306 | rt2x00mmio_register_read(rt2x00dev, BCNCSR1, ®); |
306 | rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); | 307 | rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); |
307 | rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); | 308 | rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); |
308 | rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); | 309 | rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg); |
309 | 310 | ||
310 | /* | 311 | /* |
311 | * Enable synchronisation. | 312 | * Enable synchronisation. |
312 | */ | 313 | */ |
313 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 314 | rt2x00mmio_register_read(rt2x00dev, CSR14, ®); |
314 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); | 315 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); |
315 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 316 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
316 | } | 317 | } |
317 | 318 | ||
318 | if (flags & CONFIG_UPDATE_MAC) | 319 | if (flags & CONFIG_UPDATE_MAC) |
319 | rt2x00pci_register_multiwrite(rt2x00dev, CSR3, | 320 | rt2x00mmio_register_multiwrite(rt2x00dev, CSR3, |
320 | conf->mac, sizeof(conf->mac)); | 321 | conf->mac, sizeof(conf->mac)); |
321 | 322 | ||
322 | if (flags & CONFIG_UPDATE_BSSID) | 323 | if (flags & CONFIG_UPDATE_BSSID) |
323 | rt2x00pci_register_multiwrite(rt2x00dev, CSR5, | 324 | rt2x00mmio_register_multiwrite(rt2x00dev, CSR5, |
324 | conf->bssid, sizeof(conf->bssid)); | 325 | conf->bssid, sizeof(conf->bssid)); |
325 | } | 326 | } |
326 | 327 | ||
@@ -337,68 +338,68 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, | |||
337 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 338 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
338 | preamble_mask = erp->short_preamble << 3; | 339 | preamble_mask = erp->short_preamble << 3; |
339 | 340 | ||
340 | rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); | 341 | rt2x00mmio_register_read(rt2x00dev, TXCSR1, ®); |
341 | rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x162); | 342 | rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x162); |
342 | rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0xa2); | 343 | rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0xa2); |
343 | rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); | 344 | rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); |
344 | rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); | 345 | rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); |
345 | rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); | 346 | rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg); |
346 | 347 | ||
347 | rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); | 348 | rt2x00mmio_register_read(rt2x00dev, ARCSR2, ®); |
348 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); | 349 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); |
349 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); | 350 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); |
350 | rt2x00_set_field32(®, ARCSR2_LENGTH, | 351 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
351 | GET_DURATION(ACK_SIZE, 10)); | 352 | GET_DURATION(ACK_SIZE, 10)); |
352 | rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); | 353 | rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg); |
353 | 354 | ||
354 | rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); | 355 | rt2x00mmio_register_read(rt2x00dev, ARCSR3, ®); |
355 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); | 356 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); |
356 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); | 357 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); |
357 | rt2x00_set_field32(®, ARCSR2_LENGTH, | 358 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
358 | GET_DURATION(ACK_SIZE, 20)); | 359 | GET_DURATION(ACK_SIZE, 20)); |
359 | rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); | 360 | rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg); |
360 | 361 | ||
361 | rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); | 362 | rt2x00mmio_register_read(rt2x00dev, ARCSR4, ®); |
362 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); | 363 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); |
363 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); | 364 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); |
364 | rt2x00_set_field32(®, ARCSR2_LENGTH, | 365 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
365 | GET_DURATION(ACK_SIZE, 55)); | 366 | GET_DURATION(ACK_SIZE, 55)); |
366 | rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); | 367 | rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg); |
367 | 368 | ||
368 | rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); | 369 | rt2x00mmio_register_read(rt2x00dev, ARCSR5, ®); |
369 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); | 370 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); |
370 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); | 371 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); |
371 | rt2x00_set_field32(®, ARCSR2_LENGTH, | 372 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
372 | GET_DURATION(ACK_SIZE, 110)); | 373 | GET_DURATION(ACK_SIZE, 110)); |
373 | rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); | 374 | rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg); |
374 | } | 375 | } |
375 | 376 | ||
376 | if (changed & BSS_CHANGED_BASIC_RATES) | 377 | if (changed & BSS_CHANGED_BASIC_RATES) |
377 | rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); | 378 | rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates); |
378 | 379 | ||
379 | if (changed & BSS_CHANGED_ERP_SLOT) { | 380 | if (changed & BSS_CHANGED_ERP_SLOT) { |
380 | rt2x00pci_register_read(rt2x00dev, CSR11, ®); | 381 | rt2x00mmio_register_read(rt2x00dev, CSR11, ®); |
381 | rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); | 382 | rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); |
382 | rt2x00pci_register_write(rt2x00dev, CSR11, reg); | 383 | rt2x00mmio_register_write(rt2x00dev, CSR11, reg); |
383 | 384 | ||
384 | rt2x00pci_register_read(rt2x00dev, CSR18, ®); | 385 | rt2x00mmio_register_read(rt2x00dev, CSR18, ®); |
385 | rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); | 386 | rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); |
386 | rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); | 387 | rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); |
387 | rt2x00pci_register_write(rt2x00dev, CSR18, reg); | 388 | rt2x00mmio_register_write(rt2x00dev, CSR18, reg); |
388 | 389 | ||
389 | rt2x00pci_register_read(rt2x00dev, CSR19, ®); | 390 | rt2x00mmio_register_read(rt2x00dev, CSR19, ®); |
390 | rt2x00_set_field32(®, CSR19_DIFS, erp->difs); | 391 | rt2x00_set_field32(®, CSR19_DIFS, erp->difs); |
391 | rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); | 392 | rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); |
392 | rt2x00pci_register_write(rt2x00dev, CSR19, reg); | 393 | rt2x00mmio_register_write(rt2x00dev, CSR19, reg); |
393 | } | 394 | } |
394 | 395 | ||
395 | if (changed & BSS_CHANGED_BEACON_INT) { | 396 | if (changed & BSS_CHANGED_BEACON_INT) { |
396 | rt2x00pci_register_read(rt2x00dev, CSR12, ®); | 397 | rt2x00mmio_register_read(rt2x00dev, CSR12, ®); |
397 | rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, | 398 | rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, |
398 | erp->beacon_int * 16); | 399 | erp->beacon_int * 16); |
399 | rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, | 400 | rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, |
400 | erp->beacon_int * 16); | 401 | erp->beacon_int * 16); |
401 | rt2x00pci_register_write(rt2x00dev, CSR12, reg); | 402 | rt2x00mmio_register_write(rt2x00dev, CSR12, reg); |
402 | } | 403 | } |
403 | 404 | ||
404 | } | 405 | } |
@@ -417,7 +418,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
417 | BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || | 418 | BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || |
418 | ant->tx == ANTENNA_SW_DIVERSITY); | 419 | ant->tx == ANTENNA_SW_DIVERSITY); |
419 | 420 | ||
420 | rt2x00pci_register_read(rt2x00dev, BBPCSR1, ®); | 421 | rt2x00mmio_register_read(rt2x00dev, BBPCSR1, ®); |
421 | rt2500pci_bbp_read(rt2x00dev, 14, &r14); | 422 | rt2500pci_bbp_read(rt2x00dev, 14, &r14); |
422 | rt2500pci_bbp_read(rt2x00dev, 2, &r2); | 423 | rt2500pci_bbp_read(rt2x00dev, 2, &r2); |
423 | 424 | ||
@@ -469,7 +470,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
469 | rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 0); | 470 | rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 0); |
470 | } | 471 | } |
471 | 472 | ||
472 | rt2x00pci_register_write(rt2x00dev, BBPCSR1, reg); | 473 | rt2x00mmio_register_write(rt2x00dev, BBPCSR1, reg); |
473 | rt2500pci_bbp_write(rt2x00dev, 14, r14); | 474 | rt2500pci_bbp_write(rt2x00dev, 14, r14); |
474 | rt2500pci_bbp_write(rt2x00dev, 2, r2); | 475 | rt2500pci_bbp_write(rt2x00dev, 2, r2); |
475 | } | 476 | } |
@@ -540,7 +541,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
540 | /* | 541 | /* |
541 | * Clear false CRC during channel switch. | 542 | * Clear false CRC during channel switch. |
542 | */ | 543 | */ |
543 | rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1); | 544 | rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1); |
544 | } | 545 | } |
545 | 546 | ||
546 | static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev, | 547 | static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev, |
@@ -558,12 +559,12 @@ static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |||
558 | { | 559 | { |
559 | u32 reg; | 560 | u32 reg; |
560 | 561 | ||
561 | rt2x00pci_register_read(rt2x00dev, CSR11, ®); | 562 | rt2x00mmio_register_read(rt2x00dev, CSR11, ®); |
562 | rt2x00_set_field32(®, CSR11_LONG_RETRY, | 563 | rt2x00_set_field32(®, CSR11_LONG_RETRY, |
563 | libconf->conf->long_frame_max_tx_count); | 564 | libconf->conf->long_frame_max_tx_count); |
564 | rt2x00_set_field32(®, CSR11_SHORT_RETRY, | 565 | rt2x00_set_field32(®, CSR11_SHORT_RETRY, |
565 | libconf->conf->short_frame_max_tx_count); | 566 | libconf->conf->short_frame_max_tx_count); |
566 | rt2x00pci_register_write(rt2x00dev, CSR11, reg); | 567 | rt2x00mmio_register_write(rt2x00dev, CSR11, reg); |
567 | } | 568 | } |
568 | 569 | ||
569 | static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, | 570 | static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, |
@@ -575,7 +576,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, | |||
575 | u32 reg; | 576 | u32 reg; |
576 | 577 | ||
577 | if (state == STATE_SLEEP) { | 578 | if (state == STATE_SLEEP) { |
578 | rt2x00pci_register_read(rt2x00dev, CSR20, ®); | 579 | rt2x00mmio_register_read(rt2x00dev, CSR20, ®); |
579 | rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, | 580 | rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, |
580 | (rt2x00dev->beacon_int - 20) * 16); | 581 | (rt2x00dev->beacon_int - 20) * 16); |
581 | rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, | 582 | rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, |
@@ -583,14 +584,14 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, | |||
583 | 584 | ||
584 | /* We must first disable autowake before it can be enabled */ | 585 | /* We must first disable autowake before it can be enabled */ |
585 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); | 586 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); |
586 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | 587 | rt2x00mmio_register_write(rt2x00dev, CSR20, reg); |
587 | 588 | ||
588 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); | 589 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); |
589 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | 590 | rt2x00mmio_register_write(rt2x00dev, CSR20, reg); |
590 | } else { | 591 | } else { |
591 | rt2x00pci_register_read(rt2x00dev, CSR20, ®); | 592 | rt2x00mmio_register_read(rt2x00dev, CSR20, ®); |
592 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); | 593 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); |
593 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | 594 | rt2x00mmio_register_write(rt2x00dev, CSR20, reg); |
594 | } | 595 | } |
595 | 596 | ||
596 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | 597 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); |
@@ -624,13 +625,13 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev, | |||
624 | /* | 625 | /* |
625 | * Update FCS error count from register. | 626 | * Update FCS error count from register. |
626 | */ | 627 | */ |
627 | rt2x00pci_register_read(rt2x00dev, CNT0, ®); | 628 | rt2x00mmio_register_read(rt2x00dev, CNT0, ®); |
628 | qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); | 629 | qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); |
629 | 630 | ||
630 | /* | 631 | /* |
631 | * Update False CCA count from register. | 632 | * Update False CCA count from register. |
632 | */ | 633 | */ |
633 | rt2x00pci_register_read(rt2x00dev, CNT3, ®); | 634 | rt2x00mmio_register_read(rt2x00dev, CNT3, ®); |
634 | qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); | 635 | qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); |
635 | } | 636 | } |
636 | 637 | ||
@@ -730,16 +731,16 @@ static void rt2500pci_start_queue(struct data_queue *queue) | |||
730 | 731 | ||
731 | switch (queue->qid) { | 732 | switch (queue->qid) { |
732 | case QID_RX: | 733 | case QID_RX: |
733 | rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); | 734 | rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®); |
734 | rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); | 735 | rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); |
735 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | 736 | rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); |
736 | break; | 737 | break; |
737 | case QID_BEACON: | 738 | case QID_BEACON: |
738 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 739 | rt2x00mmio_register_read(rt2x00dev, CSR14, ®); |
739 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | 740 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); |
740 | rt2x00_set_field32(®, CSR14_TBCN, 1); | 741 | rt2x00_set_field32(®, CSR14_TBCN, 1); |
741 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); | 742 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); |
742 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 743 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
743 | break; | 744 | break; |
744 | default: | 745 | default: |
745 | break; | 746 | break; |
@@ -753,19 +754,19 @@ static void rt2500pci_kick_queue(struct data_queue *queue) | |||
753 | 754 | ||
754 | switch (queue->qid) { | 755 | switch (queue->qid) { |
755 | case QID_AC_VO: | 756 | case QID_AC_VO: |
756 | rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); | 757 | rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); |
757 | rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); | 758 | rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); |
758 | rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); | 759 | rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); |
759 | break; | 760 | break; |
760 | case QID_AC_VI: | 761 | case QID_AC_VI: |
761 | rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); | 762 | rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); |
762 | rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); | 763 | rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); |
763 | rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); | 764 | rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); |
764 | break; | 765 | break; |
765 | case QID_ATIM: | 766 | case QID_ATIM: |
766 | rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); | 767 | rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); |
767 | rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); | 768 | rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); |
768 | rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); | 769 | rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); |
769 | break; | 770 | break; |
770 | default: | 771 | default: |
771 | break; | 772 | break; |
@@ -781,21 +782,21 @@ static void rt2500pci_stop_queue(struct data_queue *queue) | |||
781 | case QID_AC_VO: | 782 | case QID_AC_VO: |
782 | case QID_AC_VI: | 783 | case QID_AC_VI: |
783 | case QID_ATIM: | 784 | case QID_ATIM: |
784 | rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); | 785 | rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); |
785 | rt2x00_set_field32(®, TXCSR0_ABORT, 1); | 786 | rt2x00_set_field32(®, TXCSR0_ABORT, 1); |
786 | rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); | 787 | rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); |
787 | break; | 788 | break; |
788 | case QID_RX: | 789 | case QID_RX: |
789 | rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); | 790 | rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®); |
790 | rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); | 791 | rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); |
791 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | 792 | rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); |
792 | break; | 793 | break; |
793 | case QID_BEACON: | 794 | case QID_BEACON: |
794 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 795 | rt2x00mmio_register_read(rt2x00dev, CSR14, ®); |
795 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); | 796 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); |
796 | rt2x00_set_field32(®, CSR14_TBCN, 0); | 797 | rt2x00_set_field32(®, CSR14_TBCN, 0); |
797 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 798 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
798 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 799 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
799 | 800 | ||
800 | /* | 801 | /* |
801 | * Wait for possibly running tbtt tasklets. | 802 | * Wait for possibly running tbtt tasklets. |
@@ -812,7 +813,7 @@ static void rt2500pci_stop_queue(struct data_queue *queue) | |||
812 | */ | 813 | */ |
813 | static bool rt2500pci_get_entry_state(struct queue_entry *entry) | 814 | static bool rt2500pci_get_entry_state(struct queue_entry *entry) |
814 | { | 815 | { |
815 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 816 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
816 | u32 word; | 817 | u32 word; |
817 | 818 | ||
818 | if (entry->queue->qid == QID_RX) { | 819 | if (entry->queue->qid == QID_RX) { |
@@ -829,7 +830,7 @@ static bool rt2500pci_get_entry_state(struct queue_entry *entry) | |||
829 | 830 | ||
830 | static void rt2500pci_clear_entry(struct queue_entry *entry) | 831 | static void rt2500pci_clear_entry(struct queue_entry *entry) |
831 | { | 832 | { |
832 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 833 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
833 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 834 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
834 | u32 word; | 835 | u32 word; |
835 | 836 | ||
@@ -851,53 +852,53 @@ static void rt2500pci_clear_entry(struct queue_entry *entry) | |||
851 | 852 | ||
852 | static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) | 853 | static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) |
853 | { | 854 | { |
854 | struct queue_entry_priv_pci *entry_priv; | 855 | struct queue_entry_priv_mmio *entry_priv; |
855 | u32 reg; | 856 | u32 reg; |
856 | 857 | ||
857 | /* | 858 | /* |
858 | * Initialize registers. | 859 | * Initialize registers. |
859 | */ | 860 | */ |
860 | rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); | 861 | rt2x00mmio_register_read(rt2x00dev, TXCSR2, ®); |
861 | rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); | 862 | rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); |
862 | rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); | 863 | rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); |
863 | rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit); | 864 | rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit); |
864 | rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); | 865 | rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); |
865 | rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); | 866 | rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg); |
866 | 867 | ||
867 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; | 868 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; |
868 | rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); | 869 | rt2x00mmio_register_read(rt2x00dev, TXCSR3, ®); |
869 | rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, | 870 | rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, |
870 | entry_priv->desc_dma); | 871 | entry_priv->desc_dma); |
871 | rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); | 872 | rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg); |
872 | 873 | ||
873 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; | 874 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; |
874 | rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); | 875 | rt2x00mmio_register_read(rt2x00dev, TXCSR5, ®); |
875 | rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, | 876 | rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, |
876 | entry_priv->desc_dma); | 877 | entry_priv->desc_dma); |
877 | rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); | 878 | rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg); |
878 | 879 | ||
879 | entry_priv = rt2x00dev->atim->entries[0].priv_data; | 880 | entry_priv = rt2x00dev->atim->entries[0].priv_data; |
880 | rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); | 881 | rt2x00mmio_register_read(rt2x00dev, TXCSR4, ®); |
881 | rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, | 882 | rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, |
882 | entry_priv->desc_dma); | 883 | entry_priv->desc_dma); |
883 | rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); | 884 | rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg); |
884 | 885 | ||
885 | entry_priv = rt2x00dev->bcn->entries[0].priv_data; | 886 | entry_priv = rt2x00dev->bcn->entries[0].priv_data; |
886 | rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); | 887 | rt2x00mmio_register_read(rt2x00dev, TXCSR6, ®); |
887 | rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, | 888 | rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, |
888 | entry_priv->desc_dma); | 889 | entry_priv->desc_dma); |
889 | rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); | 890 | rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg); |
890 | 891 | ||
891 | rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); | 892 | rt2x00mmio_register_read(rt2x00dev, RXCSR1, ®); |
892 | rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); | 893 | rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); |
893 | rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); | 894 | rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); |
894 | rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); | 895 | rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg); |
895 | 896 | ||
896 | entry_priv = rt2x00dev->rx->entries[0].priv_data; | 897 | entry_priv = rt2x00dev->rx->entries[0].priv_data; |
897 | rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); | 898 | rt2x00mmio_register_read(rt2x00dev, RXCSR2, ®); |
898 | rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, | 899 | rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, |
899 | entry_priv->desc_dma); | 900 | entry_priv->desc_dma); |
900 | rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); | 901 | rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg); |
901 | 902 | ||
902 | return 0; | 903 | return 0; |
903 | } | 904 | } |
@@ -906,30 +907,30 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
906 | { | 907 | { |
907 | u32 reg; | 908 | u32 reg; |
908 | 909 | ||
909 | rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002); | 910 | rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002); |
910 | rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002); | 911 | rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002); |
911 | rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00020002); | 912 | rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00020002); |
912 | rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002); | 913 | rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002); |
913 | 914 | ||
914 | rt2x00pci_register_read(rt2x00dev, TIMECSR, ®); | 915 | rt2x00mmio_register_read(rt2x00dev, TIMECSR, ®); |
915 | rt2x00_set_field32(®, TIMECSR_US_COUNT, 33); | 916 | rt2x00_set_field32(®, TIMECSR_US_COUNT, 33); |
916 | rt2x00_set_field32(®, TIMECSR_US_64_COUNT, 63); | 917 | rt2x00_set_field32(®, TIMECSR_US_64_COUNT, 63); |
917 | rt2x00_set_field32(®, TIMECSR_BEACON_EXPECT, 0); | 918 | rt2x00_set_field32(®, TIMECSR_BEACON_EXPECT, 0); |
918 | rt2x00pci_register_write(rt2x00dev, TIMECSR, reg); | 919 | rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg); |
919 | 920 | ||
920 | rt2x00pci_register_read(rt2x00dev, CSR9, ®); | 921 | rt2x00mmio_register_read(rt2x00dev, CSR9, ®); |
921 | rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT, | 922 | rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT, |
922 | rt2x00dev->rx->data_size / 128); | 923 | rt2x00dev->rx->data_size / 128); |
923 | rt2x00pci_register_write(rt2x00dev, CSR9, reg); | 924 | rt2x00mmio_register_write(rt2x00dev, CSR9, reg); |
924 | 925 | ||
925 | /* | 926 | /* |
926 | * Always use CWmin and CWmax set in descriptor. | 927 | * Always use CWmin and CWmax set in descriptor. |
927 | */ | 928 | */ |
928 | rt2x00pci_register_read(rt2x00dev, CSR11, ®); | 929 | rt2x00mmio_register_read(rt2x00dev, CSR11, ®); |
929 | rt2x00_set_field32(®, CSR11_CW_SELECT, 0); | 930 | rt2x00_set_field32(®, CSR11_CW_SELECT, 0); |
930 | rt2x00pci_register_write(rt2x00dev, CSR11, reg); | 931 | rt2x00mmio_register_write(rt2x00dev, CSR11, reg); |
931 | 932 | ||
932 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 933 | rt2x00mmio_register_read(rt2x00dev, CSR14, ®); |
933 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); | 934 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); |
934 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); | 935 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); |
935 | rt2x00_set_field32(®, CSR14_TBCN, 0); | 936 | rt2x00_set_field32(®, CSR14_TBCN, 0); |
@@ -938,11 +939,11 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
938 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 939 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
939 | rt2x00_set_field32(®, CSR14_CFP_COUNT_PRELOAD, 0); | 940 | rt2x00_set_field32(®, CSR14_CFP_COUNT_PRELOAD, 0); |
940 | rt2x00_set_field32(®, CSR14_TBCM_PRELOAD, 0); | 941 | rt2x00_set_field32(®, CSR14_TBCM_PRELOAD, 0); |
941 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 942 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
942 | 943 | ||
943 | rt2x00pci_register_write(rt2x00dev, CNT3, 0); | 944 | rt2x00mmio_register_write(rt2x00dev, CNT3, 0); |
944 | 945 | ||
945 | rt2x00pci_register_read(rt2x00dev, TXCSR8, ®); | 946 | rt2x00mmio_register_read(rt2x00dev, TXCSR8, ®); |
946 | rt2x00_set_field32(®, TXCSR8_BBP_ID0, 10); | 947 | rt2x00_set_field32(®, TXCSR8_BBP_ID0, 10); |
947 | rt2x00_set_field32(®, TXCSR8_BBP_ID0_VALID, 1); | 948 | rt2x00_set_field32(®, TXCSR8_BBP_ID0_VALID, 1); |
948 | rt2x00_set_field32(®, TXCSR8_BBP_ID1, 11); | 949 | rt2x00_set_field32(®, TXCSR8_BBP_ID1, 11); |
@@ -951,30 +952,30 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
951 | rt2x00_set_field32(®, TXCSR8_BBP_ID2_VALID, 1); | 952 | rt2x00_set_field32(®, TXCSR8_BBP_ID2_VALID, 1); |
952 | rt2x00_set_field32(®, TXCSR8_BBP_ID3, 12); | 953 | rt2x00_set_field32(®, TXCSR8_BBP_ID3, 12); |
953 | rt2x00_set_field32(®, TXCSR8_BBP_ID3_VALID, 1); | 954 | rt2x00_set_field32(®, TXCSR8_BBP_ID3_VALID, 1); |
954 | rt2x00pci_register_write(rt2x00dev, TXCSR8, reg); | 955 | rt2x00mmio_register_write(rt2x00dev, TXCSR8, reg); |
955 | 956 | ||
956 | rt2x00pci_register_read(rt2x00dev, ARTCSR0, ®); | 957 | rt2x00mmio_register_read(rt2x00dev, ARTCSR0, ®); |
957 | rt2x00_set_field32(®, ARTCSR0_ACK_CTS_1MBS, 112); | 958 | rt2x00_set_field32(®, ARTCSR0_ACK_CTS_1MBS, 112); |
958 | rt2x00_set_field32(®, ARTCSR0_ACK_CTS_2MBS, 56); | 959 | rt2x00_set_field32(®, ARTCSR0_ACK_CTS_2MBS, 56); |
959 | rt2x00_set_field32(®, ARTCSR0_ACK_CTS_5_5MBS, 20); | 960 | rt2x00_set_field32(®, ARTCSR0_ACK_CTS_5_5MBS, 20); |
960 | rt2x00_set_field32(®, ARTCSR0_ACK_CTS_11MBS, 10); | 961 | rt2x00_set_field32(®, ARTCSR0_ACK_CTS_11MBS, 10); |
961 | rt2x00pci_register_write(rt2x00dev, ARTCSR0, reg); | 962 | rt2x00mmio_register_write(rt2x00dev, ARTCSR0, reg); |
962 | 963 | ||
963 | rt2x00pci_register_read(rt2x00dev, ARTCSR1, ®); | 964 | rt2x00mmio_register_read(rt2x00dev, ARTCSR1, ®); |
964 | rt2x00_set_field32(®, ARTCSR1_ACK_CTS_6MBS, 45); | 965 | rt2x00_set_field32(®, ARTCSR1_ACK_CTS_6MBS, 45); |
965 | rt2x00_set_field32(®, ARTCSR1_ACK_CTS_9MBS, 37); | 966 | rt2x00_set_field32(®, ARTCSR1_ACK_CTS_9MBS, 37); |
966 | rt2x00_set_field32(®, ARTCSR1_ACK_CTS_12MBS, 33); | 967 | rt2x00_set_field32(®, ARTCSR1_ACK_CTS_12MBS, 33); |
967 | rt2x00_set_field32(®, ARTCSR1_ACK_CTS_18MBS, 29); | 968 | rt2x00_set_field32(®, ARTCSR1_ACK_CTS_18MBS, 29); |
968 | rt2x00pci_register_write(rt2x00dev, ARTCSR1, reg); | 969 | rt2x00mmio_register_write(rt2x00dev, ARTCSR1, reg); |
969 | 970 | ||
970 | rt2x00pci_register_read(rt2x00dev, ARTCSR2, ®); | 971 | rt2x00mmio_register_read(rt2x00dev, ARTCSR2, ®); |
971 | rt2x00_set_field32(®, ARTCSR2_ACK_CTS_24MBS, 29); | 972 | rt2x00_set_field32(®, ARTCSR2_ACK_CTS_24MBS, 29); |
972 | rt2x00_set_field32(®, ARTCSR2_ACK_CTS_36MBS, 25); | 973 | rt2x00_set_field32(®, ARTCSR2_ACK_CTS_36MBS, 25); |
973 | rt2x00_set_field32(®, ARTCSR2_ACK_CTS_48MBS, 25); | 974 | rt2x00_set_field32(®, ARTCSR2_ACK_CTS_48MBS, 25); |
974 | rt2x00_set_field32(®, ARTCSR2_ACK_CTS_54MBS, 25); | 975 | rt2x00_set_field32(®, ARTCSR2_ACK_CTS_54MBS, 25); |
975 | rt2x00pci_register_write(rt2x00dev, ARTCSR2, reg); | 976 | rt2x00mmio_register_write(rt2x00dev, ARTCSR2, reg); |
976 | 977 | ||
977 | rt2x00pci_register_read(rt2x00dev, RXCSR3, ®); | 978 | rt2x00mmio_register_read(rt2x00dev, RXCSR3, ®); |
978 | rt2x00_set_field32(®, RXCSR3_BBP_ID0, 47); /* CCK Signal */ | 979 | rt2x00_set_field32(®, RXCSR3_BBP_ID0, 47); /* CCK Signal */ |
979 | rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1); | 980 | rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1); |
980 | rt2x00_set_field32(®, RXCSR3_BBP_ID1, 51); /* Rssi */ | 981 | rt2x00_set_field32(®, RXCSR3_BBP_ID1, 51); /* Rssi */ |
@@ -983,9 +984,9 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
983 | rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1); | 984 | rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1); |
984 | rt2x00_set_field32(®, RXCSR3_BBP_ID3, 51); /* RSSI */ | 985 | rt2x00_set_field32(®, RXCSR3_BBP_ID3, 51); /* RSSI */ |
985 | rt2x00_set_field32(®, RXCSR3_BBP_ID3_VALID, 1); | 986 | rt2x00_set_field32(®, RXCSR3_BBP_ID3_VALID, 1); |
986 | rt2x00pci_register_write(rt2x00dev, RXCSR3, reg); | 987 | rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg); |
987 | 988 | ||
988 | rt2x00pci_register_read(rt2x00dev, PCICSR, ®); | 989 | rt2x00mmio_register_read(rt2x00dev, PCICSR, ®); |
989 | rt2x00_set_field32(®, PCICSR_BIG_ENDIAN, 0); | 990 | rt2x00_set_field32(®, PCICSR_BIG_ENDIAN, 0); |
990 | rt2x00_set_field32(®, PCICSR_RX_TRESHOLD, 0); | 991 | rt2x00_set_field32(®, PCICSR_RX_TRESHOLD, 0); |
991 | rt2x00_set_field32(®, PCICSR_TX_TRESHOLD, 3); | 992 | rt2x00_set_field32(®, PCICSR_TX_TRESHOLD, 3); |
@@ -993,54 +994,54 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
993 | rt2x00_set_field32(®, PCICSR_ENABLE_CLK, 1); | 994 | rt2x00_set_field32(®, PCICSR_ENABLE_CLK, 1); |
994 | rt2x00_set_field32(®, PCICSR_READ_MULTIPLE, 1); | 995 | rt2x00_set_field32(®, PCICSR_READ_MULTIPLE, 1); |
995 | rt2x00_set_field32(®, PCICSR_WRITE_INVALID, 1); | 996 | rt2x00_set_field32(®, PCICSR_WRITE_INVALID, 1); |
996 | rt2x00pci_register_write(rt2x00dev, PCICSR, reg); | 997 | rt2x00mmio_register_write(rt2x00dev, PCICSR, reg); |
997 | 998 | ||
998 | rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); | 999 | rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); |
999 | 1000 | ||
1000 | rt2x00pci_register_write(rt2x00dev, GPIOCSR, 0x0000ff00); | 1001 | rt2x00mmio_register_write(rt2x00dev, GPIOCSR, 0x0000ff00); |
1001 | rt2x00pci_register_write(rt2x00dev, TESTCSR, 0x000000f0); | 1002 | rt2x00mmio_register_write(rt2x00dev, TESTCSR, 0x000000f0); |
1002 | 1003 | ||
1003 | if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) | 1004 | if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) |
1004 | return -EBUSY; | 1005 | return -EBUSY; |
1005 | 1006 | ||
1006 | rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00213223); | 1007 | rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00213223); |
1007 | rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518); | 1008 | rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518); |
1008 | 1009 | ||
1009 | rt2x00pci_register_read(rt2x00dev, MACCSR2, ®); | 1010 | rt2x00mmio_register_read(rt2x00dev, MACCSR2, ®); |
1010 | rt2x00_set_field32(®, MACCSR2_DELAY, 64); | 1011 | rt2x00_set_field32(®, MACCSR2_DELAY, 64); |
1011 | rt2x00pci_register_write(rt2x00dev, MACCSR2, reg); | 1012 | rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg); |
1012 | 1013 | ||
1013 | rt2x00pci_register_read(rt2x00dev, RALINKCSR, ®); | 1014 | rt2x00mmio_register_read(rt2x00dev, RALINKCSR, ®); |
1014 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17); | 1015 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17); |
1015 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 26); | 1016 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 26); |
1016 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_VALID0, 1); | 1017 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_VALID0, 1); |
1017 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA1, 0); | 1018 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA1, 0); |
1018 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 26); | 1019 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 26); |
1019 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_VALID1, 1); | 1020 | rt2x00_set_field32(®, RALINKCSR_AR_BBP_VALID1, 1); |
1020 | rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg); | 1021 | rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg); |
1021 | 1022 | ||
1022 | rt2x00pci_register_write(rt2x00dev, BBPCSR1, 0x82188200); | 1023 | rt2x00mmio_register_write(rt2x00dev, BBPCSR1, 0x82188200); |
1023 | 1024 | ||
1024 | rt2x00pci_register_write(rt2x00dev, TXACKCSR0, 0x00000020); | 1025 | rt2x00mmio_register_write(rt2x00dev, TXACKCSR0, 0x00000020); |
1025 | 1026 | ||
1026 | rt2x00pci_register_read(rt2x00dev, CSR1, ®); | 1027 | rt2x00mmio_register_read(rt2x00dev, CSR1, ®); |
1027 | rt2x00_set_field32(®, CSR1_SOFT_RESET, 1); | 1028 | rt2x00_set_field32(®, CSR1_SOFT_RESET, 1); |
1028 | rt2x00_set_field32(®, CSR1_BBP_RESET, 0); | 1029 | rt2x00_set_field32(®, CSR1_BBP_RESET, 0); |
1029 | rt2x00_set_field32(®, CSR1_HOST_READY, 0); | 1030 | rt2x00_set_field32(®, CSR1_HOST_READY, 0); |
1030 | rt2x00pci_register_write(rt2x00dev, CSR1, reg); | 1031 | rt2x00mmio_register_write(rt2x00dev, CSR1, reg); |
1031 | 1032 | ||
1032 | rt2x00pci_register_read(rt2x00dev, CSR1, ®); | 1033 | rt2x00mmio_register_read(rt2x00dev, CSR1, ®); |
1033 | rt2x00_set_field32(®, CSR1_SOFT_RESET, 0); | 1034 | rt2x00_set_field32(®, CSR1_SOFT_RESET, 0); |
1034 | rt2x00_set_field32(®, CSR1_HOST_READY, 1); | 1035 | rt2x00_set_field32(®, CSR1_HOST_READY, 1); |
1035 | rt2x00pci_register_write(rt2x00dev, CSR1, reg); | 1036 | rt2x00mmio_register_write(rt2x00dev, CSR1, reg); |
1036 | 1037 | ||
1037 | /* | 1038 | /* |
1038 | * We must clear the FCS and FIFO error count. | 1039 | * We must clear the FCS and FIFO error count. |
1039 | * These registers are cleared on read, | 1040 | * These registers are cleared on read, |
1040 | * so we may pass a useless variable to store the value. | 1041 | * so we may pass a useless variable to store the value. |
1041 | */ | 1042 | */ |
1042 | rt2x00pci_register_read(rt2x00dev, CNT0, ®); | 1043 | rt2x00mmio_register_read(rt2x00dev, CNT0, ®); |
1043 | rt2x00pci_register_read(rt2x00dev, CNT4, ®); | 1044 | rt2x00mmio_register_read(rt2x00dev, CNT4, ®); |
1044 | 1045 | ||
1045 | return 0; | 1046 | return 0; |
1046 | } | 1047 | } |
@@ -1130,8 +1131,8 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1130 | * should clear the register to assure a clean state. | 1131 | * should clear the register to assure a clean state. |
1131 | */ | 1132 | */ |
1132 | if (state == STATE_RADIO_IRQ_ON) { | 1133 | if (state == STATE_RADIO_IRQ_ON) { |
1133 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | 1134 | rt2x00mmio_register_read(rt2x00dev, CSR7, ®); |
1134 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | 1135 | rt2x00mmio_register_write(rt2x00dev, CSR7, reg); |
1135 | } | 1136 | } |
1136 | 1137 | ||
1137 | /* | 1138 | /* |
@@ -1140,13 +1141,13 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1140 | */ | 1141 | */ |
1141 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | 1142 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
1142 | 1143 | ||
1143 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 1144 | rt2x00mmio_register_read(rt2x00dev, CSR8, ®); |
1144 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); | 1145 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); |
1145 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); | 1146 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); |
1146 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, mask); | 1147 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, mask); |
1147 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); | 1148 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); |
1148 | rt2x00_set_field32(®, CSR8_RXDONE, mask); | 1149 | rt2x00_set_field32(®, CSR8_RXDONE, mask); |
1149 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1150 | rt2x00mmio_register_write(rt2x00dev, CSR8, reg); |
1150 | 1151 | ||
1151 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | 1152 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
1152 | 1153 | ||
@@ -1178,7 +1179,7 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
1178 | /* | 1179 | /* |
1179 | * Disable power | 1180 | * Disable power |
1180 | */ | 1181 | */ |
1181 | rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); | 1182 | rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0); |
1182 | } | 1183 | } |
1183 | 1184 | ||
1184 | static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, | 1185 | static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, |
@@ -1192,12 +1193,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, | |||
1192 | 1193 | ||
1193 | put_to_sleep = (state != STATE_AWAKE); | 1194 | put_to_sleep = (state != STATE_AWAKE); |
1194 | 1195 | ||
1195 | rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); | 1196 | rt2x00mmio_register_read(rt2x00dev, PWRCSR1, ®); |
1196 | rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1); | 1197 | rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1); |
1197 | rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state); | 1198 | rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state); |
1198 | rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state); | 1199 | rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state); |
1199 | rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep); | 1200 | rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep); |
1200 | rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); | 1201 | rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg); |
1201 | 1202 | ||
1202 | /* | 1203 | /* |
1203 | * Device is not guaranteed to be in the requested state yet. | 1204 | * Device is not guaranteed to be in the requested state yet. |
@@ -1205,12 +1206,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, | |||
1205 | * device has entered the correct state. | 1206 | * device has entered the correct state. |
1206 | */ | 1207 | */ |
1207 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 1208 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
1208 | rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2); | 1209 | rt2x00mmio_register_read(rt2x00dev, PWRCSR1, ®2); |
1209 | bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE); | 1210 | bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE); |
1210 | rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE); | 1211 | rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE); |
1211 | if (bbp_state == state && rf_state == state) | 1212 | if (bbp_state == state && rf_state == state) |
1212 | return 0; | 1213 | return 0; |
1213 | rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); | 1214 | rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg); |
1214 | msleep(10); | 1215 | msleep(10); |
1215 | } | 1216 | } |
1216 | 1217 | ||
@@ -1258,7 +1259,7 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry, | |||
1258 | struct txentry_desc *txdesc) | 1259 | struct txentry_desc *txdesc) |
1259 | { | 1260 | { |
1260 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1261 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
1261 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1262 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
1262 | __le32 *txd = entry_priv->desc; | 1263 | __le32 *txd = entry_priv->desc; |
1263 | u32 word; | 1264 | u32 word; |
1264 | 1265 | ||
@@ -1334,9 +1335,9 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, | |||
1334 | * Disable beaconing while we are reloading the beacon data, | 1335 | * Disable beaconing while we are reloading the beacon data, |
1335 | * otherwise we might be sending out invalid data. | 1336 | * otherwise we might be sending out invalid data. |
1336 | */ | 1337 | */ |
1337 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 1338 | rt2x00mmio_register_read(rt2x00dev, CSR14, ®); |
1338 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 1339 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
1339 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 1340 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
1340 | 1341 | ||
1341 | if (rt2x00queue_map_txskb(entry)) { | 1342 | if (rt2x00queue_map_txskb(entry)) { |
1342 | ERROR(rt2x00dev, "Fail to map beacon, aborting\n"); | 1343 | ERROR(rt2x00dev, "Fail to map beacon, aborting\n"); |
@@ -1357,7 +1358,7 @@ out: | |||
1357 | * Enable beaconing again. | 1358 | * Enable beaconing again. |
1358 | */ | 1359 | */ |
1359 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); | 1360 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); |
1360 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 1361 | rt2x00mmio_register_write(rt2x00dev, CSR14, reg); |
1361 | } | 1362 | } |
1362 | 1363 | ||
1363 | /* | 1364 | /* |
@@ -1366,7 +1367,7 @@ out: | |||
1366 | static void rt2500pci_fill_rxdone(struct queue_entry *entry, | 1367 | static void rt2500pci_fill_rxdone(struct queue_entry *entry, |
1367 | struct rxdone_entry_desc *rxdesc) | 1368 | struct rxdone_entry_desc *rxdesc) |
1368 | { | 1369 | { |
1369 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1370 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
1370 | u32 word0; | 1371 | u32 word0; |
1371 | u32 word2; | 1372 | u32 word2; |
1372 | 1373 | ||
@@ -1404,7 +1405,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1404 | const enum data_queue_qid queue_idx) | 1405 | const enum data_queue_qid queue_idx) |
1405 | { | 1406 | { |
1406 | struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx); | 1407 | struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx); |
1407 | struct queue_entry_priv_pci *entry_priv; | 1408 | struct queue_entry_priv_mmio *entry_priv; |
1408 | struct queue_entry *entry; | 1409 | struct queue_entry *entry; |
1409 | struct txdone_entry_desc txdesc; | 1410 | struct txdone_entry_desc txdesc; |
1410 | u32 word; | 1411 | u32 word; |
@@ -1450,9 +1451,9 @@ static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, | |||
1450 | */ | 1451 | */ |
1451 | spin_lock_irq(&rt2x00dev->irqmask_lock); | 1452 | spin_lock_irq(&rt2x00dev->irqmask_lock); |
1452 | 1453 | ||
1453 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 1454 | rt2x00mmio_register_read(rt2x00dev, CSR8, ®); |
1454 | rt2x00_set_field32(®, irq_field, 0); | 1455 | rt2x00_set_field32(®, irq_field, 0); |
1455 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1456 | rt2x00mmio_register_write(rt2x00dev, CSR8, reg); |
1456 | 1457 | ||
1457 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | 1458 | spin_unlock_irq(&rt2x00dev->irqmask_lock); |
1458 | } | 1459 | } |
@@ -1475,11 +1476,11 @@ static void rt2500pci_txstatus_tasklet(unsigned long data) | |||
1475 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) { | 1476 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) { |
1476 | spin_lock_irq(&rt2x00dev->irqmask_lock); | 1477 | spin_lock_irq(&rt2x00dev->irqmask_lock); |
1477 | 1478 | ||
1478 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 1479 | rt2x00mmio_register_read(rt2x00dev, CSR8, ®); |
1479 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); | 1480 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); |
1480 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); | 1481 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); |
1481 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); | 1482 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); |
1482 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1483 | rt2x00mmio_register_write(rt2x00dev, CSR8, reg); |
1483 | 1484 | ||
1484 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | 1485 | spin_unlock_irq(&rt2x00dev->irqmask_lock); |
1485 | } | 1486 | } |
@@ -1496,7 +1497,7 @@ static void rt2500pci_tbtt_tasklet(unsigned long data) | |||
1496 | static void rt2500pci_rxdone_tasklet(unsigned long data) | 1497 | static void rt2500pci_rxdone_tasklet(unsigned long data) |
1497 | { | 1498 | { |
1498 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | 1499 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
1499 | if (rt2x00pci_rxdone(rt2x00dev)) | 1500 | if (rt2x00mmio_rxdone(rt2x00dev)) |
1500 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | 1501 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); |
1501 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 1502 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
1502 | rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); | 1503 | rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); |
@@ -1511,8 +1512,8 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) | |||
1511 | * Get the interrupt sources & saved to local variable. | 1512 | * Get the interrupt sources & saved to local variable. |
1512 | * Write register value back to clear pending interrupts. | 1513 | * Write register value back to clear pending interrupts. |
1513 | */ | 1514 | */ |
1514 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | 1515 | rt2x00mmio_register_read(rt2x00dev, CSR7, ®); |
1515 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | 1516 | rt2x00mmio_register_write(rt2x00dev, CSR7, reg); |
1516 | 1517 | ||
1517 | if (!reg) | 1518 | if (!reg) |
1518 | return IRQ_NONE; | 1519 | return IRQ_NONE; |
@@ -1549,9 +1550,9 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) | |||
1549 | */ | 1550 | */ |
1550 | spin_lock(&rt2x00dev->irqmask_lock); | 1551 | spin_lock(&rt2x00dev->irqmask_lock); |
1551 | 1552 | ||
1552 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 1553 | rt2x00mmio_register_read(rt2x00dev, CSR8, ®); |
1553 | reg |= mask; | 1554 | reg |= mask; |
1554 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1555 | rt2x00mmio_register_write(rt2x00dev, CSR8, reg); |
1555 | 1556 | ||
1556 | spin_unlock(&rt2x00dev->irqmask_lock); | 1557 | spin_unlock(&rt2x00dev->irqmask_lock); |
1557 | 1558 | ||
@@ -1568,7 +1569,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1568 | u16 word; | 1569 | u16 word; |
1569 | u8 *mac; | 1570 | u8 *mac; |
1570 | 1571 | ||
1571 | rt2x00pci_register_read(rt2x00dev, CSR21, ®); | 1572 | rt2x00mmio_register_read(rt2x00dev, CSR21, ®); |
1572 | 1573 | ||
1573 | eeprom.data = rt2x00dev; | 1574 | eeprom.data = rt2x00dev; |
1574 | eeprom.register_read = rt2500pci_eepromregister_read; | 1575 | eeprom.register_read = rt2500pci_eepromregister_read; |
@@ -1643,7 +1644,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1643 | * Identify RF chipset. | 1644 | * Identify RF chipset. |
1644 | */ | 1645 | */ |
1645 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1646 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1646 | rt2x00pci_register_read(rt2x00dev, CSR0, ®); | 1647 | rt2x00mmio_register_read(rt2x00dev, CSR0, ®); |
1647 | rt2x00_set_chip(rt2x00dev, RT2560, value, | 1648 | rt2x00_set_chip(rt2x00dev, RT2560, value, |
1648 | rt2x00_get_field32(reg, CSR0_REVISION)); | 1649 | rt2x00_get_field32(reg, CSR0_REVISION)); |
1649 | 1650 | ||
@@ -1949,9 +1950,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1949 | * Enable rfkill polling by setting GPIO direction of the | 1950 | * Enable rfkill polling by setting GPIO direction of the |
1950 | * rfkill switch GPIO pin correctly. | 1951 | * rfkill switch GPIO pin correctly. |
1951 | */ | 1952 | */ |
1952 | rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); | 1953 | rt2x00mmio_register_read(rt2x00dev, GPIOCSR, ®); |
1953 | rt2x00_set_field32(®, GPIOCSR_DIR0, 1); | 1954 | rt2x00_set_field32(®, GPIOCSR_DIR0, 1); |
1954 | rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); | 1955 | rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg); |
1955 | 1956 | ||
1956 | /* | 1957 | /* |
1957 | * Initialize hw specifications. | 1958 | * Initialize hw specifications. |
@@ -1985,9 +1986,9 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw, | |||
1985 | u64 tsf; | 1986 | u64 tsf; |
1986 | u32 reg; | 1987 | u32 reg; |
1987 | 1988 | ||
1988 | rt2x00pci_register_read(rt2x00dev, CSR17, ®); | 1989 | rt2x00mmio_register_read(rt2x00dev, CSR17, ®); |
1989 | tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; | 1990 | tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; |
1990 | rt2x00pci_register_read(rt2x00dev, CSR16, ®); | 1991 | rt2x00mmio_register_read(rt2x00dev, CSR16, ®); |
1991 | tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER); | 1992 | tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER); |
1992 | 1993 | ||
1993 | return tsf; | 1994 | return tsf; |
@@ -1998,7 +1999,7 @@ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw) | |||
1998 | struct rt2x00_dev *rt2x00dev = hw->priv; | 1999 | struct rt2x00_dev *rt2x00dev = hw->priv; |
1999 | u32 reg; | 2000 | u32 reg; |
2000 | 2001 | ||
2001 | rt2x00pci_register_read(rt2x00dev, CSR15, ®); | 2002 | rt2x00mmio_register_read(rt2x00dev, CSR15, ®); |
2002 | return rt2x00_get_field32(reg, CSR15_BEACON_SENT); | 2003 | return rt2x00_get_field32(reg, CSR15_BEACON_SENT); |
2003 | } | 2004 | } |
2004 | 2005 | ||
@@ -2031,8 +2032,8 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { | |||
2031 | .tbtt_tasklet = rt2500pci_tbtt_tasklet, | 2032 | .tbtt_tasklet = rt2500pci_tbtt_tasklet, |
2032 | .rxdone_tasklet = rt2500pci_rxdone_tasklet, | 2033 | .rxdone_tasklet = rt2500pci_rxdone_tasklet, |
2033 | .probe_hw = rt2500pci_probe_hw, | 2034 | .probe_hw = rt2500pci_probe_hw, |
2034 | .initialize = rt2x00pci_initialize, | 2035 | .initialize = rt2x00mmio_initialize, |
2035 | .uninitialize = rt2x00pci_uninitialize, | 2036 | .uninitialize = rt2x00mmio_uninitialize, |
2036 | .get_entry_state = rt2500pci_get_entry_state, | 2037 | .get_entry_state = rt2500pci_get_entry_state, |
2037 | .clear_entry = rt2500pci_clear_entry, | 2038 | .clear_entry = rt2500pci_clear_entry, |
2038 | .set_device_state = rt2500pci_set_device_state, | 2039 | .set_device_state = rt2500pci_set_device_state, |
@@ -2043,7 +2044,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { | |||
2043 | .start_queue = rt2500pci_start_queue, | 2044 | .start_queue = rt2500pci_start_queue, |
2044 | .kick_queue = rt2500pci_kick_queue, | 2045 | .kick_queue = rt2500pci_kick_queue, |
2045 | .stop_queue = rt2500pci_stop_queue, | 2046 | .stop_queue = rt2500pci_stop_queue, |
2046 | .flush_queue = rt2x00pci_flush_queue, | 2047 | .flush_queue = rt2x00mmio_flush_queue, |
2047 | .write_tx_desc = rt2500pci_write_tx_desc, | 2048 | .write_tx_desc = rt2500pci_write_tx_desc, |
2048 | .write_beacon = rt2500pci_write_beacon, | 2049 | .write_beacon = rt2500pci_write_beacon, |
2049 | .fill_rxdone = rt2500pci_fill_rxdone, | 2050 | .fill_rxdone = rt2500pci_fill_rxdone, |
@@ -2058,28 +2059,28 @@ static const struct data_queue_desc rt2500pci_queue_rx = { | |||
2058 | .entry_num = 32, | 2059 | .entry_num = 32, |
2059 | .data_size = DATA_FRAME_SIZE, | 2060 | .data_size = DATA_FRAME_SIZE, |
2060 | .desc_size = RXD_DESC_SIZE, | 2061 | .desc_size = RXD_DESC_SIZE, |
2061 | .priv_size = sizeof(struct queue_entry_priv_pci), | 2062 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
2062 | }; | 2063 | }; |
2063 | 2064 | ||
2064 | static const struct data_queue_desc rt2500pci_queue_tx = { | 2065 | static const struct data_queue_desc rt2500pci_queue_tx = { |
2065 | .entry_num = 32, | 2066 | .entry_num = 32, |
2066 | .data_size = DATA_FRAME_SIZE, | 2067 | .data_size = DATA_FRAME_SIZE, |
2067 | .desc_size = TXD_DESC_SIZE, | 2068 | .desc_size = TXD_DESC_SIZE, |
2068 | .priv_size = sizeof(struct queue_entry_priv_pci), | 2069 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
2069 | }; | 2070 | }; |
2070 | 2071 | ||
2071 | static const struct data_queue_desc rt2500pci_queue_bcn = { | 2072 | static const struct data_queue_desc rt2500pci_queue_bcn = { |
2072 | .entry_num = 1, | 2073 | .entry_num = 1, |
2073 | .data_size = MGMT_FRAME_SIZE, | 2074 | .data_size = MGMT_FRAME_SIZE, |
2074 | .desc_size = TXD_DESC_SIZE, | 2075 | .desc_size = TXD_DESC_SIZE, |
2075 | .priv_size = sizeof(struct queue_entry_priv_pci), | 2076 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
2076 | }; | 2077 | }; |
2077 | 2078 | ||
2078 | static const struct data_queue_desc rt2500pci_queue_atim = { | 2079 | static const struct data_queue_desc rt2500pci_queue_atim = { |
2079 | .entry_num = 8, | 2080 | .entry_num = 8, |
2080 | .data_size = DATA_FRAME_SIZE, | 2081 | .data_size = DATA_FRAME_SIZE, |
2081 | .desc_size = TXD_DESC_SIZE, | 2082 | .desc_size = TXD_DESC_SIZE, |
2082 | .priv_size = sizeof(struct queue_entry_priv_pci), | 2083 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
2083 | }; | 2084 | }; |
2084 | 2085 | ||
2085 | static const struct rt2x00_ops rt2500pci_ops = { | 2086 | static const struct rt2x00_ops rt2500pci_ops = { |
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 34456b45acbb..72bbb962579f 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) || |
@@ -4821,9 +5431,9 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4821 | 5431 | ||
4822 | static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | 5432 | static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) |
4823 | { | 5433 | { |
4824 | u32 reg; | ||
4825 | u16 value; | 5434 | u16 value; |
4826 | u16 eeprom; | 5435 | u16 eeprom; |
5436 | u16 rf; | ||
4827 | 5437 | ||
4828 | /* | 5438 | /* |
4829 | * Read EEPROM word for configuration. | 5439 | * Read EEPROM word for configuration. |
@@ -4835,41 +5445,14 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4835 | * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field | 5445 | * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field |
4836 | * RT53xx: defined in "EEPROM_CHIP_ID" field | 5446 | * RT53xx: defined in "EEPROM_CHIP_ID" field |
4837 | */ | 5447 | */ |
4838 | if (rt2x00_rt(rt2x00dev, RT3290)) | 5448 | if (rt2x00_rt(rt2x00dev, RT3290) || |
4839 | rt2800_register_read(rt2x00dev, MAC_CSR0_3290, ®); | 5449 | rt2x00_rt(rt2x00dev, RT5390) || |
4840 | else | 5450 | rt2x00_rt(rt2x00dev, RT5392)) |
4841 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | 5451 | rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); |
4842 | |||
4843 | if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290 || | ||
4844 | rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 || | ||
4845 | rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392) | ||
4846 | rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value); | ||
4847 | else | 5452 | else |
4848 | value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); | 5453 | rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); |
4849 | |||
4850 | rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), | ||
4851 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); | ||
4852 | |||
4853 | switch (rt2x00dev->chip.rt) { | ||
4854 | case RT2860: | ||
4855 | case RT2872: | ||
4856 | case RT2883: | ||
4857 | case RT3070: | ||
4858 | case RT3071: | ||
4859 | case RT3090: | ||
4860 | case RT3290: | ||
4861 | case RT3352: | ||
4862 | case RT3390: | ||
4863 | case RT3572: | ||
4864 | case RT5390: | ||
4865 | case RT5392: | ||
4866 | break; | ||
4867 | default: | ||
4868 | ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt); | ||
4869 | return -ENODEV; | ||
4870 | } | ||
4871 | 5454 | ||
4872 | switch (rt2x00dev->chip.rf) { | 5455 | switch (rf) { |
4873 | case RF2820: | 5456 | case RF2820: |
4874 | case RF2850: | 5457 | case RF2850: |
4875 | case RF2720: | 5458 | case RF2720: |
@@ -4887,13 +5470,15 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4887 | case RF5372: | 5470 | case RF5372: |
4888 | case RF5390: | 5471 | case RF5390: |
4889 | case RF5392: | 5472 | case RF5392: |
5473 | case RF5592: | ||
4890 | break; | 5474 | break; |
4891 | default: | 5475 | default: |
4892 | ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", | 5476 | ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", rf); |
4893 | rt2x00dev->chip.rf); | ||
4894 | return -ENODEV; | 5477 | return -ENODEV; |
4895 | } | 5478 | } |
4896 | 5479 | ||
5480 | rt2x00_set_rf(rt2x00dev, rf); | ||
5481 | |||
4897 | /* | 5482 | /* |
4898 | * Identify default antenna configuration. | 5483 | * Identify default antenna configuration. |
4899 | */ | 5484 | */ |
@@ -5122,6 +5707,138 @@ static const struct rf_channel rf_vals_3x[] = { | |||
5122 | {173, 0x61, 0, 9}, | 5707 | {173, 0x61, 0, 9}, |
5123 | }; | 5708 | }; |
5124 | 5709 | ||
5710 | static const struct rf_channel rf_vals_5592_xtal20[] = { | ||
5711 | /* Channel, N, K, mod, R */ | ||
5712 | {1, 482, 4, 10, 3}, | ||
5713 | {2, 483, 4, 10, 3}, | ||
5714 | {3, 484, 4, 10, 3}, | ||
5715 | {4, 485, 4, 10, 3}, | ||
5716 | {5, 486, 4, 10, 3}, | ||
5717 | {6, 487, 4, 10, 3}, | ||
5718 | {7, 488, 4, 10, 3}, | ||
5719 | {8, 489, 4, 10, 3}, | ||
5720 | {9, 490, 4, 10, 3}, | ||
5721 | {10, 491, 4, 10, 3}, | ||
5722 | {11, 492, 4, 10, 3}, | ||
5723 | {12, 493, 4, 10, 3}, | ||
5724 | {13, 494, 4, 10, 3}, | ||
5725 | {14, 496, 8, 10, 3}, | ||
5726 | {36, 172, 8, 12, 1}, | ||
5727 | {38, 173, 0, 12, 1}, | ||
5728 | {40, 173, 4, 12, 1}, | ||
5729 | {42, 173, 8, 12, 1}, | ||
5730 | {44, 174, 0, 12, 1}, | ||
5731 | {46, 174, 4, 12, 1}, | ||
5732 | {48, 174, 8, 12, 1}, | ||
5733 | {50, 175, 0, 12, 1}, | ||
5734 | {52, 175, 4, 12, 1}, | ||
5735 | {54, 175, 8, 12, 1}, | ||
5736 | {56, 176, 0, 12, 1}, | ||
5737 | {58, 176, 4, 12, 1}, | ||
5738 | {60, 176, 8, 12, 1}, | ||
5739 | {62, 177, 0, 12, 1}, | ||
5740 | {64, 177, 4, 12, 1}, | ||
5741 | {100, 183, 4, 12, 1}, | ||
5742 | {102, 183, 8, 12, 1}, | ||
5743 | {104, 184, 0, 12, 1}, | ||
5744 | {106, 184, 4, 12, 1}, | ||
5745 | {108, 184, 8, 12, 1}, | ||
5746 | {110, 185, 0, 12, 1}, | ||
5747 | {112, 185, 4, 12, 1}, | ||
5748 | {114, 185, 8, 12, 1}, | ||
5749 | {116, 186, 0, 12, 1}, | ||
5750 | {118, 186, 4, 12, 1}, | ||
5751 | {120, 186, 8, 12, 1}, | ||
5752 | {122, 187, 0, 12, 1}, | ||
5753 | {124, 187, 4, 12, 1}, | ||
5754 | {126, 187, 8, 12, 1}, | ||
5755 | {128, 188, 0, 12, 1}, | ||
5756 | {130, 188, 4, 12, 1}, | ||
5757 | {132, 188, 8, 12, 1}, | ||
5758 | {134, 189, 0, 12, 1}, | ||
5759 | {136, 189, 4, 12, 1}, | ||
5760 | {138, 189, 8, 12, 1}, | ||
5761 | {140, 190, 0, 12, 1}, | ||
5762 | {149, 191, 6, 12, 1}, | ||
5763 | {151, 191, 10, 12, 1}, | ||
5764 | {153, 192, 2, 12, 1}, | ||
5765 | {155, 192, 6, 12, 1}, | ||
5766 | {157, 192, 10, 12, 1}, | ||
5767 | {159, 193, 2, 12, 1}, | ||
5768 | {161, 193, 6, 12, 1}, | ||
5769 | {165, 194, 2, 12, 1}, | ||
5770 | {184, 164, 0, 12, 1}, | ||
5771 | {188, 164, 4, 12, 1}, | ||
5772 | {192, 165, 8, 12, 1}, | ||
5773 | {196, 166, 0, 12, 1}, | ||
5774 | }; | ||
5775 | |||
5776 | static const struct rf_channel rf_vals_5592_xtal40[] = { | ||
5777 | /* Channel, N, K, mod, R */ | ||
5778 | {1, 241, 2, 10, 3}, | ||
5779 | {2, 241, 7, 10, 3}, | ||
5780 | {3, 242, 2, 10, 3}, | ||
5781 | {4, 242, 7, 10, 3}, | ||
5782 | {5, 243, 2, 10, 3}, | ||
5783 | {6, 243, 7, 10, 3}, | ||
5784 | {7, 244, 2, 10, 3}, | ||
5785 | {8, 244, 7, 10, 3}, | ||
5786 | {9, 245, 2, 10, 3}, | ||
5787 | {10, 245, 7, 10, 3}, | ||
5788 | {11, 246, 2, 10, 3}, | ||
5789 | {12, 246, 7, 10, 3}, | ||
5790 | {13, 247, 2, 10, 3}, | ||
5791 | {14, 248, 4, 10, 3}, | ||
5792 | {36, 86, 4, 12, 1}, | ||
5793 | {38, 86, 6, 12, 1}, | ||
5794 | {40, 86, 8, 12, 1}, | ||
5795 | {42, 86, 10, 12, 1}, | ||
5796 | {44, 87, 0, 12, 1}, | ||
5797 | {46, 87, 2, 12, 1}, | ||
5798 | {48, 87, 4, 12, 1}, | ||
5799 | {50, 87, 6, 12, 1}, | ||
5800 | {52, 87, 8, 12, 1}, | ||
5801 | {54, 87, 10, 12, 1}, | ||
5802 | {56, 88, 0, 12, 1}, | ||
5803 | {58, 88, 2, 12, 1}, | ||
5804 | {60, 88, 4, 12, 1}, | ||
5805 | {62, 88, 6, 12, 1}, | ||
5806 | {64, 88, 8, 12, 1}, | ||
5807 | {100, 91, 8, 12, 1}, | ||
5808 | {102, 91, 10, 12, 1}, | ||
5809 | {104, 92, 0, 12, 1}, | ||
5810 | {106, 92, 2, 12, 1}, | ||
5811 | {108, 92, 4, 12, 1}, | ||
5812 | {110, 92, 6, 12, 1}, | ||
5813 | {112, 92, 8, 12, 1}, | ||
5814 | {114, 92, 10, 12, 1}, | ||
5815 | {116, 93, 0, 12, 1}, | ||
5816 | {118, 93, 2, 12, 1}, | ||
5817 | {120, 93, 4, 12, 1}, | ||
5818 | {122, 93, 6, 12, 1}, | ||
5819 | {124, 93, 8, 12, 1}, | ||
5820 | {126, 93, 10, 12, 1}, | ||
5821 | {128, 94, 0, 12, 1}, | ||
5822 | {130, 94, 2, 12, 1}, | ||
5823 | {132, 94, 4, 12, 1}, | ||
5824 | {134, 94, 6, 12, 1}, | ||
5825 | {136, 94, 8, 12, 1}, | ||
5826 | {138, 94, 10, 12, 1}, | ||
5827 | {140, 95, 0, 12, 1}, | ||
5828 | {149, 95, 9, 12, 1}, | ||
5829 | {151, 95, 11, 12, 1}, | ||
5830 | {153, 96, 1, 12, 1}, | ||
5831 | {155, 96, 3, 12, 1}, | ||
5832 | {157, 96, 5, 12, 1}, | ||
5833 | {159, 96, 7, 12, 1}, | ||
5834 | {161, 96, 9, 12, 1}, | ||
5835 | {165, 97, 1, 12, 1}, | ||
5836 | {184, 82, 0, 12, 1}, | ||
5837 | {188, 82, 4, 12, 1}, | ||
5838 | {192, 82, 8, 12, 1}, | ||
5839 | {196, 83, 0, 12, 1}, | ||
5840 | }; | ||
5841 | |||
5125 | static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | 5842 | static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) |
5126 | { | 5843 | { |
5127 | struct hw_mode_spec *spec = &rt2x00dev->spec; | 5844 | struct hw_mode_spec *spec = &rt2x00dev->spec; |
@@ -5130,6 +5847,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
5130 | char *default_power2; | 5847 | char *default_power2; |
5131 | unsigned int i; | 5848 | unsigned int i; |
5132 | u16 eeprom; | 5849 | u16 eeprom; |
5850 | u32 reg; | ||
5133 | 5851 | ||
5134 | /* | 5852 | /* |
5135 | * Disable powersaving as default on PCI devices. | 5853 | * Disable powersaving as default on PCI devices. |
@@ -5211,8 +5929,22 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
5211 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 5929 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
5212 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); | 5930 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); |
5213 | spec->channels = rf_vals_3x; | 5931 | spec->channels = rf_vals_3x; |
5932 | } else if (rt2x00_rf(rt2x00dev, RF5592)) { | ||
5933 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | ||
5934 | |||
5935 | rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); | ||
5936 | if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { | ||
5937 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40); | ||
5938 | spec->channels = rf_vals_5592_xtal40; | ||
5939 | } else { | ||
5940 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20); | ||
5941 | spec->channels = rf_vals_5592_xtal20; | ||
5942 | } | ||
5214 | } | 5943 | } |
5215 | 5944 | ||
5945 | if (WARN_ON_ONCE(!spec->channels)) | ||
5946 | return -ENODEV; | ||
5947 | |||
5216 | /* | 5948 | /* |
5217 | * Initialize HT information. | 5949 | * Initialize HT information. |
5218 | */ | 5950 | */ |
@@ -5300,11 +6032,56 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
5300 | return 0; | 6032 | return 0; |
5301 | } | 6033 | } |
5302 | 6034 | ||
6035 | static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev) | ||
6036 | { | ||
6037 | u32 reg; | ||
6038 | u32 rt; | ||
6039 | u32 rev; | ||
6040 | |||
6041 | if (rt2x00_rt(rt2x00dev, RT3290)) | ||
6042 | rt2800_register_read(rt2x00dev, MAC_CSR0_3290, ®); | ||
6043 | else | ||
6044 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
6045 | |||
6046 | rt = rt2x00_get_field32(reg, MAC_CSR0_CHIPSET); | ||
6047 | rev = rt2x00_get_field32(reg, MAC_CSR0_REVISION); | ||
6048 | |||
6049 | switch (rt) { | ||
6050 | case RT2860: | ||
6051 | case RT2872: | ||
6052 | case RT2883: | ||
6053 | case RT3070: | ||
6054 | case RT3071: | ||
6055 | case RT3090: | ||
6056 | case RT3290: | ||
6057 | case RT3352: | ||
6058 | case RT3390: | ||
6059 | case RT3572: | ||
6060 | case RT5390: | ||
6061 | case RT5392: | ||
6062 | case RT5592: | ||
6063 | break; | ||
6064 | default: | ||
6065 | ERROR(rt2x00dev, | ||
6066 | "Invalid RT chipset 0x%04x, rev %04x detected.\n", | ||
6067 | rt, rev); | ||
6068 | return -ENODEV; | ||
6069 | } | ||
6070 | |||
6071 | rt2x00_set_rt(rt2x00dev, rt, rev); | ||
6072 | |||
6073 | return 0; | ||
6074 | } | ||
6075 | |||
5303 | int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) | 6076 | int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) |
5304 | { | 6077 | { |
5305 | int retval; | 6078 | int retval; |
5306 | u32 reg; | 6079 | u32 reg; |
5307 | 6080 | ||
6081 | retval = rt2800_probe_rt(rt2x00dev); | ||
6082 | if (retval) | ||
6083 | return retval; | ||
6084 | |||
5308 | /* | 6085 | /* |
5309 | * Allocate eeprom data. | 6086 | * Allocate eeprom data. |
5310 | */ | 6087 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 48a01aa21f1c..def357eb0586 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/eeprom_93cx6.h> | 41 | #include <linux/eeprom_93cx6.h> |
42 | 42 | ||
43 | #include "rt2x00.h" | 43 | #include "rt2x00.h" |
44 | #include "rt2x00mmio.h" | ||
44 | #include "rt2x00pci.h" | 45 | #include "rt2x00pci.h" |
45 | #include "rt2x00soc.h" | 46 | #include "rt2x00soc.h" |
46 | #include "rt2800lib.h" | 47 | #include "rt2800lib.h" |
@@ -71,7 +72,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
71 | return; | 72 | return; |
72 | 73 | ||
73 | for (i = 0; i < 200; i++) { | 74 | for (i = 0; i < 200; i++) { |
74 | rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); | 75 | rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); |
75 | 76 | ||
76 | if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || | 77 | if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || |
77 | (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || | 78 | (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || |
@@ -85,11 +86,11 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
85 | if (i == 200) | 86 | if (i == 200) |
86 | ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); | 87 | ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); |
87 | 88 | ||
88 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); | 89 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); |
89 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | 90 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); |
90 | } | 91 | } |
91 | 92 | ||
92 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 93 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
93 | static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 94 | static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
94 | { | 95 | { |
95 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); | 96 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); |
@@ -107,7 +108,7 @@ static inline int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | |||
107 | { | 108 | { |
108 | return -ENOMEM; | 109 | return -ENOMEM; |
109 | } | 110 | } |
110 | #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ | 111 | #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */ |
111 | 112 | ||
112 | #ifdef CONFIG_PCI | 113 | #ifdef CONFIG_PCI |
113 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 114 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
@@ -115,7 +116,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | |||
115 | struct rt2x00_dev *rt2x00dev = eeprom->data; | 116 | struct rt2x00_dev *rt2x00dev = eeprom->data; |
116 | u32 reg; | 117 | u32 reg; |
117 | 118 | ||
118 | rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); | 119 | rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, ®); |
119 | 120 | ||
120 | eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); | 121 | eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); |
121 | eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); | 122 | eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); |
@@ -137,7 +138,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom) | |||
137 | rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, | 138 | rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, |
138 | !!eeprom->reg_chip_select); | 139 | !!eeprom->reg_chip_select); |
139 | 140 | ||
140 | rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); | 141 | rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg); |
141 | } | 142 | } |
142 | 143 | ||
143 | static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) | 144 | static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) |
@@ -145,7 +146,7 @@ static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) | |||
145 | struct eeprom_93cx6 eeprom; | 146 | struct eeprom_93cx6 eeprom; |
146 | u32 reg; | 147 | u32 reg; |
147 | 148 | ||
148 | rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); | 149 | rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, ®); |
149 | 150 | ||
150 | eeprom.data = rt2x00dev; | 151 | eeprom.data = rt2x00dev; |
151 | eeprom.register_read = rt2800pci_eepromregister_read; | 152 | eeprom.register_read = rt2800pci_eepromregister_read; |
@@ -209,20 +210,20 @@ static void rt2800pci_start_queue(struct data_queue *queue) | |||
209 | 210 | ||
210 | switch (queue->qid) { | 211 | switch (queue->qid) { |
211 | case QID_RX: | 212 | case QID_RX: |
212 | rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | 213 | rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); |
213 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); | 214 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); |
214 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | 215 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); |
215 | break; | 216 | break; |
216 | case QID_BEACON: | 217 | case QID_BEACON: |
217 | rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 218 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
218 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | 219 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); |
219 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | 220 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); |
220 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | 221 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); |
221 | rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 222 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
222 | 223 | ||
223 | rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, ®); | 224 | rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); |
224 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); | 225 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); |
225 | rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg); | 226 | rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); |
226 | break; | 227 | break; |
227 | default: | 228 | default: |
228 | break; | 229 | break; |
@@ -240,13 +241,13 @@ static void rt2800pci_kick_queue(struct data_queue *queue) | |||
240 | case QID_AC_BE: | 241 | case QID_AC_BE: |
241 | case QID_AC_BK: | 242 | case QID_AC_BK: |
242 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | 243 | entry = rt2x00queue_get_entry(queue, Q_INDEX); |
243 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), | 244 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), |
244 | entry->entry_idx); | 245 | entry->entry_idx); |
245 | break; | 246 | break; |
246 | case QID_MGMT: | 247 | case QID_MGMT: |
247 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | 248 | entry = rt2x00queue_get_entry(queue, Q_INDEX); |
248 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5), | 249 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(5), |
249 | entry->entry_idx); | 250 | entry->entry_idx); |
250 | break; | 251 | break; |
251 | default: | 252 | default: |
252 | break; | 253 | break; |
@@ -260,20 +261,20 @@ static void rt2800pci_stop_queue(struct data_queue *queue) | |||
260 | 261 | ||
261 | switch (queue->qid) { | 262 | switch (queue->qid) { |
262 | case QID_RX: | 263 | case QID_RX: |
263 | rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | 264 | rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); |
264 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); | 265 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); |
265 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | 266 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); |
266 | break; | 267 | break; |
267 | case QID_BEACON: | 268 | case QID_BEACON: |
268 | rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 269 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
269 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); | 270 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); |
270 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); | 271 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); |
271 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | 272 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); |
272 | rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 273 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
273 | 274 | ||
274 | rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, ®); | 275 | rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); |
275 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); | 276 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); |
276 | rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg); | 277 | rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); |
277 | 278 | ||
278 | /* | 279 | /* |
279 | * Wait for current invocation to finish. The tasklet | 280 | * Wait for current invocation to finish. The tasklet |
@@ -313,19 +314,19 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, | |||
313 | */ | 314 | */ |
314 | reg = 0; | 315 | reg = 0; |
315 | rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); | 316 | rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); |
316 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg); | 317 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg); |
317 | 318 | ||
318 | /* | 319 | /* |
319 | * Write firmware to device. | 320 | * Write firmware to device. |
320 | */ | 321 | */ |
321 | rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, | 322 | rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, |
322 | data, len); | 323 | data, len); |
323 | 324 | ||
324 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); | 325 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); |
325 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); | 326 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); |
326 | 327 | ||
327 | rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | 328 | rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0); |
328 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | 329 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); |
329 | 330 | ||
330 | return 0; | 331 | return 0; |
331 | } | 332 | } |
@@ -335,7 +336,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, | |||
335 | */ | 336 | */ |
336 | static bool rt2800pci_get_entry_state(struct queue_entry *entry) | 337 | static bool rt2800pci_get_entry_state(struct queue_entry *entry) |
337 | { | 338 | { |
338 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 339 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
339 | u32 word; | 340 | u32 word; |
340 | 341 | ||
341 | if (entry->queue->qid == QID_RX) { | 342 | if (entry->queue->qid == QID_RX) { |
@@ -351,7 +352,7 @@ static bool rt2800pci_get_entry_state(struct queue_entry *entry) | |||
351 | 352 | ||
352 | static void rt2800pci_clear_entry(struct queue_entry *entry) | 353 | static void rt2800pci_clear_entry(struct queue_entry *entry) |
353 | { | 354 | { |
354 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 355 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
355 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 356 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
356 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 357 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
357 | u32 word; | 358 | u32 word; |
@@ -369,8 +370,8 @@ static void rt2800pci_clear_entry(struct queue_entry *entry) | |||
369 | * Set RX IDX in register to inform hardware that we have | 370 | * Set RX IDX in register to inform hardware that we have |
370 | * handled this entry and it is available for reuse again. | 371 | * handled this entry and it is available for reuse again. |
371 | */ | 372 | */ |
372 | rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, | 373 | rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, |
373 | entry->entry_idx); | 374 | entry->entry_idx); |
374 | } else { | 375 | } else { |
375 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 376 | rt2x00_desc_read(entry_priv->desc, 1, &word); |
376 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); | 377 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); |
@@ -380,60 +381,65 @@ static void rt2800pci_clear_entry(struct queue_entry *entry) | |||
380 | 381 | ||
381 | static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) | 382 | static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) |
382 | { | 383 | { |
383 | struct queue_entry_priv_pci *entry_priv; | 384 | struct queue_entry_priv_mmio *entry_priv; |
384 | 385 | ||
385 | /* | 386 | /* |
386 | * Initialize registers. | 387 | * Initialize registers. |
387 | */ | 388 | */ |
388 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; | 389 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; |
389 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); | 390 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0, |
390 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0, | 391 | entry_priv->desc_dma); |
391 | rt2x00dev->tx[0].limit); | 392 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0, |
392 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0); | 393 | rt2x00dev->tx[0].limit); |
393 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0); | 394 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0); |
395 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0); | ||
394 | 396 | ||
395 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; | 397 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; |
396 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); | 398 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1, |
397 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1, | 399 | entry_priv->desc_dma); |
398 | rt2x00dev->tx[1].limit); | 400 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1, |
399 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0); | 401 | rt2x00dev->tx[1].limit); |
400 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0); | 402 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0); |
403 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0); | ||
401 | 404 | ||
402 | entry_priv = rt2x00dev->tx[2].entries[0].priv_data; | 405 | entry_priv = rt2x00dev->tx[2].entries[0].priv_data; |
403 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); | 406 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2, |
404 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2, | 407 | entry_priv->desc_dma); |
405 | rt2x00dev->tx[2].limit); | 408 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2, |
406 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0); | 409 | rt2x00dev->tx[2].limit); |
407 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0); | 410 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0); |
411 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0); | ||
408 | 412 | ||
409 | entry_priv = rt2x00dev->tx[3].entries[0].priv_data; | 413 | entry_priv = rt2x00dev->tx[3].entries[0].priv_data; |
410 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); | 414 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3, |
411 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3, | 415 | entry_priv->desc_dma); |
412 | rt2x00dev->tx[3].limit); | 416 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3, |
413 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0); | 417 | rt2x00dev->tx[3].limit); |
414 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0); | 418 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0); |
415 | 419 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0); | |
416 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR4, 0); | 420 | |
417 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT4, 0); | 421 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0); |
418 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX4, 0); | 422 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0); |
419 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX4, 0); | 423 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX4, 0); |
420 | 424 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX4, 0); | |
421 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR5, 0); | 425 | |
422 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT5, 0); | 426 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR5, 0); |
423 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX5, 0); | 427 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT5, 0); |
424 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX5, 0); | 428 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX5, 0); |
429 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX5, 0); | ||
425 | 430 | ||
426 | entry_priv = rt2x00dev->rx->entries[0].priv_data; | 431 | entry_priv = rt2x00dev->rx->entries[0].priv_data; |
427 | rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); | 432 | rt2x00mmio_register_write(rt2x00dev, RX_BASE_PTR, |
428 | rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, | 433 | entry_priv->desc_dma); |
429 | rt2x00dev->rx[0].limit); | 434 | rt2x00mmio_register_write(rt2x00dev, RX_MAX_CNT, |
430 | rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, | 435 | rt2x00dev->rx[0].limit); |
431 | rt2x00dev->rx[0].limit - 1); | 436 | rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, |
432 | rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0); | 437 | rt2x00dev->rx[0].limit - 1); |
438 | rt2x00mmio_register_write(rt2x00dev, RX_DRX_IDX, 0); | ||
433 | 439 | ||
434 | rt2800_disable_wpdma(rt2x00dev); | 440 | rt2800_disable_wpdma(rt2x00dev); |
435 | 441 | ||
436 | rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0); | 442 | rt2x00mmio_register_write(rt2x00dev, DELAY_INT_CFG, 0); |
437 | 443 | ||
438 | return 0; | 444 | return 0; |
439 | } | 445 | } |
@@ -452,8 +458,8 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
452 | * should clear the register to assure a clean state. | 458 | * should clear the register to assure a clean state. |
453 | */ | 459 | */ |
454 | if (state == STATE_RADIO_IRQ_ON) { | 460 | if (state == STATE_RADIO_IRQ_ON) { |
455 | rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | 461 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); |
456 | rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | 462 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); |
457 | } | 463 | } |
458 | 464 | ||
459 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | 465 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
@@ -465,7 +471,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
465 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); | 471 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); |
466 | rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, 1); | 472 | rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, 1); |
467 | } | 473 | } |
468 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); | 474 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); |
469 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | 475 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
470 | 476 | ||
471 | if (state == STATE_RADIO_IRQ_OFF) { | 477 | if (state == STATE_RADIO_IRQ_OFF) { |
@@ -487,7 +493,7 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
487 | /* | 493 | /* |
488 | * Reset DMA indexes | 494 | * Reset DMA indexes |
489 | */ | 495 | */ |
490 | rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | 496 | rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, ®); |
491 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | 497 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); |
492 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | 498 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); |
493 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | 499 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); |
@@ -495,29 +501,29 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
495 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | 501 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); |
496 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | 502 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); |
497 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | 503 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); |
498 | rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | 504 | rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg); |
499 | 505 | ||
500 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | 506 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); |
501 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | 507 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); |
502 | 508 | ||
503 | if (rt2x00_is_pcie(rt2x00dev) && | 509 | if (rt2x00_is_pcie(rt2x00dev) && |
504 | (rt2x00_rt(rt2x00dev, RT3572) || | 510 | (rt2x00_rt(rt2x00dev, RT3572) || |
505 | rt2x00_rt(rt2x00dev, RT5390) || | 511 | rt2x00_rt(rt2x00dev, RT5390) || |
506 | rt2x00_rt(rt2x00dev, RT5392))) { | 512 | rt2x00_rt(rt2x00dev, RT5392))) { |
507 | rt2x00pci_register_read(rt2x00dev, AUX_CTRL, ®); | 513 | rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, ®); |
508 | rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); | 514 | rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); |
509 | rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); | 515 | rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); |
510 | rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg); | 516 | rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg); |
511 | } | 517 | } |
512 | 518 | ||
513 | rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | 519 | rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); |
514 | 520 | ||
515 | reg = 0; | 521 | reg = 0; |
516 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); | 522 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); |
517 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | 523 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); |
518 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | 524 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); |
519 | 525 | ||
520 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | 526 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); |
521 | 527 | ||
522 | return 0; | 528 | return 0; |
523 | } | 529 | } |
@@ -537,8 +543,8 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
537 | return retval; | 543 | return retval; |
538 | 544 | ||
539 | /* After resume MCU_BOOT_SIGNAL will trash these. */ | 545 | /* After resume MCU_BOOT_SIGNAL will trash these. */ |
540 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); | 546 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); |
541 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | 547 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); |
542 | 548 | ||
543 | rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02); | 549 | rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02); |
544 | rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF); | 550 | rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF); |
@@ -553,8 +559,8 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
553 | { | 559 | { |
554 | if (rt2x00_is_soc(rt2x00dev)) { | 560 | if (rt2x00_is_soc(rt2x00dev)) { |
555 | rt2800_disable_radio(rt2x00dev); | 561 | rt2800_disable_radio(rt2x00dev); |
556 | rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0); | 562 | rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0); |
557 | rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0); | 563 | rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0); |
558 | } | 564 | } |
559 | } | 565 | } |
560 | 566 | ||
@@ -566,10 +572,10 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, | |||
566 | 0, 0x02); | 572 | 0, 0x02); |
567 | rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); | 573 | rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); |
568 | } else if (state == STATE_SLEEP) { | 574 | } else if (state == STATE_SLEEP) { |
569 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, | 575 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, |
570 | 0xffffffff); | 576 | 0xffffffff); |
571 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, | 577 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, |
572 | 0xffffffff); | 578 | 0xffffffff); |
573 | rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP, | 579 | rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP, |
574 | 0xff, 0x01); | 580 | 0xff, 0x01); |
575 | } | 581 | } |
@@ -628,7 +634,7 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry, | |||
628 | struct txentry_desc *txdesc) | 634 | struct txentry_desc *txdesc) |
629 | { | 635 | { |
630 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 636 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
631 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 637 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
632 | __le32 *txd = entry_priv->desc; | 638 | __le32 *txd = entry_priv->desc; |
633 | u32 word; | 639 | u32 word; |
634 | 640 | ||
@@ -682,7 +688,7 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry, | |||
682 | static void rt2800pci_fill_rxdone(struct queue_entry *entry, | 688 | static void rt2800pci_fill_rxdone(struct queue_entry *entry, |
683 | struct rxdone_entry_desc *rxdesc) | 689 | struct rxdone_entry_desc *rxdesc) |
684 | { | 690 | { |
685 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 691 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
686 | __le32 *rxd = entry_priv->desc; | 692 | __le32 *rxd = entry_priv->desc; |
687 | u32 word; | 693 | u32 word; |
688 | 694 | ||
@@ -729,6 +735,11 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
729 | * Process the RXWI structure that is at the start of the buffer. | 735 | * Process the RXWI structure that is at the start of the buffer. |
730 | */ | 736 | */ |
731 | rt2800_process_rxwi(entry, rxdesc); | 737 | rt2800_process_rxwi(entry, rxdesc); |
738 | |||
739 | /* | ||
740 | * Remove RXWI descriptor from start of buffer. | ||
741 | */ | ||
742 | skb_pull(entry->skb, RXWI_DESC_SIZE); | ||
732 | } | 743 | } |
733 | 744 | ||
734 | /* | 745 | /* |
@@ -742,10 +753,90 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | |||
742 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | 753 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); |
743 | } | 754 | } |
744 | 755 | ||
756 | static bool rt2800pci_txdone_entry_check(struct queue_entry *entry, u32 status) | ||
757 | { | ||
758 | __le32 *txwi; | ||
759 | u32 word; | ||
760 | int wcid, tx_wcid; | ||
761 | |||
762 | wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID); | ||
763 | |||
764 | txwi = rt2800_drv_get_txwi(entry); | ||
765 | rt2x00_desc_read(txwi, 1, &word); | ||
766 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
767 | |||
768 | return (tx_wcid == wcid); | ||
769 | } | ||
770 | |||
771 | static bool rt2800pci_txdone_find_entry(struct queue_entry *entry, void *data) | ||
772 | { | ||
773 | u32 status = *(u32 *)data; | ||
774 | |||
775 | /* | ||
776 | * rt2800pci hardware might reorder frames when exchanging traffic | ||
777 | * with multiple BA enabled STAs. | ||
778 | * | ||
779 | * For example, a tx queue | ||
780 | * [ STA1 | STA2 | STA1 | STA2 ] | ||
781 | * can result in tx status reports | ||
782 | * [ STA1 | STA1 | STA2 | STA2 ] | ||
783 | * when the hw decides to aggregate the frames for STA1 into one AMPDU. | ||
784 | * | ||
785 | * To mitigate this effect, associate the tx status to the first frame | ||
786 | * in the tx queue with a matching wcid. | ||
787 | */ | ||
788 | if (rt2800pci_txdone_entry_check(entry, status) && | ||
789 | !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
790 | /* | ||
791 | * Got a matching frame, associate the tx status with | ||
792 | * the frame | ||
793 | */ | ||
794 | entry->status = status; | ||
795 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
796 | return true; | ||
797 | } | ||
798 | |||
799 | /* Check the next frame */ | ||
800 | return false; | ||
801 | } | ||
802 | |||
803 | static bool rt2800pci_txdone_match_first(struct queue_entry *entry, void *data) | ||
804 | { | ||
805 | u32 status = *(u32 *)data; | ||
806 | |||
807 | /* | ||
808 | * Find the first frame without tx status and assign this status to it | ||
809 | * regardless if it matches or not. | ||
810 | */ | ||
811 | if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
812 | /* | ||
813 | * Got a matching frame, associate the tx status with | ||
814 | * the frame | ||
815 | */ | ||
816 | entry->status = status; | ||
817 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
818 | return true; | ||
819 | } | ||
820 | |||
821 | /* Check the next frame */ | ||
822 | return false; | ||
823 | } | ||
824 | static bool rt2800pci_txdone_release_entries(struct queue_entry *entry, | ||
825 | void *data) | ||
826 | { | ||
827 | if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
828 | rt2800_txdone_entry(entry, entry->status, | ||
829 | rt2800pci_get_txwi(entry)); | ||
830 | return false; | ||
831 | } | ||
832 | |||
833 | /* No more frames to release */ | ||
834 | return true; | ||
835 | } | ||
836 | |||
745 | static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | 837 | static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) |
746 | { | 838 | { |
747 | struct data_queue *queue; | 839 | struct data_queue *queue; |
748 | struct queue_entry *entry; | ||
749 | u32 status; | 840 | u32 status; |
750 | u8 qid; | 841 | u8 qid; |
751 | int max_tx_done = 16; | 842 | int max_tx_done = 16; |
@@ -783,8 +874,33 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
783 | break; | 874 | break; |
784 | } | 875 | } |
785 | 876 | ||
786 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 877 | /* |
787 | rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry)); | 878 | * Let's associate this tx status with the first |
879 | * matching frame. | ||
880 | */ | ||
881 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
882 | Q_INDEX, &status, | ||
883 | rt2800pci_txdone_find_entry)) { | ||
884 | /* | ||
885 | * We cannot match the tx status to any frame, so just | ||
886 | * use the first one. | ||
887 | */ | ||
888 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
889 | Q_INDEX, &status, | ||
890 | rt2800pci_txdone_match_first)) { | ||
891 | WARNING(rt2x00dev, "No frame found for TX " | ||
892 | "status on queue %u, dropping\n", | ||
893 | qid); | ||
894 | break; | ||
895 | } | ||
896 | } | ||
897 | |||
898 | /* | ||
899 | * Release all frames with a valid tx status. | ||
900 | */ | ||
901 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
902 | Q_INDEX, NULL, | ||
903 | rt2800pci_txdone_release_entries); | ||
788 | 904 | ||
789 | if (--max_tx_done == 0) | 905 | if (--max_tx_done == 0) |
790 | break; | 906 | break; |
@@ -803,9 +919,9 @@ static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, | |||
803 | * access needs locking. | 919 | * access needs locking. |
804 | */ | 920 | */ |
805 | spin_lock_irq(&rt2x00dev->irqmask_lock); | 921 | spin_lock_irq(&rt2x00dev->irqmask_lock); |
806 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | 922 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); |
807 | rt2x00_set_field32(®, irq_field, 1); | 923 | rt2x00_set_field32(®, irq_field, 1); |
808 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); | 924 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); |
809 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | 925 | spin_unlock_irq(&rt2x00dev->irqmask_lock); |
810 | } | 926 | } |
811 | 927 | ||
@@ -846,15 +962,15 @@ static void rt2800pci_tbtt_tasklet(unsigned long data) | |||
846 | * interval every 64 beacons by 64us to mitigate this effect. | 962 | * interval every 64 beacons by 64us to mitigate this effect. |
847 | */ | 963 | */ |
848 | if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) { | 964 | if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) { |
849 | rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 965 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
850 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | 966 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, |
851 | (rt2x00dev->beacon_int * 16) - 1); | 967 | (rt2x00dev->beacon_int * 16) - 1); |
852 | rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 968 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
853 | } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) { | 969 | } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) { |
854 | rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 970 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
855 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | 971 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, |
856 | (rt2x00dev->beacon_int * 16)); | 972 | (rt2x00dev->beacon_int * 16)); |
857 | rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 973 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
858 | } | 974 | } |
859 | drv_data->tbtt_tick++; | 975 | drv_data->tbtt_tick++; |
860 | drv_data->tbtt_tick %= BCN_TBTT_OFFSET; | 976 | drv_data->tbtt_tick %= BCN_TBTT_OFFSET; |
@@ -867,7 +983,7 @@ static void rt2800pci_tbtt_tasklet(unsigned long data) | |||
867 | static void rt2800pci_rxdone_tasklet(unsigned long data) | 983 | static void rt2800pci_rxdone_tasklet(unsigned long data) |
868 | { | 984 | { |
869 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | 985 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
870 | if (rt2x00pci_rxdone(rt2x00dev)) | 986 | if (rt2x00mmio_rxdone(rt2x00dev)) |
871 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | 987 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); |
872 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 988 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
873 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); | 989 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); |
@@ -905,7 +1021,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) | |||
905 | * need to lock the kfifo. | 1021 | * need to lock the kfifo. |
906 | */ | 1022 | */ |
907 | for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { | 1023 | for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { |
908 | rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status); | 1024 | rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); |
909 | 1025 | ||
910 | if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) | 1026 | if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) |
911 | break; | 1027 | break; |
@@ -927,8 +1043,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | |||
927 | u32 reg, mask; | 1043 | u32 reg, mask; |
928 | 1044 | ||
929 | /* Read status and ACK all interrupts */ | 1045 | /* Read status and ACK all interrupts */ |
930 | rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | 1046 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); |
931 | rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | 1047 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); |
932 | 1048 | ||
933 | if (!reg) | 1049 | if (!reg) |
934 | return IRQ_NONE; | 1050 | return IRQ_NONE; |
@@ -968,9 +1084,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | |||
968 | * the tasklet will reenable the appropriate interrupts. | 1084 | * the tasklet will reenable the appropriate interrupts. |
969 | */ | 1085 | */ |
970 | spin_lock(&rt2x00dev->irqmask_lock); | 1086 | spin_lock(&rt2x00dev->irqmask_lock); |
971 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | 1087 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); |
972 | reg &= mask; | 1088 | reg &= mask; |
973 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); | 1089 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); |
974 | spin_unlock(&rt2x00dev->irqmask_lock); | 1090 | spin_unlock(&rt2x00dev->irqmask_lock); |
975 | 1091 | ||
976 | return IRQ_HANDLED; | 1092 | return IRQ_HANDLED; |
@@ -1021,13 +1137,13 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = { | |||
1021 | }; | 1137 | }; |
1022 | 1138 | ||
1023 | static const struct rt2800_ops rt2800pci_rt2800_ops = { | 1139 | static const struct rt2800_ops rt2800pci_rt2800_ops = { |
1024 | .register_read = rt2x00pci_register_read, | 1140 | .register_read = rt2x00mmio_register_read, |
1025 | .register_read_lock = rt2x00pci_register_read, /* same for PCI */ | 1141 | .register_read_lock = rt2x00mmio_register_read, /* same for PCI */ |
1026 | .register_write = rt2x00pci_register_write, | 1142 | .register_write = rt2x00mmio_register_write, |
1027 | .register_write_lock = rt2x00pci_register_write, /* same for PCI */ | 1143 | .register_write_lock = rt2x00mmio_register_write, /* same for PCI */ |
1028 | .register_multiread = rt2x00pci_register_multiread, | 1144 | .register_multiread = rt2x00mmio_register_multiread, |
1029 | .register_multiwrite = rt2x00pci_register_multiwrite, | 1145 | .register_multiwrite = rt2x00mmio_register_multiwrite, |
1030 | .regbusy_read = rt2x00pci_regbusy_read, | 1146 | .regbusy_read = rt2x00mmio_regbusy_read, |
1031 | .read_eeprom = rt2800pci_read_eeprom, | 1147 | .read_eeprom = rt2800pci_read_eeprom, |
1032 | .hwcrypt_disabled = rt2800pci_hwcrypt_disabled, | 1148 | .hwcrypt_disabled = rt2800pci_hwcrypt_disabled, |
1033 | .drv_write_firmware = rt2800pci_write_firmware, | 1149 | .drv_write_firmware = rt2800pci_write_firmware, |
@@ -1046,8 +1162,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
1046 | .get_firmware_name = rt2800pci_get_firmware_name, | 1162 | .get_firmware_name = rt2800pci_get_firmware_name, |
1047 | .check_firmware = rt2800_check_firmware, | 1163 | .check_firmware = rt2800_check_firmware, |
1048 | .load_firmware = rt2800_load_firmware, | 1164 | .load_firmware = rt2800_load_firmware, |
1049 | .initialize = rt2x00pci_initialize, | 1165 | .initialize = rt2x00mmio_initialize, |
1050 | .uninitialize = rt2x00pci_uninitialize, | 1166 | .uninitialize = rt2x00mmio_uninitialize, |
1051 | .get_entry_state = rt2800pci_get_entry_state, | 1167 | .get_entry_state = rt2800pci_get_entry_state, |
1052 | .clear_entry = rt2800pci_clear_entry, | 1168 | .clear_entry = rt2800pci_clear_entry, |
1053 | .set_device_state = rt2800pci_set_device_state, | 1169 | .set_device_state = rt2800pci_set_device_state, |
@@ -1060,7 +1176,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
1060 | .start_queue = rt2800pci_start_queue, | 1176 | .start_queue = rt2800pci_start_queue, |
1061 | .kick_queue = rt2800pci_kick_queue, | 1177 | .kick_queue = rt2800pci_kick_queue, |
1062 | .stop_queue = rt2800pci_stop_queue, | 1178 | .stop_queue = rt2800pci_stop_queue, |
1063 | .flush_queue = rt2x00pci_flush_queue, | 1179 | .flush_queue = rt2x00mmio_flush_queue, |
1064 | .write_tx_desc = rt2800pci_write_tx_desc, | 1180 | .write_tx_desc = rt2800pci_write_tx_desc, |
1065 | .write_tx_data = rt2800_write_tx_data, | 1181 | .write_tx_data = rt2800_write_tx_data, |
1066 | .write_beacon = rt2800_write_beacon, | 1182 | .write_beacon = rt2800_write_beacon, |
@@ -1081,21 +1197,21 @@ static const struct data_queue_desc rt2800pci_queue_rx = { | |||
1081 | .entry_num = 128, | 1197 | .entry_num = 128, |
1082 | .data_size = AGGREGATION_SIZE, | 1198 | .data_size = AGGREGATION_SIZE, |
1083 | .desc_size = RXD_DESC_SIZE, | 1199 | .desc_size = RXD_DESC_SIZE, |
1084 | .priv_size = sizeof(struct queue_entry_priv_pci), | 1200 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
1085 | }; | 1201 | }; |
1086 | 1202 | ||
1087 | static const struct data_queue_desc rt2800pci_queue_tx = { | 1203 | static const struct data_queue_desc rt2800pci_queue_tx = { |
1088 | .entry_num = 64, | 1204 | .entry_num = 64, |
1089 | .data_size = AGGREGATION_SIZE, | 1205 | .data_size = AGGREGATION_SIZE, |
1090 | .desc_size = TXD_DESC_SIZE, | 1206 | .desc_size = TXD_DESC_SIZE, |
1091 | .priv_size = sizeof(struct queue_entry_priv_pci), | 1207 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
1092 | }; | 1208 | }; |
1093 | 1209 | ||
1094 | static const struct data_queue_desc rt2800pci_queue_bcn = { | 1210 | static const struct data_queue_desc rt2800pci_queue_bcn = { |
1095 | .entry_num = 8, | 1211 | .entry_num = 8, |
1096 | .data_size = 0, /* No DMA required for beacons */ | 1212 | .data_size = 0, /* No DMA required for beacons */ |
1097 | .desc_size = TXWI_DESC_SIZE, | 1213 | .desc_size = TXWI_DESC_SIZE, |
1098 | .priv_size = sizeof(struct queue_entry_priv_pci), | 1214 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
1099 | }; | 1215 | }; |
1100 | 1216 | ||
1101 | static const struct rt2x00_ops rt2800pci_ops = { | 1217 | static const struct rt2x00_ops rt2800pci_ops = { |
@@ -1177,7 +1293,7 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); | |||
1177 | #endif /* CONFIG_PCI */ | 1293 | #endif /* CONFIG_PCI */ |
1178 | MODULE_LICENSE("GPL"); | 1294 | MODULE_LICENSE("GPL"); |
1179 | 1295 | ||
1180 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1296 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1181 | static int rt2800soc_probe(struct platform_device *pdev) | 1297 | static int rt2800soc_probe(struct platform_device *pdev) |
1182 | { | 1298 | { |
1183 | return rt2x00soc_probe(pdev, &rt2800pci_ops); | 1299 | return rt2x00soc_probe(pdev, &rt2800pci_ops); |
@@ -1194,7 +1310,7 @@ static struct platform_driver rt2800soc_driver = { | |||
1194 | .suspend = rt2x00soc_suspend, | 1310 | .suspend = rt2x00soc_suspend, |
1195 | .resume = rt2x00soc_resume, | 1311 | .resume = rt2x00soc_resume, |
1196 | }; | 1312 | }; |
1197 | #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ | 1313 | #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */ |
1198 | 1314 | ||
1199 | #ifdef CONFIG_PCI | 1315 | #ifdef CONFIG_PCI |
1200 | static int rt2800pci_probe(struct pci_dev *pci_dev, | 1316 | static int rt2800pci_probe(struct pci_dev *pci_dev, |
@@ -1217,7 +1333,7 @@ static int __init rt2800pci_init(void) | |||
1217 | { | 1333 | { |
1218 | int ret = 0; | 1334 | int ret = 0; |
1219 | 1335 | ||
1220 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1336 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1221 | ret = platform_driver_register(&rt2800soc_driver); | 1337 | ret = platform_driver_register(&rt2800soc_driver); |
1222 | if (ret) | 1338 | if (ret) |
1223 | return ret; | 1339 | return ret; |
@@ -1225,7 +1341,7 @@ static int __init rt2800pci_init(void) | |||
1225 | #ifdef CONFIG_PCI | 1341 | #ifdef CONFIG_PCI |
1226 | ret = pci_register_driver(&rt2800pci_driver); | 1342 | ret = pci_register_driver(&rt2800pci_driver); |
1227 | if (ret) { | 1343 | if (ret) { |
1228 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1344 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1229 | platform_driver_unregister(&rt2800soc_driver); | 1345 | platform_driver_unregister(&rt2800soc_driver); |
1230 | #endif | 1346 | #endif |
1231 | return ret; | 1347 | return ret; |
@@ -1240,7 +1356,7 @@ static void __exit rt2800pci_exit(void) | |||
1240 | #ifdef CONFIG_PCI | 1356 | #ifdef CONFIG_PCI |
1241 | pci_unregister_driver(&rt2800pci_driver); | 1357 | pci_unregister_driver(&rt2800pci_driver); |
1242 | #endif | 1358 | #endif |
1243 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1359 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1244 | platform_driver_unregister(&rt2800soc_driver); | 1360 | platform_driver_unregister(&rt2800soc_driver); |
1245 | #endif | 1361 | #endif |
1246 | } | 1362 | } |
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 041b392f4f47..0d02d16ca166 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 | */ |
@@ -1100,6 +1106,23 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, | |||
1100 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); | 1106 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); |
1101 | } | 1107 | } |
1102 | 1108 | ||
1109 | static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev, | ||
1110 | const u16 rt, const u16 rev) | ||
1111 | { | ||
1112 | rt2x00dev->chip.rt = rt; | ||
1113 | rt2x00dev->chip.rev = rev; | ||
1114 | |||
1115 | INFO(rt2x00dev, "RT chipset %04x, rev %04x detected\n", | ||
1116 | rt2x00dev->chip.rt, rt2x00dev->chip.rev); | ||
1117 | } | ||
1118 | |||
1119 | static inline void rt2x00_set_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) | ||
1120 | { | ||
1121 | rt2x00dev->chip.rf = rf; | ||
1122 | |||
1123 | INFO(rt2x00dev, "RF chipset %04x detected\n", rt2x00dev->chip.rf); | ||
1124 | } | ||
1125 | |||
1103 | static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) | 1126 | static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) |
1104 | { | 1127 | { |
1105 | return (rt2x00dev->chip.rt == rt); | 1128 | return (rt2x00dev->chip.rt == rt); |
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/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c new file mode 100644 index 000000000000..06c766930b15 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00mmio.c | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | <http://rt2x00.serialmonkey.com> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the | ||
17 | Free Software Foundation, Inc., | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | Module: rt2x00mmio | ||
23 | Abstract: rt2x00 generic mmio device routines. | ||
24 | */ | ||
25 | |||
26 | #include <linux/dma-mapping.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/slab.h> | ||
30 | |||
31 | #include "rt2x00.h" | ||
32 | #include "rt2x00mmio.h" | ||
33 | |||
34 | /* | ||
35 | * Register access. | ||
36 | */ | ||
37 | int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
38 | const unsigned int offset, | ||
39 | const struct rt2x00_field32 field, | ||
40 | u32 *reg) | ||
41 | { | ||
42 | unsigned int i; | ||
43 | |||
44 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | ||
45 | return 0; | ||
46 | |||
47 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
48 | rt2x00mmio_register_read(rt2x00dev, offset, reg); | ||
49 | if (!rt2x00_get_field32(*reg, field)) | ||
50 | return 1; | ||
51 | udelay(REGISTER_BUSY_DELAY); | ||
52 | } | ||
53 | |||
54 | printk_once(KERN_ERR "%s() Indirect register access failed: " | ||
55 | "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg); | ||
56 | *reg = ~0; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | EXPORT_SYMBOL_GPL(rt2x00mmio_regbusy_read); | ||
61 | |||
62 | bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev) | ||
63 | { | ||
64 | struct data_queue *queue = rt2x00dev->rx; | ||
65 | struct queue_entry *entry; | ||
66 | struct queue_entry_priv_mmio *entry_priv; | ||
67 | struct skb_frame_desc *skbdesc; | ||
68 | int max_rx = 16; | ||
69 | |||
70 | while (--max_rx) { | ||
71 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
72 | entry_priv = entry->priv_data; | ||
73 | |||
74 | if (rt2x00dev->ops->lib->get_entry_state(entry)) | ||
75 | break; | ||
76 | |||
77 | /* | ||
78 | * Fill in desc fields of the skb descriptor | ||
79 | */ | ||
80 | skbdesc = get_skb_frame_desc(entry->skb); | ||
81 | skbdesc->desc = entry_priv->desc; | ||
82 | skbdesc->desc_len = entry->queue->desc_size; | ||
83 | |||
84 | /* | ||
85 | * DMA is already done, notify rt2x00lib that | ||
86 | * it finished successfully. | ||
87 | */ | ||
88 | rt2x00lib_dmastart(entry); | ||
89 | rt2x00lib_dmadone(entry); | ||
90 | |||
91 | /* | ||
92 | * Send the frame to rt2x00lib for further processing. | ||
93 | */ | ||
94 | rt2x00lib_rxdone(entry, GFP_ATOMIC); | ||
95 | } | ||
96 | |||
97 | return !max_rx; | ||
98 | } | ||
99 | EXPORT_SYMBOL_GPL(rt2x00mmio_rxdone); | ||
100 | |||
101 | void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop) | ||
102 | { | ||
103 | unsigned int i; | ||
104 | |||
105 | for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++) | ||
106 | msleep(10); | ||
107 | } | ||
108 | EXPORT_SYMBOL_GPL(rt2x00mmio_flush_queue); | ||
109 | |||
110 | /* | ||
111 | * Device initialization handlers. | ||
112 | */ | ||
113 | static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, | ||
114 | struct data_queue *queue) | ||
115 | { | ||
116 | struct queue_entry_priv_mmio *entry_priv; | ||
117 | void *addr; | ||
118 | dma_addr_t dma; | ||
119 | unsigned int i; | ||
120 | |||
121 | /* | ||
122 | * Allocate DMA memory for descriptor and buffer. | ||
123 | */ | ||
124 | addr = dma_alloc_coherent(rt2x00dev->dev, | ||
125 | queue->limit * queue->desc_size, | ||
126 | &dma, GFP_KERNEL); | ||
127 | if (!addr) | ||
128 | return -ENOMEM; | ||
129 | |||
130 | memset(addr, 0, queue->limit * queue->desc_size); | ||
131 | |||
132 | /* | ||
133 | * Initialize all queue entries to contain valid addresses. | ||
134 | */ | ||
135 | for (i = 0; i < queue->limit; i++) { | ||
136 | entry_priv = queue->entries[i].priv_data; | ||
137 | entry_priv->desc = addr + i * queue->desc_size; | ||
138 | entry_priv->desc_dma = dma + i * queue->desc_size; | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static void rt2x00mmio_free_queue_dma(struct rt2x00_dev *rt2x00dev, | ||
145 | struct data_queue *queue) | ||
146 | { | ||
147 | struct queue_entry_priv_mmio *entry_priv = | ||
148 | queue->entries[0].priv_data; | ||
149 | |||
150 | if (entry_priv->desc) | ||
151 | dma_free_coherent(rt2x00dev->dev, | ||
152 | queue->limit * queue->desc_size, | ||
153 | entry_priv->desc, entry_priv->desc_dma); | ||
154 | entry_priv->desc = NULL; | ||
155 | } | ||
156 | |||
157 | int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev) | ||
158 | { | ||
159 | struct data_queue *queue; | ||
160 | int status; | ||
161 | |||
162 | /* | ||
163 | * Allocate DMA | ||
164 | */ | ||
165 | queue_for_each(rt2x00dev, queue) { | ||
166 | status = rt2x00mmio_alloc_queue_dma(rt2x00dev, queue); | ||
167 | if (status) | ||
168 | goto exit; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * Register interrupt handler. | ||
173 | */ | ||
174 | status = request_irq(rt2x00dev->irq, | ||
175 | rt2x00dev->ops->lib->irq_handler, | ||
176 | IRQF_SHARED, rt2x00dev->name, rt2x00dev); | ||
177 | if (status) { | ||
178 | ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", | ||
179 | rt2x00dev->irq, status); | ||
180 | goto exit; | ||
181 | } | ||
182 | |||
183 | return 0; | ||
184 | |||
185 | exit: | ||
186 | queue_for_each(rt2x00dev, queue) | ||
187 | rt2x00mmio_free_queue_dma(rt2x00dev, queue); | ||
188 | |||
189 | return status; | ||
190 | } | ||
191 | EXPORT_SYMBOL_GPL(rt2x00mmio_initialize); | ||
192 | |||
193 | void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev) | ||
194 | { | ||
195 | struct data_queue *queue; | ||
196 | |||
197 | /* | ||
198 | * Free irq line. | ||
199 | */ | ||
200 | free_irq(rt2x00dev->irq, rt2x00dev); | ||
201 | |||
202 | /* | ||
203 | * Free DMA | ||
204 | */ | ||
205 | queue_for_each(rt2x00dev, queue) | ||
206 | rt2x00mmio_free_queue_dma(rt2x00dev, queue); | ||
207 | } | ||
208 | EXPORT_SYMBOL_GPL(rt2x00mmio_uninitialize); | ||
209 | |||
210 | /* | ||
211 | * rt2x00mmio module information. | ||
212 | */ | ||
213 | MODULE_AUTHOR(DRV_PROJECT); | ||
214 | MODULE_VERSION(DRV_VERSION); | ||
215 | MODULE_DESCRIPTION("rt2x00 mmio library"); | ||
216 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.h b/drivers/net/wireless/rt2x00/rt2x00mmio.h new file mode 100644 index 000000000000..cda3dbcf7ead --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00mmio.h | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | <http://rt2x00.serialmonkey.com> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the | ||
17 | Free Software Foundation, Inc., | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | Module: rt2x00mmio | ||
23 | Abstract: Data structures for the rt2x00mmio module. | ||
24 | */ | ||
25 | |||
26 | #ifndef RT2X00MMIO_H | ||
27 | #define RT2X00MMIO_H | ||
28 | |||
29 | #include <linux/io.h> | ||
30 | |||
31 | /* | ||
32 | * Register access. | ||
33 | */ | ||
34 | static inline void rt2x00mmio_register_read(struct rt2x00_dev *rt2x00dev, | ||
35 | const unsigned int offset, | ||
36 | u32 *value) | ||
37 | { | ||
38 | *value = readl(rt2x00dev->csr.base + offset); | ||
39 | } | ||
40 | |||
41 | static inline void rt2x00mmio_register_multiread(struct rt2x00_dev *rt2x00dev, | ||
42 | const unsigned int offset, | ||
43 | void *value, const u32 length) | ||
44 | { | ||
45 | memcpy_fromio(value, rt2x00dev->csr.base + offset, length); | ||
46 | } | ||
47 | |||
48 | static inline void rt2x00mmio_register_write(struct rt2x00_dev *rt2x00dev, | ||
49 | const unsigned int offset, | ||
50 | u32 value) | ||
51 | { | ||
52 | writel(value, rt2x00dev->csr.base + offset); | ||
53 | } | ||
54 | |||
55 | static inline void rt2x00mmio_register_multiwrite(struct rt2x00_dev *rt2x00dev, | ||
56 | const unsigned int offset, | ||
57 | const void *value, | ||
58 | const u32 length) | ||
59 | { | ||
60 | __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * rt2x00mmio_regbusy_read - Read from register with busy check | ||
65 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
66 | * @offset: Register offset | ||
67 | * @field: Field to check if register is busy | ||
68 | * @reg: Pointer to where register contents should be stored | ||
69 | * | ||
70 | * This function will read the given register, and checks if the | ||
71 | * register is busy. If it is, it will sleep for a couple of | ||
72 | * microseconds before reading the register again. If the register | ||
73 | * is not read after a certain timeout, this function will return | ||
74 | * FALSE. | ||
75 | */ | ||
76 | int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
77 | const unsigned int offset, | ||
78 | const struct rt2x00_field32 field, | ||
79 | u32 *reg); | ||
80 | |||
81 | /** | ||
82 | * struct queue_entry_priv_mmio: Per entry PCI specific information | ||
83 | * | ||
84 | * @desc: Pointer to device descriptor | ||
85 | * @desc_dma: DMA pointer to &desc. | ||
86 | * @data: Pointer to device's entry memory. | ||
87 | * @data_dma: DMA pointer to &data. | ||
88 | */ | ||
89 | struct queue_entry_priv_mmio { | ||
90 | __le32 *desc; | ||
91 | dma_addr_t desc_dma; | ||
92 | }; | ||
93 | |||
94 | /** | ||
95 | * rt2x00mmio_rxdone - Handle RX done events | ||
96 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
97 | * | ||
98 | * Returns true if there are still rx frames pending and false if all | ||
99 | * pending rx frames were processed. | ||
100 | */ | ||
101 | bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev); | ||
102 | |||
103 | /** | ||
104 | * rt2x00mmio_flush_queue - Flush data queue | ||
105 | * @queue: Data queue to stop | ||
106 | * @drop: True to drop all pending frames. | ||
107 | * | ||
108 | * This will wait for a maximum of 100ms, waiting for the queues | ||
109 | * to become empty. | ||
110 | */ | ||
111 | void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop); | ||
112 | |||
113 | /* | ||
114 | * Device initialization handlers. | ||
115 | */ | ||
116 | int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev); | ||
117 | void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev); | ||
118 | |||
119 | #endif /* RT2X00MMIO_H */ | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index a0c8caef3b0a..e87865e33113 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -33,182 +33,6 @@ | |||
33 | #include "rt2x00pci.h" | 33 | #include "rt2x00pci.h" |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Register access. | ||
37 | */ | ||
38 | int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
39 | const unsigned int offset, | ||
40 | const struct rt2x00_field32 field, | ||
41 | u32 *reg) | ||
42 | { | ||
43 | unsigned int i; | ||
44 | |||
45 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | ||
46 | return 0; | ||
47 | |||
48 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
49 | rt2x00pci_register_read(rt2x00dev, offset, reg); | ||
50 | if (!rt2x00_get_field32(*reg, field)) | ||
51 | return 1; | ||
52 | udelay(REGISTER_BUSY_DELAY); | ||
53 | } | ||
54 | |||
55 | ERROR(rt2x00dev, "Indirect register access failed: " | ||
56 | "offset=0x%.08x, value=0x%.08x\n", offset, *reg); | ||
57 | *reg = ~0; | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); | ||
62 | |||
63 | bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | ||
64 | { | ||
65 | struct data_queue *queue = rt2x00dev->rx; | ||
66 | struct queue_entry *entry; | ||
67 | struct queue_entry_priv_pci *entry_priv; | ||
68 | struct skb_frame_desc *skbdesc; | ||
69 | int max_rx = 16; | ||
70 | |||
71 | while (--max_rx) { | ||
72 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
73 | entry_priv = entry->priv_data; | ||
74 | |||
75 | if (rt2x00dev->ops->lib->get_entry_state(entry)) | ||
76 | break; | ||
77 | |||
78 | /* | ||
79 | * Fill in desc fields of the skb descriptor | ||
80 | */ | ||
81 | skbdesc = get_skb_frame_desc(entry->skb); | ||
82 | skbdesc->desc = entry_priv->desc; | ||
83 | skbdesc->desc_len = entry->queue->desc_size; | ||
84 | |||
85 | /* | ||
86 | * DMA is already done, notify rt2x00lib that | ||
87 | * it finished successfully. | ||
88 | */ | ||
89 | rt2x00lib_dmastart(entry); | ||
90 | rt2x00lib_dmadone(entry); | ||
91 | |||
92 | /* | ||
93 | * Send the frame to rt2x00lib for further processing. | ||
94 | */ | ||
95 | rt2x00lib_rxdone(entry, GFP_ATOMIC); | ||
96 | } | ||
97 | |||
98 | return !max_rx; | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); | ||
101 | |||
102 | void rt2x00pci_flush_queue(struct data_queue *queue, bool drop) | ||
103 | { | ||
104 | unsigned int i; | ||
105 | |||
106 | for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++) | ||
107 | msleep(10); | ||
108 | } | ||
109 | EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue); | ||
110 | |||
111 | /* | ||
112 | * Device initialization handlers. | ||
113 | */ | ||
114 | static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, | ||
115 | struct data_queue *queue) | ||
116 | { | ||
117 | struct queue_entry_priv_pci *entry_priv; | ||
118 | void *addr; | ||
119 | dma_addr_t dma; | ||
120 | unsigned int i; | ||
121 | |||
122 | /* | ||
123 | * Allocate DMA memory for descriptor and buffer. | ||
124 | */ | ||
125 | addr = dma_alloc_coherent(rt2x00dev->dev, | ||
126 | queue->limit * queue->desc_size, | ||
127 | &dma, GFP_KERNEL); | ||
128 | if (!addr) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | memset(addr, 0, queue->limit * queue->desc_size); | ||
132 | |||
133 | /* | ||
134 | * Initialize all queue entries to contain valid addresses. | ||
135 | */ | ||
136 | for (i = 0; i < queue->limit; i++) { | ||
137 | entry_priv = queue->entries[i].priv_data; | ||
138 | entry_priv->desc = addr + i * queue->desc_size; | ||
139 | entry_priv->desc_dma = dma + i * queue->desc_size; | ||
140 | } | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, | ||
146 | struct data_queue *queue) | ||
147 | { | ||
148 | struct queue_entry_priv_pci *entry_priv = | ||
149 | queue->entries[0].priv_data; | ||
150 | |||
151 | if (entry_priv->desc) | ||
152 | dma_free_coherent(rt2x00dev->dev, | ||
153 | queue->limit * queue->desc_size, | ||
154 | entry_priv->desc, entry_priv->desc_dma); | ||
155 | entry_priv->desc = NULL; | ||
156 | } | ||
157 | |||
158 | int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) | ||
159 | { | ||
160 | struct data_queue *queue; | ||
161 | int status; | ||
162 | |||
163 | /* | ||
164 | * Allocate DMA | ||
165 | */ | ||
166 | queue_for_each(rt2x00dev, queue) { | ||
167 | status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue); | ||
168 | if (status) | ||
169 | goto exit; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Register interrupt handler. | ||
174 | */ | ||
175 | status = request_irq(rt2x00dev->irq, | ||
176 | rt2x00dev->ops->lib->irq_handler, | ||
177 | IRQF_SHARED, rt2x00dev->name, rt2x00dev); | ||
178 | if (status) { | ||
179 | ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", | ||
180 | rt2x00dev->irq, status); | ||
181 | goto exit; | ||
182 | } | ||
183 | |||
184 | return 0; | ||
185 | |||
186 | exit: | ||
187 | queue_for_each(rt2x00dev, queue) | ||
188 | rt2x00pci_free_queue_dma(rt2x00dev, queue); | ||
189 | |||
190 | return status; | ||
191 | } | ||
192 | EXPORT_SYMBOL_GPL(rt2x00pci_initialize); | ||
193 | |||
194 | void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) | ||
195 | { | ||
196 | struct data_queue *queue; | ||
197 | |||
198 | /* | ||
199 | * Free irq line. | ||
200 | */ | ||
201 | free_irq(rt2x00dev->irq, rt2x00dev); | ||
202 | |||
203 | /* | ||
204 | * Free DMA | ||
205 | */ | ||
206 | queue_for_each(rt2x00dev, queue) | ||
207 | rt2x00pci_free_queue_dma(rt2x00dev, queue); | ||
208 | } | ||
209 | EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); | ||
210 | |||
211 | /* | ||
212 | * PCI driver handlers. | 36 | * PCI driver handlers. |
213 | */ | 37 | */ |
214 | static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev) | 38 | static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index e2c99f2b9a14..60d90b20f8b9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h | |||
@@ -36,94 +36,6 @@ | |||
36 | #define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops) | 36 | #define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops) |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Register access. | ||
40 | */ | ||
41 | static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev, | ||
42 | const unsigned int offset, | ||
43 | u32 *value) | ||
44 | { | ||
45 | *value = readl(rt2x00dev->csr.base + offset); | ||
46 | } | ||
47 | |||
48 | static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev, | ||
49 | const unsigned int offset, | ||
50 | void *value, const u32 length) | ||
51 | { | ||
52 | memcpy_fromio(value, rt2x00dev->csr.base + offset, length); | ||
53 | } | ||
54 | |||
55 | static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev, | ||
56 | const unsigned int offset, | ||
57 | u32 value) | ||
58 | { | ||
59 | writel(value, rt2x00dev->csr.base + offset); | ||
60 | } | ||
61 | |||
62 | static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, | ||
63 | const unsigned int offset, | ||
64 | const void *value, | ||
65 | const u32 length) | ||
66 | { | ||
67 | __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2); | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * rt2x00pci_regbusy_read - Read from register with busy check | ||
72 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
73 | * @offset: Register offset | ||
74 | * @field: Field to check if register is busy | ||
75 | * @reg: Pointer to where register contents should be stored | ||
76 | * | ||
77 | * This function will read the given register, and checks if the | ||
78 | * register is busy. If it is, it will sleep for a couple of | ||
79 | * microseconds before reading the register again. If the register | ||
80 | * is not read after a certain timeout, this function will return | ||
81 | * FALSE. | ||
82 | */ | ||
83 | int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
84 | const unsigned int offset, | ||
85 | const struct rt2x00_field32 field, | ||
86 | u32 *reg); | ||
87 | |||
88 | /** | ||
89 | * struct queue_entry_priv_pci: Per entry PCI specific information | ||
90 | * | ||
91 | * @desc: Pointer to device descriptor | ||
92 | * @desc_dma: DMA pointer to &desc. | ||
93 | * @data: Pointer to device's entry memory. | ||
94 | * @data_dma: DMA pointer to &data. | ||
95 | */ | ||
96 | struct queue_entry_priv_pci { | ||
97 | __le32 *desc; | ||
98 | dma_addr_t desc_dma; | ||
99 | }; | ||
100 | |||
101 | /** | ||
102 | * rt2x00pci_rxdone - Handle RX done events | ||
103 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
104 | * | ||
105 | * Returns true if there are still rx frames pending and false if all | ||
106 | * pending rx frames were processed. | ||
107 | */ | ||
108 | bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); | ||
109 | |||
110 | /** | ||
111 | * rt2x00pci_flush_queue - Flush data queue | ||
112 | * @queue: Data queue to stop | ||
113 | * @drop: True to drop all pending frames. | ||
114 | * | ||
115 | * This will wait for a maximum of 100ms, waiting for the queues | ||
116 | * to become empty. | ||
117 | */ | ||
118 | void rt2x00pci_flush_queue(struct data_queue *queue, bool drop); | ||
119 | |||
120 | /* | ||
121 | * Device initialization handlers. | ||
122 | */ | ||
123 | int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev); | ||
124 | void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev); | ||
125 | |||
126 | /* | ||
127 | * PCI driver handlers. | 39 | * PCI driver handlers. |
128 | */ | 40 | */ |
129 | int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops); | 41 | int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops); |
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/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index f85035cc836f..fc99258ae777 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/eeprom_93cx6.h> | 35 | #include <linux/eeprom_93cx6.h> |
36 | 36 | ||
37 | #include "rt2x00.h" | 37 | #include "rt2x00.h" |
38 | #include "rt2x00mmio.h" | ||
38 | #include "rt2x00pci.h" | 39 | #include "rt2x00pci.h" |
39 | #include "rt61pci.h" | 40 | #include "rt61pci.h" |
40 | 41 | ||
@@ -57,12 +58,12 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | |||
57 | * and we will print an error. | 58 | * and we will print an error. |
58 | */ | 59 | */ |
59 | #define WAIT_FOR_BBP(__dev, __reg) \ | 60 | #define WAIT_FOR_BBP(__dev, __reg) \ |
60 | rt2x00pci_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) | 61 | rt2x00mmio_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) |
61 | #define WAIT_FOR_RF(__dev, __reg) \ | 62 | #define WAIT_FOR_RF(__dev, __reg) \ |
62 | rt2x00pci_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) | 63 | rt2x00mmio_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) |
63 | #define WAIT_FOR_MCU(__dev, __reg) \ | 64 | #define WAIT_FOR_MCU(__dev, __reg) \ |
64 | rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \ | 65 | rt2x00mmio_regbusy_read((__dev), H2M_MAILBOX_CSR, \ |
65 | H2M_MAILBOX_CSR_OWNER, (__reg)) | 66 | H2M_MAILBOX_CSR_OWNER, (__reg)) |
66 | 67 | ||
67 | static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, | 68 | static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, |
68 | const unsigned int word, const u8 value) | 69 | const unsigned int word, const u8 value) |
@@ -82,7 +83,7 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
82 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | 83 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); |
83 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); | 84 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); |
84 | 85 | ||
85 | rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); | 86 | rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg); |
86 | } | 87 | } |
87 | 88 | ||
88 | mutex_unlock(&rt2x00dev->csr_mutex); | 89 | mutex_unlock(&rt2x00dev->csr_mutex); |
@@ -109,7 +110,7 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
109 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | 110 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); |
110 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); | 111 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); |
111 | 112 | ||
112 | rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); | 113 | rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg); |
113 | 114 | ||
114 | WAIT_FOR_BBP(rt2x00dev, ®); | 115 | WAIT_FOR_BBP(rt2x00dev, ®); |
115 | } | 116 | } |
@@ -137,7 +138,7 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev, | |||
137 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); | 138 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); |
138 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); | 139 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); |
139 | 140 | ||
140 | rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg); | 141 | rt2x00mmio_register_write(rt2x00dev, PHY_CSR4, reg); |
141 | rt2x00_rf_write(rt2x00dev, word, value); | 142 | rt2x00_rf_write(rt2x00dev, word, value); |
142 | } | 143 | } |
143 | 144 | ||
@@ -161,12 +162,12 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
161 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); | 162 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); |
162 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); | 163 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); |
163 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); | 164 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); |
164 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); | 165 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); |
165 | 166 | ||
166 | rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®); | 167 | rt2x00mmio_register_read(rt2x00dev, HOST_CMD_CSR, ®); |
167 | rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); | 168 | rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); |
168 | rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); | 169 | rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); |
169 | rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); | 170 | rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, reg); |
170 | } | 171 | } |
171 | 172 | ||
172 | mutex_unlock(&rt2x00dev->csr_mutex); | 173 | mutex_unlock(&rt2x00dev->csr_mutex); |
@@ -178,7 +179,7 @@ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | |||
178 | struct rt2x00_dev *rt2x00dev = eeprom->data; | 179 | struct rt2x00_dev *rt2x00dev = eeprom->data; |
179 | u32 reg; | 180 | u32 reg; |
180 | 181 | ||
181 | rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); | 182 | rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, ®); |
182 | 183 | ||
183 | eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); | 184 | eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); |
184 | eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); | 185 | eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); |
@@ -200,15 +201,15 @@ static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom) | |||
200 | rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, | 201 | rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, |
201 | !!eeprom->reg_chip_select); | 202 | !!eeprom->reg_chip_select); |
202 | 203 | ||
203 | rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); | 204 | rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg); |
204 | } | 205 | } |
205 | 206 | ||
206 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 207 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
207 | static const struct rt2x00debug rt61pci_rt2x00debug = { | 208 | static const struct rt2x00debug rt61pci_rt2x00debug = { |
208 | .owner = THIS_MODULE, | 209 | .owner = THIS_MODULE, |
209 | .csr = { | 210 | .csr = { |
210 | .read = rt2x00pci_register_read, | 211 | .read = rt2x00mmio_register_read, |
211 | .write = rt2x00pci_register_write, | 212 | .write = rt2x00mmio_register_write, |
212 | .flags = RT2X00DEBUGFS_OFFSET, | 213 | .flags = RT2X00DEBUGFS_OFFSET, |
213 | .word_base = CSR_REG_BASE, | 214 | .word_base = CSR_REG_BASE, |
214 | .word_size = sizeof(u32), | 215 | .word_size = sizeof(u32), |
@@ -242,7 +243,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) | |||
242 | { | 243 | { |
243 | u32 reg; | 244 | u32 reg; |
244 | 245 | ||
245 | rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); | 246 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, ®); |
246 | return rt2x00_get_field32(reg, MAC_CSR13_VAL5); | 247 | return rt2x00_get_field32(reg, MAC_CSR13_VAL5); |
247 | } | 248 | } |
248 | 249 | ||
@@ -293,10 +294,10 @@ static int rt61pci_blink_set(struct led_classdev *led_cdev, | |||
293 | container_of(led_cdev, struct rt2x00_led, led_dev); | 294 | container_of(led_cdev, struct rt2x00_led, led_dev); |
294 | u32 reg; | 295 | u32 reg; |
295 | 296 | ||
296 | rt2x00pci_register_read(led->rt2x00dev, MAC_CSR14, ®); | 297 | rt2x00mmio_register_read(led->rt2x00dev, MAC_CSR14, ®); |
297 | rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on); | 298 | rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on); |
298 | rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off); | 299 | rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off); |
299 | rt2x00pci_register_write(led->rt2x00dev, MAC_CSR14, reg); | 300 | rt2x00mmio_register_write(led->rt2x00dev, MAC_CSR14, reg); |
300 | 301 | ||
301 | return 0; | 302 | return 0; |
302 | } | 303 | } |
@@ -338,7 +339,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
338 | */ | 339 | */ |
339 | mask = (0xf << crypto->bssidx); | 340 | mask = (0xf << crypto->bssidx); |
340 | 341 | ||
341 | rt2x00pci_register_read(rt2x00dev, SEC_CSR0, ®); | 342 | rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, ®); |
342 | reg &= mask; | 343 | reg &= mask; |
343 | 344 | ||
344 | if (reg && reg == mask) | 345 | if (reg && reg == mask) |
@@ -357,8 +358,8 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
357 | sizeof(key_entry.rx_mic)); | 358 | sizeof(key_entry.rx_mic)); |
358 | 359 | ||
359 | reg = SHARED_KEY_ENTRY(key->hw_key_idx); | 360 | reg = SHARED_KEY_ENTRY(key->hw_key_idx); |
360 | rt2x00pci_register_multiwrite(rt2x00dev, reg, | 361 | rt2x00mmio_register_multiwrite(rt2x00dev, reg, |
361 | &key_entry, sizeof(key_entry)); | 362 | &key_entry, sizeof(key_entry)); |
362 | 363 | ||
363 | /* | 364 | /* |
364 | * The cipher types are stored over 2 registers. | 365 | * The cipher types are stored over 2 registers. |
@@ -371,16 +372,16 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
371 | field.bit_offset = (3 * key->hw_key_idx); | 372 | field.bit_offset = (3 * key->hw_key_idx); |
372 | field.bit_mask = 0x7 << field.bit_offset; | 373 | field.bit_mask = 0x7 << field.bit_offset; |
373 | 374 | ||
374 | rt2x00pci_register_read(rt2x00dev, SEC_CSR1, ®); | 375 | rt2x00mmio_register_read(rt2x00dev, SEC_CSR1, ®); |
375 | rt2x00_set_field32(®, field, crypto->cipher); | 376 | rt2x00_set_field32(®, field, crypto->cipher); |
376 | rt2x00pci_register_write(rt2x00dev, SEC_CSR1, reg); | 377 | rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg); |
377 | } else { | 378 | } else { |
378 | field.bit_offset = (3 * (key->hw_key_idx - 8)); | 379 | field.bit_offset = (3 * (key->hw_key_idx - 8)); |
379 | field.bit_mask = 0x7 << field.bit_offset; | 380 | field.bit_mask = 0x7 << field.bit_offset; |
380 | 381 | ||
381 | rt2x00pci_register_read(rt2x00dev, SEC_CSR5, ®); | 382 | rt2x00mmio_register_read(rt2x00dev, SEC_CSR5, ®); |
382 | rt2x00_set_field32(®, field, crypto->cipher); | 383 | rt2x00_set_field32(®, field, crypto->cipher); |
383 | rt2x00pci_register_write(rt2x00dev, SEC_CSR5, reg); | 384 | rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg); |
384 | } | 385 | } |
385 | 386 | ||
386 | /* | 387 | /* |
@@ -403,12 +404,12 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
403 | */ | 404 | */ |
404 | mask = 1 << key->hw_key_idx; | 405 | mask = 1 << key->hw_key_idx; |
405 | 406 | ||
406 | rt2x00pci_register_read(rt2x00dev, SEC_CSR0, ®); | 407 | rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, ®); |
407 | if (crypto->cmd == SET_KEY) | 408 | if (crypto->cmd == SET_KEY) |
408 | reg |= mask; | 409 | reg |= mask; |
409 | else if (crypto->cmd == DISABLE_KEY) | 410 | else if (crypto->cmd == DISABLE_KEY) |
410 | reg &= ~mask; | 411 | reg &= ~mask; |
411 | rt2x00pci_register_write(rt2x00dev, SEC_CSR0, reg); | 412 | rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, reg); |
412 | 413 | ||
413 | return 0; | 414 | return 0; |
414 | } | 415 | } |
@@ -432,10 +433,10 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
432 | * When both registers are full, we drop the key. | 433 | * When both registers are full, we drop the key. |
433 | * Otherwise, we use the first invalid entry. | 434 | * Otherwise, we use the first invalid entry. |
434 | */ | 435 | */ |
435 | rt2x00pci_register_read(rt2x00dev, SEC_CSR2, ®); | 436 | rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, ®); |
436 | if (reg && reg == ~0) { | 437 | if (reg && reg == ~0) { |
437 | key->hw_key_idx = 32; | 438 | key->hw_key_idx = 32; |
438 | rt2x00pci_register_read(rt2x00dev, SEC_CSR3, ®); | 439 | rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, ®); |
439 | if (reg && reg == ~0) | 440 | if (reg && reg == ~0) |
440 | return -ENOSPC; | 441 | return -ENOSPC; |
441 | } | 442 | } |
@@ -457,21 +458,21 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
457 | addr_entry.cipher = crypto->cipher; | 458 | addr_entry.cipher = crypto->cipher; |
458 | 459 | ||
459 | reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx); | 460 | reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx); |
460 | rt2x00pci_register_multiwrite(rt2x00dev, reg, | 461 | rt2x00mmio_register_multiwrite(rt2x00dev, reg, |
461 | &key_entry, sizeof(key_entry)); | 462 | &key_entry, sizeof(key_entry)); |
462 | 463 | ||
463 | reg = PAIRWISE_TA_ENTRY(key->hw_key_idx); | 464 | reg = PAIRWISE_TA_ENTRY(key->hw_key_idx); |
464 | rt2x00pci_register_multiwrite(rt2x00dev, reg, | 465 | rt2x00mmio_register_multiwrite(rt2x00dev, reg, |
465 | &addr_entry, sizeof(addr_entry)); | 466 | &addr_entry, sizeof(addr_entry)); |
466 | 467 | ||
467 | /* | 468 | /* |
468 | * Enable pairwise lookup table for given BSS idx. | 469 | * Enable pairwise lookup table for given BSS idx. |
469 | * Without this, received frames will not be decrypted | 470 | * Without this, received frames will not be decrypted |
470 | * by the hardware. | 471 | * by the hardware. |
471 | */ | 472 | */ |
472 | rt2x00pci_register_read(rt2x00dev, SEC_CSR4, ®); | 473 | rt2x00mmio_register_read(rt2x00dev, SEC_CSR4, ®); |
473 | reg |= (1 << crypto->bssidx); | 474 | reg |= (1 << crypto->bssidx); |
474 | rt2x00pci_register_write(rt2x00dev, SEC_CSR4, reg); | 475 | rt2x00mmio_register_write(rt2x00dev, SEC_CSR4, reg); |
475 | 476 | ||
476 | /* | 477 | /* |
477 | * The driver does not support the IV/EIV generation | 478 | * The driver does not support the IV/EIV generation |
@@ -494,21 +495,21 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
494 | if (key->hw_key_idx < 32) { | 495 | if (key->hw_key_idx < 32) { |
495 | mask = 1 << key->hw_key_idx; | 496 | mask = 1 << key->hw_key_idx; |
496 | 497 | ||
497 | rt2x00pci_register_read(rt2x00dev, SEC_CSR2, ®); | 498 | rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, ®); |
498 | if (crypto->cmd == SET_KEY) | 499 | if (crypto->cmd == SET_KEY) |
499 | reg |= mask; | 500 | reg |= mask; |
500 | else if (crypto->cmd == DISABLE_KEY) | 501 | else if (crypto->cmd == DISABLE_KEY) |
501 | reg &= ~mask; | 502 | reg &= ~mask; |
502 | rt2x00pci_register_write(rt2x00dev, SEC_CSR2, reg); | 503 | rt2x00mmio_register_write(rt2x00dev, SEC_CSR2, reg); |
503 | } else { | 504 | } else { |
504 | mask = 1 << (key->hw_key_idx - 32); | 505 | mask = 1 << (key->hw_key_idx - 32); |
505 | 506 | ||
506 | rt2x00pci_register_read(rt2x00dev, SEC_CSR3, ®); | 507 | rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, ®); |
507 | if (crypto->cmd == SET_KEY) | 508 | if (crypto->cmd == SET_KEY) |
508 | reg |= mask; | 509 | reg |= mask; |
509 | else if (crypto->cmd == DISABLE_KEY) | 510 | else if (crypto->cmd == DISABLE_KEY) |
510 | reg &= ~mask; | 511 | reg &= ~mask; |
511 | rt2x00pci_register_write(rt2x00dev, SEC_CSR3, reg); | 512 | rt2x00mmio_register_write(rt2x00dev, SEC_CSR3, reg); |
512 | } | 513 | } |
513 | 514 | ||
514 | return 0; | 515 | return 0; |
@@ -525,7 +526,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev, | |||
525 | * and broadcast frames will always be accepted since | 526 | * and broadcast frames will always be accepted since |
526 | * there is no filter for it at this time. | 527 | * there is no filter for it at this time. |
527 | */ | 528 | */ |
528 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); | 529 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, ®); |
529 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, | 530 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, |
530 | !(filter_flags & FIF_FCSFAIL)); | 531 | !(filter_flags & FIF_FCSFAIL)); |
531 | rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, | 532 | rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, |
@@ -543,7 +544,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev, | |||
543 | rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); | 544 | rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); |
544 | rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, | 545 | rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, |
545 | !(filter_flags & FIF_CONTROL)); | 546 | !(filter_flags & FIF_CONTROL)); |
546 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); | 547 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg); |
547 | } | 548 | } |
548 | 549 | ||
549 | static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, | 550 | static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, |
@@ -557,9 +558,9 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
557 | /* | 558 | /* |
558 | * Enable synchronisation. | 559 | * Enable synchronisation. |
559 | */ | 560 | */ |
560 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 561 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®); |
561 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); | 562 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); |
562 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 563 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); |
563 | } | 564 | } |
564 | 565 | ||
565 | if (flags & CONFIG_UPDATE_MAC) { | 566 | if (flags & CONFIG_UPDATE_MAC) { |
@@ -567,8 +568,8 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
567 | rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); | 568 | rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); |
568 | conf->mac[1] = cpu_to_le32(reg); | 569 | conf->mac[1] = cpu_to_le32(reg); |
569 | 570 | ||
570 | rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, | 571 | rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR2, |
571 | conf->mac, sizeof(conf->mac)); | 572 | conf->mac, sizeof(conf->mac)); |
572 | } | 573 | } |
573 | 574 | ||
574 | if (flags & CONFIG_UPDATE_BSSID) { | 575 | if (flags & CONFIG_UPDATE_BSSID) { |
@@ -576,8 +577,9 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
576 | rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); | 577 | rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); |
577 | conf->bssid[1] = cpu_to_le32(reg); | 578 | conf->bssid[1] = cpu_to_le32(reg); |
578 | 579 | ||
579 | rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, | 580 | rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR4, |
580 | conf->bssid, sizeof(conf->bssid)); | 581 | conf->bssid, |
582 | sizeof(conf->bssid)); | ||
581 | } | 583 | } |
582 | } | 584 | } |
583 | 585 | ||
@@ -587,40 +589,40 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, | |||
587 | { | 589 | { |
588 | u32 reg; | 590 | u32 reg; |
589 | 591 | ||
590 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); | 592 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, ®); |
591 | rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32); | 593 | rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32); |
592 | rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); | 594 | rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); |
593 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); | 595 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg); |
594 | 596 | ||
595 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 597 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
596 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); | 598 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, ®); |
597 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); | 599 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); |
598 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, | 600 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, |
599 | !!erp->short_preamble); | 601 | !!erp->short_preamble); |
600 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); | 602 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg); |
601 | } | 603 | } |
602 | 604 | ||
603 | if (changed & BSS_CHANGED_BASIC_RATES) | 605 | if (changed & BSS_CHANGED_BASIC_RATES) |
604 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, | 606 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR5, |
605 | erp->basic_rates); | 607 | erp->basic_rates); |
606 | 608 | ||
607 | if (changed & BSS_CHANGED_BEACON_INT) { | 609 | if (changed & BSS_CHANGED_BEACON_INT) { |
608 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 610 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®); |
609 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, | 611 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, |
610 | erp->beacon_int * 16); | 612 | erp->beacon_int * 16); |
611 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 613 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); |
612 | } | 614 | } |
613 | 615 | ||
614 | if (changed & BSS_CHANGED_ERP_SLOT) { | 616 | if (changed & BSS_CHANGED_ERP_SLOT) { |
615 | rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); | 617 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, ®); |
616 | rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); | 618 | rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); |
617 | rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); | 619 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg); |
618 | 620 | ||
619 | rt2x00pci_register_read(rt2x00dev, MAC_CSR8, ®); | 621 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR8, ®); |
620 | rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); | 622 | rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); |
621 | rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); | 623 | rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); |
622 | rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); | 624 | rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); |
623 | rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg); | 625 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR8, reg); |
624 | } | 626 | } |
625 | } | 627 | } |
626 | 628 | ||
@@ -713,7 +715,7 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev, | |||
713 | { | 715 | { |
714 | u32 reg; | 716 | u32 reg; |
715 | 717 | ||
716 | rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); | 718 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, ®); |
717 | 719 | ||
718 | rt2x00_set_field32(®, MAC_CSR13_DIR4, 0); | 720 | rt2x00_set_field32(®, MAC_CSR13_DIR4, 0); |
719 | rt2x00_set_field32(®, MAC_CSR13_VAL4, p1); | 721 | rt2x00_set_field32(®, MAC_CSR13_VAL4, p1); |
@@ -721,7 +723,7 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev, | |||
721 | rt2x00_set_field32(®, MAC_CSR13_DIR3, 0); | 723 | rt2x00_set_field32(®, MAC_CSR13_DIR3, 0); |
722 | rt2x00_set_field32(®, MAC_CSR13_VAL3, !p2); | 724 | rt2x00_set_field32(®, MAC_CSR13_VAL3, !p2); |
723 | 725 | ||
724 | rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); | 726 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg); |
725 | } | 727 | } |
726 | 728 | ||
727 | static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev, | 729 | static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev, |
@@ -820,14 +822,14 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
820 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) | 822 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) |
821 | rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); | 823 | rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); |
822 | 824 | ||
823 | rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®); | 825 | rt2x00mmio_register_read(rt2x00dev, PHY_CSR0, ®); |
824 | 826 | ||
825 | rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, | 827 | rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, |
826 | rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); | 828 | rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); |
827 | rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, | 829 | rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, |
828 | rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); | 830 | rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); |
829 | 831 | ||
830 | rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); | 832 | rt2x00mmio_register_write(rt2x00dev, PHY_CSR0, reg); |
831 | 833 | ||
832 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) | 834 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) |
833 | rt61pci_config_antenna_5x(rt2x00dev, ant); | 835 | rt61pci_config_antenna_5x(rt2x00dev, ant); |
@@ -927,7 +929,7 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |||
927 | { | 929 | { |
928 | u32 reg; | 930 | u32 reg; |
929 | 931 | ||
930 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); | 932 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, ®); |
931 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1); | 933 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1); |
932 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_STEP, 0); | 934 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_STEP, 0); |
933 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0); | 935 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0); |
@@ -935,7 +937,7 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |||
935 | libconf->conf->long_frame_max_tx_count); | 937 | libconf->conf->long_frame_max_tx_count); |
936 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, | 938 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, |
937 | libconf->conf->short_frame_max_tx_count); | 939 | libconf->conf->short_frame_max_tx_count); |
938 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); | 940 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg); |
939 | } | 941 | } |
940 | 942 | ||
941 | static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, | 943 | static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, |
@@ -947,7 +949,7 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, | |||
947 | u32 reg; | 949 | u32 reg; |
948 | 950 | ||
949 | if (state == STATE_SLEEP) { | 951 | if (state == STATE_SLEEP) { |
950 | rt2x00pci_register_read(rt2x00dev, MAC_CSR11, ®); | 952 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, ®); |
951 | rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, | 953 | rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, |
952 | rt2x00dev->beacon_int - 10); | 954 | rt2x00dev->beacon_int - 10); |
953 | rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, | 955 | rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, |
@@ -956,27 +958,29 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, | |||
956 | 958 | ||
957 | /* We must first disable autowake before it can be enabled */ | 959 | /* We must first disable autowake before it can be enabled */ |
958 | rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); | 960 | rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); |
959 | rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); | 961 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg); |
960 | 962 | ||
961 | rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 1); | 963 | rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 1); |
962 | rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); | 964 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg); |
963 | 965 | ||
964 | rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000005); | 966 | rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR, |
965 | rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c); | 967 | 0x00000005); |
966 | rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060); | 968 | rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c); |
969 | rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060); | ||
967 | 970 | ||
968 | rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0); | 971 | rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0); |
969 | } else { | 972 | } else { |
970 | rt2x00pci_register_read(rt2x00dev, MAC_CSR11, ®); | 973 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, ®); |
971 | rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); | 974 | rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); |
972 | rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); | 975 | rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); |
973 | rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); | 976 | rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); |
974 | rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); | 977 | rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); |
975 | rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); | 978 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg); |
976 | 979 | ||
977 | rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007); | 980 | rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR, |
978 | rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018); | 981 | 0x00000007); |
979 | rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020); | 982 | rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018); |
983 | rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020); | ||
980 | 984 | ||
981 | rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); | 985 | rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); |
982 | } | 986 | } |
@@ -1012,13 +1016,13 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev, | |||
1012 | /* | 1016 | /* |
1013 | * Update FCS error count from register. | 1017 | * Update FCS error count from register. |
1014 | */ | 1018 | */ |
1015 | rt2x00pci_register_read(rt2x00dev, STA_CSR0, ®); | 1019 | rt2x00mmio_register_read(rt2x00dev, STA_CSR0, ®); |
1016 | qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); | 1020 | qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); |
1017 | 1021 | ||
1018 | /* | 1022 | /* |
1019 | * Update False CCA count from register. | 1023 | * Update False CCA count from register. |
1020 | */ | 1024 | */ |
1021 | rt2x00pci_register_read(rt2x00dev, STA_CSR1, ®); | 1025 | rt2x00mmio_register_read(rt2x00dev, STA_CSR1, ®); |
1022 | qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); | 1026 | qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); |
1023 | } | 1027 | } |
1024 | 1028 | ||
@@ -1137,16 +1141,16 @@ static void rt61pci_start_queue(struct data_queue *queue) | |||
1137 | 1141 | ||
1138 | switch (queue->qid) { | 1142 | switch (queue->qid) { |
1139 | case QID_RX: | 1143 | case QID_RX: |
1140 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); | 1144 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, ®); |
1141 | rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); | 1145 | rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); |
1142 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); | 1146 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg); |
1143 | break; | 1147 | break; |
1144 | case QID_BEACON: | 1148 | case QID_BEACON: |
1145 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 1149 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®); |
1146 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | 1150 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); |
1147 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | 1151 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); |
1148 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | 1152 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); |
1149 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 1153 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); |
1150 | break; | 1154 | break; |
1151 | default: | 1155 | default: |
1152 | break; | 1156 | break; |
@@ -1160,24 +1164,24 @@ static void rt61pci_kick_queue(struct data_queue *queue) | |||
1160 | 1164 | ||
1161 | switch (queue->qid) { | 1165 | switch (queue->qid) { |
1162 | case QID_AC_VO: | 1166 | case QID_AC_VO: |
1163 | rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); | 1167 | rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); |
1164 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, 1); | 1168 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, 1); |
1165 | rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); | 1169 | rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); |
1166 | break; | 1170 | break; |
1167 | case QID_AC_VI: | 1171 | case QID_AC_VI: |
1168 | rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); | 1172 | rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); |
1169 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, 1); | 1173 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, 1); |
1170 | rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); | 1174 | rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); |
1171 | break; | 1175 | break; |
1172 | case QID_AC_BE: | 1176 | case QID_AC_BE: |
1173 | rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); | 1177 | rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); |
1174 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, 1); | 1178 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, 1); |
1175 | rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); | 1179 | rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); |
1176 | break; | 1180 | break; |
1177 | case QID_AC_BK: | 1181 | case QID_AC_BK: |
1178 | rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); | 1182 | rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); |
1179 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, 1); | 1183 | rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, 1); |
1180 | rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); | 1184 | rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); |
1181 | break; | 1185 | break; |
1182 | default: | 1186 | default: |
1183 | break; | 1187 | break; |
@@ -1191,36 +1195,36 @@ static void rt61pci_stop_queue(struct data_queue *queue) | |||
1191 | 1195 | ||
1192 | switch (queue->qid) { | 1196 | switch (queue->qid) { |
1193 | case QID_AC_VO: | 1197 | case QID_AC_VO: |
1194 | rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); | 1198 | rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); |
1195 | rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, 1); | 1199 | rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, 1); |
1196 | rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); | 1200 | rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); |
1197 | break; | 1201 | break; |
1198 | case QID_AC_VI: | 1202 | case QID_AC_VI: |
1199 | rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); | 1203 | rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); |
1200 | rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, 1); | 1204 | rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, 1); |
1201 | rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); | 1205 | rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); |
1202 | break; | 1206 | break; |
1203 | case QID_AC_BE: | 1207 | case QID_AC_BE: |
1204 | rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); | 1208 | rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); |
1205 | rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1); | 1209 | rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1); |
1206 | rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); | 1210 | rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); |
1207 | break; | 1211 | break; |
1208 | case QID_AC_BK: | 1212 | case QID_AC_BK: |
1209 | rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); | 1213 | rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); |
1210 | rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1); | 1214 | rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1); |
1211 | rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); | 1215 | rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); |
1212 | break; | 1216 | break; |
1213 | case QID_RX: | 1217 | case QID_RX: |
1214 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); | 1218 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, ®); |
1215 | rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); | 1219 | rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); |
1216 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); | 1220 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg); |
1217 | break; | 1221 | break; |
1218 | case QID_BEACON: | 1222 | case QID_BEACON: |
1219 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 1223 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®); |
1220 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); | 1224 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); |
1221 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); | 1225 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); |
1222 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | 1226 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); |
1223 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 1227 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); |
1224 | 1228 | ||
1225 | /* | 1229 | /* |
1226 | * Wait for possibly running tbtt tasklets. | 1230 | * Wait for possibly running tbtt tasklets. |
@@ -1298,7 +1302,7 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
1298 | * Wait for stable hardware. | 1302 | * Wait for stable hardware. |
1299 | */ | 1303 | */ |
1300 | for (i = 0; i < 100; i++) { | 1304 | for (i = 0; i < 100; i++) { |
1301 | rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); | 1305 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, ®); |
1302 | if (reg) | 1306 | if (reg) |
1303 | break; | 1307 | break; |
1304 | msleep(1); | 1308 | msleep(1); |
@@ -1314,10 +1318,10 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
1314 | */ | 1318 | */ |
1315 | reg = 0; | 1319 | reg = 0; |
1316 | rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 1); | 1320 | rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 1); |
1317 | rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); | 1321 | rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg); |
1318 | rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); | 1322 | rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); |
1319 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | 1323 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); |
1320 | rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, 0); | 1324 | rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, 0); |
1321 | 1325 | ||
1322 | /* | 1326 | /* |
1323 | * Write firmware to device. | 1327 | * Write firmware to device. |
@@ -1325,19 +1329,19 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
1325 | reg = 0; | 1329 | reg = 0; |
1326 | rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 1); | 1330 | rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 1); |
1327 | rt2x00_set_field32(®, MCU_CNTL_CSR_SELECT_BANK, 1); | 1331 | rt2x00_set_field32(®, MCU_CNTL_CSR_SELECT_BANK, 1); |
1328 | rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); | 1332 | rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg); |
1329 | 1333 | ||
1330 | rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, | 1334 | rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, |
1331 | data, len); | 1335 | data, len); |
1332 | 1336 | ||
1333 | rt2x00_set_field32(®, MCU_CNTL_CSR_SELECT_BANK, 0); | 1337 | rt2x00_set_field32(®, MCU_CNTL_CSR_SELECT_BANK, 0); |
1334 | rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); | 1338 | rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg); |
1335 | 1339 | ||
1336 | rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 0); | 1340 | rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 0); |
1337 | rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); | 1341 | rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg); |
1338 | 1342 | ||
1339 | for (i = 0; i < 100; i++) { | 1343 | for (i = 0; i < 100; i++) { |
1340 | rt2x00pci_register_read(rt2x00dev, MCU_CNTL_CSR, ®); | 1344 | rt2x00mmio_register_read(rt2x00dev, MCU_CNTL_CSR, ®); |
1341 | if (rt2x00_get_field32(reg, MCU_CNTL_CSR_READY)) | 1345 | if (rt2x00_get_field32(reg, MCU_CNTL_CSR_READY)) |
1342 | break; | 1346 | break; |
1343 | msleep(1); | 1347 | msleep(1); |
@@ -1359,16 +1363,16 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
1359 | reg = 0; | 1363 | reg = 0; |
1360 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); | 1364 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); |
1361 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); | 1365 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); |
1362 | rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); | 1366 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg); |
1363 | 1367 | ||
1364 | rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); | 1368 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, ®); |
1365 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0); | 1369 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0); |
1366 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); | 1370 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); |
1367 | rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); | 1371 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg); |
1368 | 1372 | ||
1369 | rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); | 1373 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, ®); |
1370 | rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); | 1374 | rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); |
1371 | rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); | 1375 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg); |
1372 | 1376 | ||
1373 | return 0; | 1377 | return 0; |
1374 | } | 1378 | } |
@@ -1378,7 +1382,7 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
1378 | */ | 1382 | */ |
1379 | static bool rt61pci_get_entry_state(struct queue_entry *entry) | 1383 | static bool rt61pci_get_entry_state(struct queue_entry *entry) |
1380 | { | 1384 | { |
1381 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1385 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
1382 | u32 word; | 1386 | u32 word; |
1383 | 1387 | ||
1384 | if (entry->queue->qid == QID_RX) { | 1388 | if (entry->queue->qid == QID_RX) { |
@@ -1395,7 +1399,7 @@ static bool rt61pci_get_entry_state(struct queue_entry *entry) | |||
1395 | 1399 | ||
1396 | static void rt61pci_clear_entry(struct queue_entry *entry) | 1400 | static void rt61pci_clear_entry(struct queue_entry *entry) |
1397 | { | 1401 | { |
1398 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1402 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
1399 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1403 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
1400 | u32 word; | 1404 | u32 word; |
1401 | 1405 | ||
@@ -1418,13 +1422,13 @@ static void rt61pci_clear_entry(struct queue_entry *entry) | |||
1418 | 1422 | ||
1419 | static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) | 1423 | static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) |
1420 | { | 1424 | { |
1421 | struct queue_entry_priv_pci *entry_priv; | 1425 | struct queue_entry_priv_mmio *entry_priv; |
1422 | u32 reg; | 1426 | u32 reg; |
1423 | 1427 | ||
1424 | /* | 1428 | /* |
1425 | * Initialize registers. | 1429 | * Initialize registers. |
1426 | */ | 1430 | */ |
1427 | rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, ®); | 1431 | rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR0, ®); |
1428 | rt2x00_set_field32(®, TX_RING_CSR0_AC0_RING_SIZE, | 1432 | rt2x00_set_field32(®, TX_RING_CSR0_AC0_RING_SIZE, |
1429 | rt2x00dev->tx[0].limit); | 1433 | rt2x00dev->tx[0].limit); |
1430 | rt2x00_set_field32(®, TX_RING_CSR0_AC1_RING_SIZE, | 1434 | rt2x00_set_field32(®, TX_RING_CSR0_AC1_RING_SIZE, |
@@ -1433,67 +1437,67 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) | |||
1433 | rt2x00dev->tx[2].limit); | 1437 | rt2x00dev->tx[2].limit); |
1434 | rt2x00_set_field32(®, TX_RING_CSR0_AC3_RING_SIZE, | 1438 | rt2x00_set_field32(®, TX_RING_CSR0_AC3_RING_SIZE, |
1435 | rt2x00dev->tx[3].limit); | 1439 | rt2x00dev->tx[3].limit); |
1436 | rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg); | 1440 | rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR0, reg); |
1437 | 1441 | ||
1438 | rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, ®); | 1442 | rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR1, ®); |
1439 | rt2x00_set_field32(®, TX_RING_CSR1_TXD_SIZE, | 1443 | rt2x00_set_field32(®, TX_RING_CSR1_TXD_SIZE, |
1440 | rt2x00dev->tx[0].desc_size / 4); | 1444 | rt2x00dev->tx[0].desc_size / 4); |
1441 | rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg); | 1445 | rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR1, reg); |
1442 | 1446 | ||
1443 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; | 1447 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; |
1444 | rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, ®); | 1448 | rt2x00mmio_register_read(rt2x00dev, AC0_BASE_CSR, ®); |
1445 | rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, | 1449 | rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, |
1446 | entry_priv->desc_dma); | 1450 | entry_priv->desc_dma); |
1447 | rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg); | 1451 | rt2x00mmio_register_write(rt2x00dev, AC0_BASE_CSR, reg); |
1448 | 1452 | ||
1449 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; | 1453 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; |
1450 | rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, ®); | 1454 | rt2x00mmio_register_read(rt2x00dev, AC1_BASE_CSR, ®); |
1451 | rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, | 1455 | rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, |
1452 | entry_priv->desc_dma); | 1456 | entry_priv->desc_dma); |
1453 | rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg); | 1457 | rt2x00mmio_register_write(rt2x00dev, AC1_BASE_CSR, reg); |
1454 | 1458 | ||
1455 | entry_priv = rt2x00dev->tx[2].entries[0].priv_data; | 1459 | entry_priv = rt2x00dev->tx[2].entries[0].priv_data; |
1456 | rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, ®); | 1460 | rt2x00mmio_register_read(rt2x00dev, AC2_BASE_CSR, ®); |
1457 | rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, | 1461 | rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, |
1458 | entry_priv->desc_dma); | 1462 | entry_priv->desc_dma); |
1459 | rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg); | 1463 | rt2x00mmio_register_write(rt2x00dev, AC2_BASE_CSR, reg); |
1460 | 1464 | ||
1461 | entry_priv = rt2x00dev->tx[3].entries[0].priv_data; | 1465 | entry_priv = rt2x00dev->tx[3].entries[0].priv_data; |
1462 | rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, ®); | 1466 | rt2x00mmio_register_read(rt2x00dev, AC3_BASE_CSR, ®); |
1463 | rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, | 1467 | rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, |
1464 | entry_priv->desc_dma); | 1468 | entry_priv->desc_dma); |
1465 | rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg); | 1469 | rt2x00mmio_register_write(rt2x00dev, AC3_BASE_CSR, reg); |
1466 | 1470 | ||
1467 | rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, ®); | 1471 | rt2x00mmio_register_read(rt2x00dev, RX_RING_CSR, ®); |
1468 | rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit); | 1472 | rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit); |
1469 | rt2x00_set_field32(®, RX_RING_CSR_RXD_SIZE, | 1473 | rt2x00_set_field32(®, RX_RING_CSR_RXD_SIZE, |
1470 | rt2x00dev->rx->desc_size / 4); | 1474 | rt2x00dev->rx->desc_size / 4); |
1471 | rt2x00_set_field32(®, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4); | 1475 | rt2x00_set_field32(®, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4); |
1472 | rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg); | 1476 | rt2x00mmio_register_write(rt2x00dev, RX_RING_CSR, reg); |
1473 | 1477 | ||
1474 | entry_priv = rt2x00dev->rx->entries[0].priv_data; | 1478 | entry_priv = rt2x00dev->rx->entries[0].priv_data; |
1475 | rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, ®); | 1479 | rt2x00mmio_register_read(rt2x00dev, RX_BASE_CSR, ®); |
1476 | rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, | 1480 | rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, |
1477 | entry_priv->desc_dma); | 1481 | entry_priv->desc_dma); |
1478 | rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg); | 1482 | rt2x00mmio_register_write(rt2x00dev, RX_BASE_CSR, reg); |
1479 | 1483 | ||
1480 | rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, ®); | 1484 | rt2x00mmio_register_read(rt2x00dev, TX_DMA_DST_CSR, ®); |
1481 | rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC0, 2); | 1485 | rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC0, 2); |
1482 | rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC1, 2); | 1486 | rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC1, 2); |
1483 | rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC2, 2); | 1487 | rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC2, 2); |
1484 | rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC3, 2); | 1488 | rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC3, 2); |
1485 | rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg); | 1489 | rt2x00mmio_register_write(rt2x00dev, TX_DMA_DST_CSR, reg); |
1486 | 1490 | ||
1487 | rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, ®); | 1491 | rt2x00mmio_register_read(rt2x00dev, LOAD_TX_RING_CSR, ®); |
1488 | rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC0, 1); | 1492 | rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC0, 1); |
1489 | rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1); | 1493 | rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1); |
1490 | rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1); | 1494 | rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1); |
1491 | rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1); | 1495 | rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1); |
1492 | rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg); | 1496 | rt2x00mmio_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg); |
1493 | 1497 | ||
1494 | rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); | 1498 | rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, ®); |
1495 | rt2x00_set_field32(®, RX_CNTL_CSR_LOAD_RXD, 1); | 1499 | rt2x00_set_field32(®, RX_CNTL_CSR_LOAD_RXD, 1); |
1496 | rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg); | 1500 | rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg); |
1497 | 1501 | ||
1498 | return 0; | 1502 | return 0; |
1499 | } | 1503 | } |
@@ -1502,13 +1506,13 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1502 | { | 1506 | { |
1503 | u32 reg; | 1507 | u32 reg; |
1504 | 1508 | ||
1505 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); | 1509 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, ®); |
1506 | rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1); | 1510 | rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1); |
1507 | rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); | 1511 | rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); |
1508 | rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0); | 1512 | rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0); |
1509 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); | 1513 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg); |
1510 | 1514 | ||
1511 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR1, ®); | 1515 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR1, ®); |
1512 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */ | 1516 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */ |
1513 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0_VALID, 1); | 1517 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0_VALID, 1); |
1514 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1, 30); /* Rssi */ | 1518 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1, 30); /* Rssi */ |
@@ -1517,12 +1521,12 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1517 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2_VALID, 1); | 1521 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2_VALID, 1); |
1518 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3, 30); /* Rssi */ | 1522 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3, 30); /* Rssi */ |
1519 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3_VALID, 1); | 1523 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3_VALID, 1); |
1520 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR1, reg); | 1524 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR1, reg); |
1521 | 1525 | ||
1522 | /* | 1526 | /* |
1523 | * CCK TXD BBP registers | 1527 | * CCK TXD BBP registers |
1524 | */ | 1528 | */ |
1525 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR2, ®); | 1529 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR2, ®); |
1526 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0, 13); | 1530 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0, 13); |
1527 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0_VALID, 1); | 1531 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0_VALID, 1); |
1528 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1, 12); | 1532 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1, 12); |
@@ -1531,76 +1535,76 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1531 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2_VALID, 1); | 1535 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2_VALID, 1); |
1532 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3, 10); | 1536 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3, 10); |
1533 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3_VALID, 1); | 1537 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3_VALID, 1); |
1534 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR2, reg); | 1538 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR2, reg); |
1535 | 1539 | ||
1536 | /* | 1540 | /* |
1537 | * OFDM TXD BBP registers | 1541 | * OFDM TXD BBP registers |
1538 | */ | 1542 | */ |
1539 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR3, ®); | 1543 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR3, ®); |
1540 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0, 7); | 1544 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0, 7); |
1541 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0_VALID, 1); | 1545 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0_VALID, 1); |
1542 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1, 6); | 1546 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1, 6); |
1543 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1_VALID, 1); | 1547 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1_VALID, 1); |
1544 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2, 5); | 1548 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2, 5); |
1545 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2_VALID, 1); | 1549 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2_VALID, 1); |
1546 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR3, reg); | 1550 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR3, reg); |
1547 | 1551 | ||
1548 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR7, ®); | 1552 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR7, ®); |
1549 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_6MBS, 59); | 1553 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_6MBS, 59); |
1550 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_9MBS, 53); | 1554 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_9MBS, 53); |
1551 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_12MBS, 49); | 1555 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_12MBS, 49); |
1552 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_18MBS, 46); | 1556 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_18MBS, 46); |
1553 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR7, reg); | 1557 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR7, reg); |
1554 | 1558 | ||
1555 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR8, ®); | 1559 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR8, ®); |
1556 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_24MBS, 44); | 1560 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_24MBS, 44); |
1557 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_36MBS, 42); | 1561 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_36MBS, 42); |
1558 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_48MBS, 42); | 1562 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_48MBS, 42); |
1559 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_54MBS, 42); | 1563 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_54MBS, 42); |
1560 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR8, reg); | 1564 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR8, reg); |
1561 | 1565 | ||
1562 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 1566 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®); |
1563 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, 0); | 1567 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, 0); |
1564 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); | 1568 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); |
1565 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0); | 1569 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0); |
1566 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); | 1570 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); |
1567 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | 1571 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); |
1568 | rt2x00_set_field32(®, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0); | 1572 | rt2x00_set_field32(®, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0); |
1569 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 1573 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); |
1570 | 1574 | ||
1571 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); | 1575 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); |
1572 | 1576 | ||
1573 | rt2x00pci_register_write(rt2x00dev, MAC_CSR6, 0x00000fff); | 1577 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR6, 0x00000fff); |
1574 | 1578 | ||
1575 | rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); | 1579 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, ®); |
1576 | rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); | 1580 | rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); |
1577 | rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); | 1581 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg); |
1578 | 1582 | ||
1579 | rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x0000071c); | 1583 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x0000071c); |
1580 | 1584 | ||
1581 | if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) | 1585 | if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) |
1582 | return -EBUSY; | 1586 | return -EBUSY; |
1583 | 1587 | ||
1584 | rt2x00pci_register_write(rt2x00dev, MAC_CSR13, 0x0000e000); | 1588 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, 0x0000e000); |
1585 | 1589 | ||
1586 | /* | 1590 | /* |
1587 | * Invalidate all Shared Keys (SEC_CSR0), | 1591 | * Invalidate all Shared Keys (SEC_CSR0), |
1588 | * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) | 1592 | * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) |
1589 | */ | 1593 | */ |
1590 | rt2x00pci_register_write(rt2x00dev, SEC_CSR0, 0x00000000); | 1594 | rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, 0x00000000); |
1591 | rt2x00pci_register_write(rt2x00dev, SEC_CSR1, 0x00000000); | 1595 | rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, 0x00000000); |
1592 | rt2x00pci_register_write(rt2x00dev, SEC_CSR5, 0x00000000); | 1596 | rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, 0x00000000); |
1593 | 1597 | ||
1594 | rt2x00pci_register_write(rt2x00dev, PHY_CSR1, 0x000023b0); | 1598 | rt2x00mmio_register_write(rt2x00dev, PHY_CSR1, 0x000023b0); |
1595 | rt2x00pci_register_write(rt2x00dev, PHY_CSR5, 0x060a100c); | 1599 | rt2x00mmio_register_write(rt2x00dev, PHY_CSR5, 0x060a100c); |
1596 | rt2x00pci_register_write(rt2x00dev, PHY_CSR6, 0x00080606); | 1600 | rt2x00mmio_register_write(rt2x00dev, PHY_CSR6, 0x00080606); |
1597 | rt2x00pci_register_write(rt2x00dev, PHY_CSR7, 0x00000a08); | 1601 | rt2x00mmio_register_write(rt2x00dev, PHY_CSR7, 0x00000a08); |
1598 | 1602 | ||
1599 | rt2x00pci_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404); | 1603 | rt2x00mmio_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404); |
1600 | 1604 | ||
1601 | rt2x00pci_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200); | 1605 | rt2x00mmio_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200); |
1602 | 1606 | ||
1603 | rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); | 1607 | rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); |
1604 | 1608 | ||
1605 | /* | 1609 | /* |
1606 | * Clear all beacons | 1610 | * Clear all beacons |
@@ -1608,36 +1612,36 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1608 | * the first byte since that byte contains the VALID and OWNER | 1612 | * the first byte since that byte contains the VALID and OWNER |
1609 | * bits which (when set to 0) will invalidate the entire beacon. | 1613 | * bits which (when set to 0) will invalidate the entire beacon. |
1610 | */ | 1614 | */ |
1611 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); | 1615 | rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE0, 0); |
1612 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); | 1616 | rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE1, 0); |
1613 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); | 1617 | rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE2, 0); |
1614 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); | 1618 | rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE3, 0); |
1615 | 1619 | ||
1616 | /* | 1620 | /* |
1617 | * We must clear the error counters. | 1621 | * We must clear the error counters. |
1618 | * These registers are cleared on read, | 1622 | * These registers are cleared on read, |
1619 | * so we may pass a useless variable to store the value. | 1623 | * so we may pass a useless variable to store the value. |
1620 | */ | 1624 | */ |
1621 | rt2x00pci_register_read(rt2x00dev, STA_CSR0, ®); | 1625 | rt2x00mmio_register_read(rt2x00dev, STA_CSR0, ®); |
1622 | rt2x00pci_register_read(rt2x00dev, STA_CSR1, ®); | 1626 | rt2x00mmio_register_read(rt2x00dev, STA_CSR1, ®); |
1623 | rt2x00pci_register_read(rt2x00dev, STA_CSR2, ®); | 1627 | rt2x00mmio_register_read(rt2x00dev, STA_CSR2, ®); |
1624 | 1628 | ||
1625 | /* | 1629 | /* |
1626 | * Reset MAC and BBP registers. | 1630 | * Reset MAC and BBP registers. |
1627 | */ | 1631 | */ |
1628 | rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); | 1632 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, ®); |
1629 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); | 1633 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); |
1630 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); | 1634 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); |
1631 | rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); | 1635 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg); |
1632 | 1636 | ||
1633 | rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); | 1637 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, ®); |
1634 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0); | 1638 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0); |
1635 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); | 1639 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); |
1636 | rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); | 1640 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg); |
1637 | 1641 | ||
1638 | rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); | 1642 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, ®); |
1639 | rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); | 1643 | rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); |
1640 | rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); | 1644 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg); |
1641 | 1645 | ||
1642 | return 0; | 1646 | return 0; |
1643 | } | 1647 | } |
@@ -1721,11 +1725,11 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1721 | * should clear the register to assure a clean state. | 1725 | * should clear the register to assure a clean state. |
1722 | */ | 1726 | */ |
1723 | if (state == STATE_RADIO_IRQ_ON) { | 1727 | if (state == STATE_RADIO_IRQ_ON) { |
1724 | rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | 1728 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); |
1725 | rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | 1729 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); |
1726 | 1730 | ||
1727 | rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®); | 1731 | rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®); |
1728 | rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg); | 1732 | rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg); |
1729 | } | 1733 | } |
1730 | 1734 | ||
1731 | /* | 1735 | /* |
@@ -1734,15 +1738,15 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1734 | */ | 1738 | */ |
1735 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | 1739 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
1736 | 1740 | ||
1737 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | 1741 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); |
1738 | rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask); | 1742 | rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask); |
1739 | rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask); | 1743 | rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask); |
1740 | rt2x00_set_field32(®, INT_MASK_CSR_BEACON_DONE, mask); | 1744 | rt2x00_set_field32(®, INT_MASK_CSR_BEACON_DONE, mask); |
1741 | rt2x00_set_field32(®, INT_MASK_CSR_ENABLE_MITIGATION, mask); | 1745 | rt2x00_set_field32(®, INT_MASK_CSR_ENABLE_MITIGATION, mask); |
1742 | rt2x00_set_field32(®, INT_MASK_CSR_MITIGATION_PERIOD, 0xff); | 1746 | rt2x00_set_field32(®, INT_MASK_CSR_MITIGATION_PERIOD, 0xff); |
1743 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); | 1747 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); |
1744 | 1748 | ||
1745 | rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); | 1749 | rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); |
1746 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_0, mask); | 1750 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_0, mask); |
1747 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_1, mask); | 1751 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_1, mask); |
1748 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_2, mask); | 1752 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_2, mask); |
@@ -1752,7 +1756,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1752 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_6, mask); | 1756 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_6, mask); |
1753 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask); | 1757 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask); |
1754 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_TWAKEUP, mask); | 1758 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_TWAKEUP, mask); |
1755 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); | 1759 | rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); |
1756 | 1760 | ||
1757 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | 1761 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
1758 | 1762 | ||
@@ -1782,9 +1786,9 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
1782 | /* | 1786 | /* |
1783 | * Enable RX. | 1787 | * Enable RX. |
1784 | */ | 1788 | */ |
1785 | rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); | 1789 | rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, ®); |
1786 | rt2x00_set_field32(®, RX_CNTL_CSR_ENABLE_RX_DMA, 1); | 1790 | rt2x00_set_field32(®, RX_CNTL_CSR_ENABLE_RX_DMA, 1); |
1787 | rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg); | 1791 | rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg); |
1788 | 1792 | ||
1789 | return 0; | 1793 | return 0; |
1790 | } | 1794 | } |
@@ -1794,7 +1798,7 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
1794 | /* | 1798 | /* |
1795 | * Disable power | 1799 | * Disable power |
1796 | */ | 1800 | */ |
1797 | rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818); | 1801 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x00001818); |
1798 | } | 1802 | } |
1799 | 1803 | ||
1800 | static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) | 1804 | static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) |
@@ -1805,10 +1809,10 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) | |||
1805 | 1809 | ||
1806 | put_to_sleep = (state != STATE_AWAKE); | 1810 | put_to_sleep = (state != STATE_AWAKE); |
1807 | 1811 | ||
1808 | rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®); | 1812 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, ®); |
1809 | rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep); | 1813 | rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep); |
1810 | rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep); | 1814 | rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep); |
1811 | rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg); | 1815 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg); |
1812 | 1816 | ||
1813 | /* | 1817 | /* |
1814 | * Device is not guaranteed to be in the requested state yet. | 1818 | * Device is not guaranteed to be in the requested state yet. |
@@ -1816,11 +1820,11 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) | |||
1816 | * device has entered the correct state. | 1820 | * device has entered the correct state. |
1817 | */ | 1821 | */ |
1818 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 1822 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
1819 | rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®2); | 1823 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, ®2); |
1820 | state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE); | 1824 | state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE); |
1821 | if (state == !put_to_sleep) | 1825 | if (state == !put_to_sleep) |
1822 | return 0; | 1826 | return 0; |
1823 | rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg); | 1827 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg); |
1824 | msleep(10); | 1828 | msleep(10); |
1825 | } | 1829 | } |
1826 | 1830 | ||
@@ -1868,7 +1872,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, | |||
1868 | struct txentry_desc *txdesc) | 1872 | struct txentry_desc *txdesc) |
1869 | { | 1873 | { |
1870 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1874 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
1871 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1875 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
1872 | __le32 *txd = entry_priv->desc; | 1876 | __le32 *txd = entry_priv->desc; |
1873 | u32 word; | 1877 | u32 word; |
1874 | 1878 | ||
@@ -1966,7 +1970,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry, | |||
1966 | struct txentry_desc *txdesc) | 1970 | struct txentry_desc *txdesc) |
1967 | { | 1971 | { |
1968 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 1972 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
1969 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1973 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
1970 | unsigned int beacon_base; | 1974 | unsigned int beacon_base; |
1971 | unsigned int padding_len; | 1975 | unsigned int padding_len; |
1972 | u32 orig_reg, reg; | 1976 | u32 orig_reg, reg; |
@@ -1975,10 +1979,10 @@ static void rt61pci_write_beacon(struct queue_entry *entry, | |||
1975 | * Disable beaconing while we are reloading the beacon data, | 1979 | * Disable beaconing while we are reloading the beacon data, |
1976 | * otherwise we might be sending out invalid data. | 1980 | * otherwise we might be sending out invalid data. |
1977 | */ | 1981 | */ |
1978 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 1982 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®); |
1979 | orig_reg = reg; | 1983 | orig_reg = reg; |
1980 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | 1984 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); |
1981 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 1985 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); |
1982 | 1986 | ||
1983 | /* | 1987 | /* |
1984 | * Write the TX descriptor for the beacon. | 1988 | * Write the TX descriptor for the beacon. |
@@ -1998,16 +2002,16 @@ static void rt61pci_write_beacon(struct queue_entry *entry, | |||
1998 | ERROR(rt2x00dev, "Failure padding beacon, aborting\n"); | 2002 | ERROR(rt2x00dev, "Failure padding beacon, aborting\n"); |
1999 | /* skb freed by skb_pad() on failure */ | 2003 | /* skb freed by skb_pad() on failure */ |
2000 | entry->skb = NULL; | 2004 | entry->skb = NULL; |
2001 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, orig_reg); | 2005 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, orig_reg); |
2002 | return; | 2006 | return; |
2003 | } | 2007 | } |
2004 | 2008 | ||
2005 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | 2009 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); |
2006 | rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, | 2010 | rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base, |
2007 | entry_priv->desc, TXINFO_SIZE); | 2011 | entry_priv->desc, TXINFO_SIZE); |
2008 | rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE, | 2012 | rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE, |
2009 | entry->skb->data, | 2013 | entry->skb->data, |
2010 | entry->skb->len + padding_len); | 2014 | entry->skb->len + padding_len); |
2011 | 2015 | ||
2012 | /* | 2016 | /* |
2013 | * Enable beaconing again. | 2017 | * Enable beaconing again. |
@@ -2015,10 +2019,10 @@ static void rt61pci_write_beacon(struct queue_entry *entry, | |||
2015 | * For Wi-Fi faily generated beacons between participating | 2019 | * For Wi-Fi faily generated beacons between participating |
2016 | * stations. Set TBTT phase adaptive adjustment step to 8us. | 2020 | * stations. Set TBTT phase adaptive adjustment step to 8us. |
2017 | */ | 2021 | */ |
2018 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); | 2022 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); |
2019 | 2023 | ||
2020 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | 2024 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); |
2021 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 2025 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); |
2022 | 2026 | ||
2023 | /* | 2027 | /* |
2024 | * Clean up beacon skb. | 2028 | * Clean up beacon skb. |
@@ -2036,21 +2040,21 @@ static void rt61pci_clear_beacon(struct queue_entry *entry) | |||
2036 | * Disable beaconing while we are reloading the beacon data, | 2040 | * Disable beaconing while we are reloading the beacon data, |
2037 | * otherwise we might be sending out invalid data. | 2041 | * otherwise we might be sending out invalid data. |
2038 | */ | 2042 | */ |
2039 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 2043 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®); |
2040 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | 2044 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); |
2041 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 2045 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); |
2042 | 2046 | ||
2043 | /* | 2047 | /* |
2044 | * Clear beacon. | 2048 | * Clear beacon. |
2045 | */ | 2049 | */ |
2046 | rt2x00pci_register_write(rt2x00dev, | 2050 | rt2x00mmio_register_write(rt2x00dev, |
2047 | HW_BEACON_OFFSET(entry->entry_idx), 0); | 2051 | HW_BEACON_OFFSET(entry->entry_idx), 0); |
2048 | 2052 | ||
2049 | /* | 2053 | /* |
2050 | * Enable beaconing again. | 2054 | * Enable beaconing again. |
2051 | */ | 2055 | */ |
2052 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | 2056 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); |
2053 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 2057 | rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); |
2054 | } | 2058 | } |
2055 | 2059 | ||
2056 | /* | 2060 | /* |
@@ -2088,7 +2092,7 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry, | |||
2088 | struct rxdone_entry_desc *rxdesc) | 2092 | struct rxdone_entry_desc *rxdesc) |
2089 | { | 2093 | { |
2090 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 2094 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
2091 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 2095 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; |
2092 | u32 word0; | 2096 | u32 word0; |
2093 | u32 word1; | 2097 | u32 word1; |
2094 | 2098 | ||
@@ -2154,7 +2158,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2154 | struct data_queue *queue; | 2158 | struct data_queue *queue; |
2155 | struct queue_entry *entry; | 2159 | struct queue_entry *entry; |
2156 | struct queue_entry *entry_done; | 2160 | struct queue_entry *entry_done; |
2157 | struct queue_entry_priv_pci *entry_priv; | 2161 | struct queue_entry_priv_mmio *entry_priv; |
2158 | struct txdone_entry_desc txdesc; | 2162 | struct txdone_entry_desc txdesc; |
2159 | u32 word; | 2163 | u32 word; |
2160 | u32 reg; | 2164 | u32 reg; |
@@ -2172,7 +2176,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2172 | * tx ring size for now. | 2176 | * tx ring size for now. |
2173 | */ | 2177 | */ |
2174 | for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { | 2178 | for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { |
2175 | rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); | 2179 | rt2x00mmio_register_read(rt2x00dev, STA_CSR4, ®); |
2176 | if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) | 2180 | if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) |
2177 | break; | 2181 | break; |
2178 | 2182 | ||
@@ -2259,9 +2263,9 @@ static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, | |||
2259 | */ | 2263 | */ |
2260 | spin_lock_irq(&rt2x00dev->irqmask_lock); | 2264 | spin_lock_irq(&rt2x00dev->irqmask_lock); |
2261 | 2265 | ||
2262 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | 2266 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); |
2263 | rt2x00_set_field32(®, irq_field, 0); | 2267 | rt2x00_set_field32(®, irq_field, 0); |
2264 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); | 2268 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); |
2265 | 2269 | ||
2266 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | 2270 | spin_unlock_irq(&rt2x00dev->irqmask_lock); |
2267 | } | 2271 | } |
@@ -2277,9 +2281,9 @@ static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev, | |||
2277 | */ | 2281 | */ |
2278 | spin_lock_irq(&rt2x00dev->irqmask_lock); | 2282 | spin_lock_irq(&rt2x00dev->irqmask_lock); |
2279 | 2283 | ||
2280 | rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); | 2284 | rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); |
2281 | rt2x00_set_field32(®, irq_field, 0); | 2285 | rt2x00_set_field32(®, irq_field, 0); |
2282 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); | 2286 | rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); |
2283 | 2287 | ||
2284 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | 2288 | spin_unlock_irq(&rt2x00dev->irqmask_lock); |
2285 | } | 2289 | } |
@@ -2303,7 +2307,7 @@ static void rt61pci_tbtt_tasklet(unsigned long data) | |||
2303 | static void rt61pci_rxdone_tasklet(unsigned long data) | 2307 | static void rt61pci_rxdone_tasklet(unsigned long data) |
2304 | { | 2308 | { |
2305 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | 2309 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
2306 | if (rt2x00pci_rxdone(rt2x00dev)) | 2310 | if (rt2x00mmio_rxdone(rt2x00dev)) |
2307 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | 2311 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); |
2308 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 2312 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
2309 | rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); | 2313 | rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); |
@@ -2313,8 +2317,8 @@ static void rt61pci_autowake_tasklet(unsigned long data) | |||
2313 | { | 2317 | { |
2314 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | 2318 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
2315 | rt61pci_wakeup(rt2x00dev); | 2319 | rt61pci_wakeup(rt2x00dev); |
2316 | rt2x00pci_register_write(rt2x00dev, | 2320 | rt2x00mmio_register_write(rt2x00dev, |
2317 | M2H_CMD_DONE_CSR, 0xffffffff); | 2321 | M2H_CMD_DONE_CSR, 0xffffffff); |
2318 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 2322 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
2319 | rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP); | 2323 | rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP); |
2320 | } | 2324 | } |
@@ -2329,11 +2333,11 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | |||
2329 | * Get the interrupt sources & saved to local variable. | 2333 | * Get the interrupt sources & saved to local variable. |
2330 | * Write register value back to clear pending interrupts. | 2334 | * Write register value back to clear pending interrupts. |
2331 | */ | 2335 | */ |
2332 | rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®_mcu); | 2336 | rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®_mcu); |
2333 | rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu); | 2337 | rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu); |
2334 | 2338 | ||
2335 | rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | 2339 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); |
2336 | rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | 2340 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); |
2337 | 2341 | ||
2338 | if (!reg && !reg_mcu) | 2342 | if (!reg && !reg_mcu) |
2339 | return IRQ_NONE; | 2343 | return IRQ_NONE; |
@@ -2370,13 +2374,13 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | |||
2370 | */ | 2374 | */ |
2371 | spin_lock(&rt2x00dev->irqmask_lock); | 2375 | spin_lock(&rt2x00dev->irqmask_lock); |
2372 | 2376 | ||
2373 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | 2377 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); |
2374 | reg |= mask; | 2378 | reg |= mask; |
2375 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); | 2379 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); |
2376 | 2380 | ||
2377 | rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); | 2381 | rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); |
2378 | reg |= mask_mcu; | 2382 | reg |= mask_mcu; |
2379 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); | 2383 | rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); |
2380 | 2384 | ||
2381 | spin_unlock(&rt2x00dev->irqmask_lock); | 2385 | spin_unlock(&rt2x00dev->irqmask_lock); |
2382 | 2386 | ||
@@ -2394,7 +2398,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2394 | u8 *mac; | 2398 | u8 *mac; |
2395 | s8 value; | 2399 | s8 value; |
2396 | 2400 | ||
2397 | rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); | 2401 | rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, ®); |
2398 | 2402 | ||
2399 | eeprom.data = rt2x00dev; | 2403 | eeprom.data = rt2x00dev; |
2400 | eeprom.register_read = rt61pci_eepromregister_read; | 2404 | eeprom.register_read = rt61pci_eepromregister_read; |
@@ -2512,7 +2516,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2512 | * Identify RF chipset. | 2516 | * Identify RF chipset. |
2513 | */ | 2517 | */ |
2514 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 2518 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
2515 | rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); | 2519 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, ®); |
2516 | rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), | 2520 | rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), |
2517 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); | 2521 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); |
2518 | 2522 | ||
@@ -2837,7 +2841,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
2837 | /* | 2841 | /* |
2838 | * Disable power saving. | 2842 | * Disable power saving. |
2839 | */ | 2843 | */ |
2840 | rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007); | 2844 | rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007); |
2841 | 2845 | ||
2842 | /* | 2846 | /* |
2843 | * Allocate eeprom data. | 2847 | * Allocate eeprom data. |
@@ -2854,9 +2858,9 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
2854 | * Enable rfkill polling by setting GPIO direction of the | 2858 | * Enable rfkill polling by setting GPIO direction of the |
2855 | * rfkill switch GPIO pin correctly. | 2859 | * rfkill switch GPIO pin correctly. |
2856 | */ | 2860 | */ |
2857 | rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); | 2861 | rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, ®); |
2858 | rt2x00_set_field32(®, MAC_CSR13_DIR5, 1); | 2862 | rt2x00_set_field32(®, MAC_CSR13_DIR5, 1); |
2859 | rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); | 2863 | rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg); |
2860 | 2864 | ||
2861 | /* | 2865 | /* |
2862 | * Initialize hw specifications. | 2866 | * Initialize hw specifications. |
@@ -2926,25 +2930,25 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, | |||
2926 | field.bit_offset = (queue_idx & 1) * 16; | 2930 | field.bit_offset = (queue_idx & 1) * 16; |
2927 | field.bit_mask = 0xffff << field.bit_offset; | 2931 | field.bit_mask = 0xffff << field.bit_offset; |
2928 | 2932 | ||
2929 | rt2x00pci_register_read(rt2x00dev, offset, ®); | 2933 | rt2x00mmio_register_read(rt2x00dev, offset, ®); |
2930 | rt2x00_set_field32(®, field, queue->txop); | 2934 | rt2x00_set_field32(®, field, queue->txop); |
2931 | rt2x00pci_register_write(rt2x00dev, offset, reg); | 2935 | rt2x00mmio_register_write(rt2x00dev, offset, reg); |
2932 | 2936 | ||
2933 | /* Update WMM registers */ | 2937 | /* Update WMM registers */ |
2934 | field.bit_offset = queue_idx * 4; | 2938 | field.bit_offset = queue_idx * 4; |
2935 | field.bit_mask = 0xf << field.bit_offset; | 2939 | field.bit_mask = 0xf << field.bit_offset; |
2936 | 2940 | ||
2937 | rt2x00pci_register_read(rt2x00dev, AIFSN_CSR, ®); | 2941 | rt2x00mmio_register_read(rt2x00dev, AIFSN_CSR, ®); |
2938 | rt2x00_set_field32(®, field, queue->aifs); | 2942 | rt2x00_set_field32(®, field, queue->aifs); |
2939 | rt2x00pci_register_write(rt2x00dev, AIFSN_CSR, reg); | 2943 | rt2x00mmio_register_write(rt2x00dev, AIFSN_CSR, reg); |
2940 | 2944 | ||
2941 | rt2x00pci_register_read(rt2x00dev, CWMIN_CSR, ®); | 2945 | rt2x00mmio_register_read(rt2x00dev, CWMIN_CSR, ®); |
2942 | rt2x00_set_field32(®, field, queue->cw_min); | 2946 | rt2x00_set_field32(®, field, queue->cw_min); |
2943 | rt2x00pci_register_write(rt2x00dev, CWMIN_CSR, reg); | 2947 | rt2x00mmio_register_write(rt2x00dev, CWMIN_CSR, reg); |
2944 | 2948 | ||
2945 | rt2x00pci_register_read(rt2x00dev, CWMAX_CSR, ®); | 2949 | rt2x00mmio_register_read(rt2x00dev, CWMAX_CSR, ®); |
2946 | rt2x00_set_field32(®, field, queue->cw_max); | 2950 | rt2x00_set_field32(®, field, queue->cw_max); |
2947 | rt2x00pci_register_write(rt2x00dev, CWMAX_CSR, reg); | 2951 | rt2x00mmio_register_write(rt2x00dev, CWMAX_CSR, reg); |
2948 | 2952 | ||
2949 | return 0; | 2953 | return 0; |
2950 | } | 2954 | } |
@@ -2955,9 +2959,9 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
2955 | u64 tsf; | 2959 | u64 tsf; |
2956 | u32 reg; | 2960 | u32 reg; |
2957 | 2961 | ||
2958 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR13, ®); | 2962 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR13, ®); |
2959 | tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; | 2963 | tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; |
2960 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR12, ®); | 2964 | rt2x00mmio_register_read(rt2x00dev, TXRX_CSR12, ®); |
2961 | tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER); | 2965 | tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER); |
2962 | 2966 | ||
2963 | return tsf; | 2967 | return tsf; |
@@ -2996,8 +3000,8 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | |||
2996 | .get_firmware_name = rt61pci_get_firmware_name, | 3000 | .get_firmware_name = rt61pci_get_firmware_name, |
2997 | .check_firmware = rt61pci_check_firmware, | 3001 | .check_firmware = rt61pci_check_firmware, |
2998 | .load_firmware = rt61pci_load_firmware, | 3002 | .load_firmware = rt61pci_load_firmware, |
2999 | .initialize = rt2x00pci_initialize, | 3003 | .initialize = rt2x00mmio_initialize, |
3000 | .uninitialize = rt2x00pci_uninitialize, | 3004 | .uninitialize = rt2x00mmio_uninitialize, |
3001 | .get_entry_state = rt61pci_get_entry_state, | 3005 | .get_entry_state = rt61pci_get_entry_state, |
3002 | .clear_entry = rt61pci_clear_entry, | 3006 | .clear_entry = rt61pci_clear_entry, |
3003 | .set_device_state = rt61pci_set_device_state, | 3007 | .set_device_state = rt61pci_set_device_state, |
@@ -3008,7 +3012,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | |||
3008 | .start_queue = rt61pci_start_queue, | 3012 | .start_queue = rt61pci_start_queue, |
3009 | .kick_queue = rt61pci_kick_queue, | 3013 | .kick_queue = rt61pci_kick_queue, |
3010 | .stop_queue = rt61pci_stop_queue, | 3014 | .stop_queue = rt61pci_stop_queue, |
3011 | .flush_queue = rt2x00pci_flush_queue, | 3015 | .flush_queue = rt2x00mmio_flush_queue, |
3012 | .write_tx_desc = rt61pci_write_tx_desc, | 3016 | .write_tx_desc = rt61pci_write_tx_desc, |
3013 | .write_beacon = rt61pci_write_beacon, | 3017 | .write_beacon = rt61pci_write_beacon, |
3014 | .clear_beacon = rt61pci_clear_beacon, | 3018 | .clear_beacon = rt61pci_clear_beacon, |
@@ -3026,21 +3030,21 @@ static const struct data_queue_desc rt61pci_queue_rx = { | |||
3026 | .entry_num = 32, | 3030 | .entry_num = 32, |
3027 | .data_size = DATA_FRAME_SIZE, | 3031 | .data_size = DATA_FRAME_SIZE, |
3028 | .desc_size = RXD_DESC_SIZE, | 3032 | .desc_size = RXD_DESC_SIZE, |
3029 | .priv_size = sizeof(struct queue_entry_priv_pci), | 3033 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
3030 | }; | 3034 | }; |
3031 | 3035 | ||
3032 | static const struct data_queue_desc rt61pci_queue_tx = { | 3036 | static const struct data_queue_desc rt61pci_queue_tx = { |
3033 | .entry_num = 32, | 3037 | .entry_num = 32, |
3034 | .data_size = DATA_FRAME_SIZE, | 3038 | .data_size = DATA_FRAME_SIZE, |
3035 | .desc_size = TXD_DESC_SIZE, | 3039 | .desc_size = TXD_DESC_SIZE, |
3036 | .priv_size = sizeof(struct queue_entry_priv_pci), | 3040 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
3037 | }; | 3041 | }; |
3038 | 3042 | ||
3039 | static const struct data_queue_desc rt61pci_queue_bcn = { | 3043 | static const struct data_queue_desc rt61pci_queue_bcn = { |
3040 | .entry_num = 4, | 3044 | .entry_num = 4, |
3041 | .data_size = 0, /* No DMA required for beacons */ | 3045 | .data_size = 0, /* No DMA required for beacons */ |
3042 | .desc_size = TXINFO_SIZE, | 3046 | .desc_size = TXINFO_SIZE, |
3043 | .priv_size = sizeof(struct queue_entry_priv_pci), | 3047 | .priv_size = sizeof(struct queue_entry_priv_mmio), |
3044 | }; | 3048 | }; |
3045 | 3049 | ||
3046 | static const struct rt2x00_ops rt61pci_ops = { | 3050 | static const struct rt2x00_ops rt61pci_ops = { |
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig index b6aa0c40658f..7253de3d8c66 100644 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ b/drivers/net/wireless/rtlwifi/Kconfig | |||
@@ -55,6 +55,15 @@ config RTL8723AE | |||
55 | 55 | ||
56 | If you choose to build it as a module, it will be called rtl8723ae | 56 | If you choose to build it as a module, it will be called rtl8723ae |
57 | 57 | ||
58 | config RTL8188EE | ||
59 | tristate "Realtek RTL8188EE Wireless Network Adapter" | ||
60 | depends on RTLWIFI && PCI | ||
61 | ---help--- | ||
62 | This is the driver for Realtek RTL8188EE 802.11n PCIe | ||
63 | wireless network adapters. | ||
64 | |||
65 | If you choose to build it as a module, it will be called rtl8188ee | ||
66 | |||
58 | config RTL8192CU | 67 | config RTL8192CU |
59 | tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" | 68 | tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" |
60 | depends on RTLWIFI && USB | 69 | depends on RTLWIFI && USB |
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile index 3b1cbac741e3..ff02b874f8d8 100644 --- a/drivers/net/wireless/rtlwifi/Makefile +++ b/drivers/net/wireless/rtlwifi/Makefile | |||
@@ -26,5 +26,6 @@ obj-$(CONFIG_RTL8192CU) += rtl8192cu/ | |||
26 | obj-$(CONFIG_RTL8192SE) += rtl8192se/ | 26 | obj-$(CONFIG_RTL8192SE) += rtl8192se/ |
27 | obj-$(CONFIG_RTL8192DE) += rtl8192de/ | 27 | obj-$(CONFIG_RTL8192DE) += rtl8192de/ |
28 | obj-$(CONFIG_RTL8723AE) += rtl8723ae/ | 28 | obj-$(CONFIG_RTL8723AE) += rtl8723ae/ |
29 | obj-$(CONFIG_RTL8188EE) += rtl8188ee/ | ||
29 | 30 | ||
30 | ccflags-y += -D__CHECK_ENDIAN__ | 31 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 0e7866d1d0e2..af59dd5718e1 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -54,7 +54,8 @@ | |||
54 | *5) frame process functions | 54 | *5) frame process functions |
55 | *6) IOT functions | 55 | *6) IOT functions |
56 | *7) sysfs functions | 56 | *7) sysfs functions |
57 | *8) ... | 57 | *8) vif functions |
58 | *9) ... | ||
58 | */ | 59 | */ |
59 | 60 | ||
60 | /********************************************************* | 61 | /********************************************************* |
@@ -198,34 +199,46 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, | |||
198 | 199 | ||
199 | ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 200 | ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
200 | 201 | ||
201 | /* | 202 | /*hw->wiphy->bands[IEEE80211_BAND_2GHZ] |
202 | *hw->wiphy->bands[IEEE80211_BAND_2GHZ] | ||
203 | *base on ant_num | 203 | *base on ant_num |
204 | *rx_mask: RX mask | 204 | *rx_mask: RX mask |
205 | *if rx_ant =1 rx_mask[0]=0xff;==>MCS0-MCS7 | 205 | *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 |
206 | *if rx_ant =2 rx_mask[1]=0xff;==>MCS8-MCS15 | 206 | *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15 |
207 | *if rx_ant >=3 rx_mask[2]=0xff; | 207 | *if rx_ant >= 3 rx_mask[2]= 0xff; |
208 | *if BW_40 rx_mask[4]=0x01; | 208 | *if BW_40 rx_mask[4]= 0x01; |
209 | *highest supported RX rate | 209 | *highest supported RX rate |
210 | */ | 210 | */ |
211 | if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_2T2R) { | 211 | if (rtlpriv->dm.supp_phymode_switch) { |
212 | 212 | ||
213 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T2R or 2T2R\n"); | 213 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, |
214 | "Support phy mode switch\n"); | ||
214 | 215 | ||
215 | ht_cap->mcs.rx_mask[0] = 0xFF; | 216 | ht_cap->mcs.rx_mask[0] = 0xFF; |
216 | ht_cap->mcs.rx_mask[1] = 0xFF; | 217 | ht_cap->mcs.rx_mask[1] = 0xFF; |
217 | ht_cap->mcs.rx_mask[4] = 0x01; | 218 | ht_cap->mcs.rx_mask[4] = 0x01; |
218 | 219 | ||
219 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); | 220 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); |
220 | } else if (get_rf_type(rtlphy) == RF_1T1R) { | 221 | } else { |
221 | 222 | if (get_rf_type(rtlphy) == RF_1T2R || | |
222 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n"); | 223 | get_rf_type(rtlphy) == RF_2T2R) { |
223 | 224 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | |
224 | ht_cap->mcs.rx_mask[0] = 0xFF; | 225 | "1T2R or 2T2R\n"); |
225 | ht_cap->mcs.rx_mask[1] = 0x00; | 226 | ht_cap->mcs.rx_mask[0] = 0xFF; |
226 | ht_cap->mcs.rx_mask[4] = 0x01; | 227 | ht_cap->mcs.rx_mask[1] = 0xFF; |
227 | 228 | ht_cap->mcs.rx_mask[4] = 0x01; | |
228 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); | 229 | |
230 | ht_cap->mcs.rx_highest = | ||
231 | cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); | ||
232 | } else if (get_rf_type(rtlphy) == RF_1T1R) { | ||
233 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n"); | ||
234 | |||
235 | ht_cap->mcs.rx_mask[0] = 0xFF; | ||
236 | ht_cap->mcs.rx_mask[1] = 0x00; | ||
237 | ht_cap->mcs.rx_mask[4] = 0x01; | ||
238 | |||
239 | ht_cap->mcs.rx_highest = | ||
240 | cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); | ||
241 | } | ||
229 | } | 242 | } |
230 | } | 243 | } |
231 | 244 | ||
@@ -311,6 +324,8 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) | |||
311 | IEEE80211_HW_AMPDU_AGGREGATION | | 324 | IEEE80211_HW_AMPDU_AGGREGATION | |
312 | IEEE80211_HW_CONNECTION_MONITOR | | 325 | IEEE80211_HW_CONNECTION_MONITOR | |
313 | /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */ | 326 | /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */ |
327 | IEEE80211_HW_CONNECTION_MONITOR | | ||
328 | IEEE80211_HW_MFP_CAPABLE | | ||
314 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; | 329 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; |
315 | 330 | ||
316 | /* swlps or hwlps has been set in diff chip in init_sw_vars */ | 331 | /* swlps or hwlps has been set in diff chip in init_sw_vars */ |
@@ -323,8 +338,12 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) | |||
323 | hw->wiphy->interface_modes = | 338 | hw->wiphy->interface_modes = |
324 | BIT(NL80211_IFTYPE_AP) | | 339 | BIT(NL80211_IFTYPE_AP) | |
325 | BIT(NL80211_IFTYPE_STATION) | | 340 | BIT(NL80211_IFTYPE_STATION) | |
326 | BIT(NL80211_IFTYPE_ADHOC); | 341 | BIT(NL80211_IFTYPE_ADHOC) | |
342 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
343 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
344 | BIT(NL80211_IFTYPE_P2P_GO); | ||
327 | 345 | ||
346 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
328 | hw->wiphy->rts_threshold = 2347; | 347 | hw->wiphy->rts_threshold = 2347; |
329 | 348 | ||
330 | hw->queues = AC_MAX; | 349 | hw->queues = AC_MAX; |
@@ -354,9 +373,10 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) | |||
354 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 373 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
355 | 374 | ||
356 | /* <1> timer */ | 375 | /* <1> timer */ |
357 | init_timer(&rtlpriv->works.watchdog_timer); | ||
358 | setup_timer(&rtlpriv->works.watchdog_timer, | 376 | setup_timer(&rtlpriv->works.watchdog_timer, |
359 | rtl_watch_dog_timer_callback, (unsigned long)hw); | 377 | rtl_watch_dog_timer_callback, (unsigned long)hw); |
378 | setup_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer, | ||
379 | rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw); | ||
360 | 380 | ||
361 | /* <2> work queue */ | 381 | /* <2> work queue */ |
362 | rtlpriv->works.hw = hw; | 382 | rtlpriv->works.hw = hw; |
@@ -369,6 +389,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) | |||
369 | (void *)rtl_swlps_wq_callback); | 389 | (void *)rtl_swlps_wq_callback); |
370 | INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, | 390 | INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, |
371 | (void *)rtl_swlps_rfon_wq_callback); | 391 | (void *)rtl_swlps_rfon_wq_callback); |
392 | INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, | ||
393 | (void *)rtl_fwevt_wq_callback); | ||
372 | 394 | ||
373 | } | 395 | } |
374 | 396 | ||
@@ -382,6 +404,7 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw) | |||
382 | cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); | 404 | cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); |
383 | cancel_delayed_work(&rtlpriv->works.ps_work); | 405 | cancel_delayed_work(&rtlpriv->works.ps_work); |
384 | cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); | 406 | cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); |
407 | cancel_delayed_work(&rtlpriv->works.fwevt_wq); | ||
385 | } | 408 | } |
386 | 409 | ||
387 | void rtl_init_rfkill(struct ieee80211_hw *hw) | 410 | void rtl_init_rfkill(struct ieee80211_hw *hw) |
@@ -436,12 +459,6 @@ int rtl_init_core(struct ieee80211_hw *hw) | |||
436 | if (rtl_regd_init(hw, rtl_reg_notifier)) { | 459 | if (rtl_regd_init(hw, rtl_reg_notifier)) { |
437 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "REGD init failed\n"); | 460 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "REGD init failed\n"); |
438 | return 1; | 461 | return 1; |
439 | } else { | ||
440 | /* CRDA regd hint must after init CRDA */ | ||
441 | if (regulatory_hint(hw->wiphy, rtlpriv->regd.alpha2)) { | ||
442 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
443 | "regulatory_hint fail\n"); | ||
444 | } | ||
445 | } | 462 | } |
446 | 463 | ||
447 | /* <4> locks */ | 464 | /* <4> locks */ |
@@ -449,15 +466,25 @@ int rtl_init_core(struct ieee80211_hw *hw) | |||
449 | mutex_init(&rtlpriv->locks.ps_mutex); | 466 | mutex_init(&rtlpriv->locks.ps_mutex); |
450 | spin_lock_init(&rtlpriv->locks.ips_lock); | 467 | spin_lock_init(&rtlpriv->locks.ips_lock); |
451 | spin_lock_init(&rtlpriv->locks.irq_th_lock); | 468 | spin_lock_init(&rtlpriv->locks.irq_th_lock); |
469 | spin_lock_init(&rtlpriv->locks.irq_pci_lock); | ||
470 | spin_lock_init(&rtlpriv->locks.tx_lock); | ||
452 | spin_lock_init(&rtlpriv->locks.h2c_lock); | 471 | spin_lock_init(&rtlpriv->locks.h2c_lock); |
453 | spin_lock_init(&rtlpriv->locks.rf_ps_lock); | 472 | spin_lock_init(&rtlpriv->locks.rf_ps_lock); |
454 | spin_lock_init(&rtlpriv->locks.rf_lock); | 473 | spin_lock_init(&rtlpriv->locks.rf_lock); |
455 | spin_lock_init(&rtlpriv->locks.waitq_lock); | 474 | spin_lock_init(&rtlpriv->locks.waitq_lock); |
475 | spin_lock_init(&rtlpriv->locks.entry_list_lock); | ||
476 | spin_lock_init(&rtlpriv->locks.fw_ps_lock); | ||
456 | spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); | 477 | spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); |
478 | spin_lock_init(&rtlpriv->locks.check_sendpkt_lock); | ||
479 | spin_lock_init(&rtlpriv->locks.fw_ps_lock); | ||
480 | spin_lock_init(&rtlpriv->locks.lps_lock); | ||
481 | |||
482 | /* <5> init list */ | ||
483 | INIT_LIST_HEAD(&rtlpriv->entry_list); | ||
457 | 484 | ||
458 | rtlmac->link_state = MAC80211_NOLINK; | 485 | rtlmac->link_state = MAC80211_NOLINK; |
459 | 486 | ||
460 | /* <5> init deferred work */ | 487 | /* <6> init deferred work */ |
461 | _rtl_init_deferred_work(hw); | 488 | _rtl_init_deferred_work(hw); |
462 | 489 | ||
463 | return 0; | 490 | return 0; |
@@ -523,7 +550,8 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw, | |||
523 | if (mac->opmode == NL80211_IFTYPE_STATION) | 550 | if (mac->opmode == NL80211_IFTYPE_STATION) |
524 | bw_40 = mac->bw_40; | 551 | bw_40 = mac->bw_40; |
525 | else if (mac->opmode == NL80211_IFTYPE_AP || | 552 | else if (mac->opmode == NL80211_IFTYPE_AP || |
526 | mac->opmode == NL80211_IFTYPE_ADHOC) | 553 | mac->opmode == NL80211_IFTYPE_ADHOC || |
554 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
527 | bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; | 555 | bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; |
528 | 556 | ||
529 | if (bw_40 && sgi_40) | 557 | if (bw_40 && sgi_40) |
@@ -578,23 +606,26 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, | |||
578 | if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { | 606 | if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { |
579 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 607 | if (mac->opmode == NL80211_IFTYPE_STATION) { |
580 | tcb_desc->ratr_index = 0; | 608 | tcb_desc->ratr_index = 0; |
581 | } else if (mac->opmode == NL80211_IFTYPE_ADHOC) { | 609 | } else if (mac->opmode == NL80211_IFTYPE_ADHOC || |
610 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
582 | if (tcb_desc->multicast || tcb_desc->broadcast) { | 611 | if (tcb_desc->multicast || tcb_desc->broadcast) { |
583 | tcb_desc->hw_rate = | 612 | tcb_desc->hw_rate = |
584 | rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; | 613 | rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; |
585 | tcb_desc->use_driver_rate = 1; | 614 | tcb_desc->use_driver_rate = 1; |
615 | tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; | ||
586 | } else { | 616 | } else { |
587 | /* TODO */ | 617 | tcb_desc->ratr_index = ratr_index; |
588 | } | 618 | } |
589 | tcb_desc->ratr_index = ratr_index; | ||
590 | } else if (mac->opmode == NL80211_IFTYPE_AP) { | 619 | } else if (mac->opmode == NL80211_IFTYPE_AP) { |
591 | tcb_desc->ratr_index = ratr_index; | 620 | tcb_desc->ratr_index = ratr_index; |
592 | } | 621 | } |
593 | } | 622 | } |
594 | 623 | ||
595 | if (rtlpriv->dm.useramask) { | 624 | if (rtlpriv->dm.useramask) { |
596 | /* TODO we will differentiate adhoc and station futrue */ | 625 | tcb_desc->ratr_index = ratr_index; |
597 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 626 | /* TODO we will differentiate adhoc and station future */ |
627 | if (mac->opmode == NL80211_IFTYPE_STATION || | ||
628 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
598 | tcb_desc->mac_id = 0; | 629 | tcb_desc->mac_id = 0; |
599 | 630 | ||
600 | if (mac->mode == WIRELESS_MODE_N_24G) | 631 | if (mac->mode == WIRELESS_MODE_N_24G) |
@@ -608,7 +639,7 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, | |||
608 | else if (mac->mode & WIRELESS_MODE_A) | 639 | else if (mac->mode & WIRELESS_MODE_A) |
609 | tcb_desc->ratr_index = RATR_INX_WIRELESS_G; | 640 | tcb_desc->ratr_index = RATR_INX_WIRELESS_G; |
610 | } else if (mac->opmode == NL80211_IFTYPE_AP || | 641 | } else if (mac->opmode == NL80211_IFTYPE_AP || |
611 | mac->opmode == NL80211_IFTYPE_ADHOC) { | 642 | mac->opmode == NL80211_IFTYPE_ADHOC) { |
612 | if (NULL != sta) { | 643 | if (NULL != sta) { |
613 | if (sta->aid > 0) | 644 | if (sta->aid > 0) |
614 | tcb_desc->mac_id = sta->aid + 1; | 645 | tcb_desc->mac_id = sta->aid + 1; |
@@ -619,7 +650,6 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, | |||
619 | } | 650 | } |
620 | } | 651 | } |
621 | } | 652 | } |
622 | |||
623 | } | 653 | } |
624 | 654 | ||
625 | static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, | 655 | static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, |
@@ -633,7 +663,8 @@ static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, | |||
633 | if (!sta) | 663 | if (!sta) |
634 | return; | 664 | return; |
635 | if (mac->opmode == NL80211_IFTYPE_AP || | 665 | if (mac->opmode == NL80211_IFTYPE_AP || |
636 | mac->opmode == NL80211_IFTYPE_ADHOC) { | 666 | mac->opmode == NL80211_IFTYPE_ADHOC || |
667 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
637 | if (sta->bandwidth == IEEE80211_STA_RX_BW_20) | 668 | if (sta->bandwidth == IEEE80211_STA_RX_BW_20) |
638 | return; | 669 | return; |
639 | } else if (mac->opmode == NL80211_IFTYPE_STATION) { | 670 | } else if (mac->opmode == NL80211_IFTYPE_STATION) { |
@@ -834,8 +865,8 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
834 | if (rtlpriv->dm.supp_phymode_switch && | 865 | if (rtlpriv->dm.supp_phymode_switch && |
835 | mac->link_state < MAC80211_LINKED && | 866 | mac->link_state < MAC80211_LINKED && |
836 | (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) { | 867 | (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) { |
837 | if (rtlpriv->cfg->ops->check_switch_to_dmdp) | 868 | if (rtlpriv->cfg->ops->chk_switch_dmdp) |
838 | rtlpriv->cfg->ops->check_switch_to_dmdp(hw); | 869 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); |
839 | } | 870 | } |
840 | if (ieee80211_is_auth(fc)) { | 871 | if (ieee80211_is_auth(fc)) { |
841 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); | 872 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); |
@@ -924,6 +955,56 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, | |||
924 | } | 955 | } |
925 | EXPORT_SYMBOL(rtl_get_tcb_desc); | 956 | EXPORT_SYMBOL(rtl_get_tcb_desc); |
926 | 957 | ||
958 | static bool addbareq_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
959 | { | ||
960 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
961 | struct ieee80211_sta *sta = NULL; | ||
962 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); | ||
963 | struct rtl_sta_info *sta_entry = NULL; | ||
964 | struct ieee80211_mgmt *mgmt = (void *)skb->data; | ||
965 | u16 capab = 0, tid = 0; | ||
966 | struct rtl_tid_data *tid_data; | ||
967 | struct sk_buff *skb_delba = NULL; | ||
968 | struct ieee80211_rx_status rx_status = { 0 }; | ||
969 | |||
970 | rcu_read_lock(); | ||
971 | sta = rtl_find_sta(hw, hdr->addr3); | ||
972 | if (sta == NULL) { | ||
973 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_EMERG, | ||
974 | "sta is NULL\n"); | ||
975 | rcu_read_unlock(); | ||
976 | return true; | ||
977 | } | ||
978 | |||
979 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
980 | if (!sta_entry) { | ||
981 | rcu_read_unlock(); | ||
982 | return true; | ||
983 | } | ||
984 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
985 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
986 | tid_data = &sta_entry->tids[tid]; | ||
987 | if (tid_data->agg.rx_agg_state == RTL_RX_AGG_START) { | ||
988 | skb_delba = rtl_make_del_ba(hw, hdr->addr2, hdr->addr3, tid); | ||
989 | if (skb_delba) { | ||
990 | rx_status.freq = hw->conf.chandef.chan->center_freq; | ||
991 | rx_status.band = hw->conf.chandef.chan->band; | ||
992 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
993 | rx_status.flag |= RX_FLAG_MACTIME_END; | ||
994 | rx_status.rate_idx = 0; | ||
995 | rx_status.signal = 50 + 10; | ||
996 | memcpy(IEEE80211_SKB_RXCB(skb_delba), &rx_status, | ||
997 | sizeof(rx_status)); | ||
998 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, | ||
999 | "fake del\n", skb_delba->data, | ||
1000 | skb_delba->len); | ||
1001 | ieee80211_rx_irqsafe(hw, skb_delba); | ||
1002 | } | ||
1003 | } | ||
1004 | rcu_read_unlock(); | ||
1005 | return false; | ||
1006 | } | ||
1007 | |||
927 | bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | 1008 | bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) |
928 | { | 1009 | { |
929 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1010 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
@@ -948,6 +1029,11 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
948 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, | 1029 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, |
949 | "%s ACT_ADDBAREQ From :%pM\n", | 1030 | "%s ACT_ADDBAREQ From :%pM\n", |
950 | is_tx ? "Tx" : "Rx", hdr->addr2); | 1031 | is_tx ? "Tx" : "Rx", hdr->addr2); |
1032 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "req\n", | ||
1033 | skb->data, skb->len); | ||
1034 | if (!is_tx) | ||
1035 | if (addbareq_rx(hw, skb)) | ||
1036 | return true; | ||
951 | break; | 1037 | break; |
952 | case ACT_ADDBARSP: | 1038 | case ACT_ADDBARSP: |
953 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, | 1039 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, |
@@ -1003,8 +1089,9 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1003 | is_tx ? "Tx" : "Rx"); | 1089 | is_tx ? "Tx" : "Rx"); |
1004 | 1090 | ||
1005 | if (is_tx) { | 1091 | if (is_tx) { |
1092 | rtlpriv->enter_ps = false; | ||
1006 | schedule_work(&rtlpriv-> | 1093 | schedule_work(&rtlpriv-> |
1007 | works.lps_leave_work); | 1094 | works.lps_change_work); |
1008 | ppsc->last_delaylps_stamp_jiffies = | 1095 | ppsc->last_delaylps_stamp_jiffies = |
1009 | jiffies; | 1096 | jiffies; |
1010 | } | 1097 | } |
@@ -1014,7 +1101,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1014 | } | 1101 | } |
1015 | } else if (ETH_P_ARP == ether_type) { | 1102 | } else if (ETH_P_ARP == ether_type) { |
1016 | if (is_tx) { | 1103 | if (is_tx) { |
1017 | schedule_work(&rtlpriv->works.lps_leave_work); | 1104 | rtlpriv->enter_ps = false; |
1105 | schedule_work(&rtlpriv->works.lps_change_work); | ||
1018 | ppsc->last_delaylps_stamp_jiffies = jiffies; | 1106 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1019 | } | 1107 | } |
1020 | 1108 | ||
@@ -1024,7 +1112,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1024 | "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); | 1112 | "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); |
1025 | 1113 | ||
1026 | if (is_tx) { | 1114 | if (is_tx) { |
1027 | schedule_work(&rtlpriv->works.lps_leave_work); | 1115 | rtlpriv->enter_ps = false; |
1116 | schedule_work(&rtlpriv->works.lps_change_work); | ||
1028 | ppsc->last_delaylps_stamp_jiffies = jiffies; | 1117 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1029 | } | 1118 | } |
1030 | 1119 | ||
@@ -1101,6 +1190,58 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw, | |||
1101 | return 0; | 1190 | return 0; |
1102 | } | 1191 | } |
1103 | 1192 | ||
1193 | int rtl_rx_agg_start(struct ieee80211_hw *hw, | ||
1194 | struct ieee80211_sta *sta, u16 tid) | ||
1195 | { | ||
1196 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1197 | struct rtl_tid_data *tid_data; | ||
1198 | struct rtl_sta_info *sta_entry = NULL; | ||
1199 | |||
1200 | if (sta == NULL) | ||
1201 | return -EINVAL; | ||
1202 | |||
1203 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1204 | return -EINVAL; | ||
1205 | |||
1206 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
1207 | if (!sta_entry) | ||
1208 | return -ENXIO; | ||
1209 | tid_data = &sta_entry->tids[tid]; | ||
1210 | |||
1211 | RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG, | ||
1212 | "on ra = %pM tid = %d seq:%d\n", sta->addr, tid, | ||
1213 | tid_data->seq_number); | ||
1214 | |||
1215 | tid_data->agg.rx_agg_state = RTL_RX_AGG_START; | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | int rtl_rx_agg_stop(struct ieee80211_hw *hw, | ||
1220 | struct ieee80211_sta *sta, u16 tid) | ||
1221 | { | ||
1222 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1223 | struct rtl_sta_info *sta_entry = NULL; | ||
1224 | |||
1225 | if (sta == NULL) | ||
1226 | return -EINVAL; | ||
1227 | |||
1228 | if (!sta->addr) { | ||
1229 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "ra = NULL\n"); | ||
1230 | return -EINVAL; | ||
1231 | } | ||
1232 | |||
1233 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, | ||
1234 | "on ra = %pM tid = %d\n", sta->addr, tid); | ||
1235 | |||
1236 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1237 | return -EINVAL; | ||
1238 | |||
1239 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
1240 | sta_entry->tids[tid].agg.rx_agg_state = RTL_RX_AGG_STOP; | ||
1241 | |||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1104 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, | 1245 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, |
1105 | struct ieee80211_sta *sta, u16 tid) | 1246 | struct ieee80211_sta *sta, u16 tid) |
1106 | { | 1247 | { |
@@ -1132,6 +1273,34 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw, | |||
1132 | * wq & timer callback functions | 1273 | * wq & timer callback functions |
1133 | * | 1274 | * |
1134 | *********************************************************/ | 1275 | *********************************************************/ |
1276 | /* this function is used for roaming */ | ||
1277 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1278 | { | ||
1279 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1280 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1281 | |||
1282 | if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) | ||
1283 | return; | ||
1284 | |||
1285 | if (rtlpriv->mac80211.link_state < MAC80211_LINKED) | ||
1286 | return; | ||
1287 | |||
1288 | /* check if this really is a beacon */ | ||
1289 | if (!ieee80211_is_beacon(hdr->frame_control) && | ||
1290 | !ieee80211_is_probe_resp(hdr->frame_control)) | ||
1291 | return; | ||
1292 | |||
1293 | /* min. beacon length + FCS_LEN */ | ||
1294 | if (skb->len <= 40 + FCS_LEN) | ||
1295 | return; | ||
1296 | |||
1297 | /* and only beacons from the associated BSSID, please */ | ||
1298 | if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) | ||
1299 | return; | ||
1300 | |||
1301 | rtlpriv->link_info.bcn_rx_inperiod++; | ||
1302 | } | ||
1303 | |||
1135 | void rtl_watchdog_wq_callback(void *data) | 1304 | void rtl_watchdog_wq_callback(void *data) |
1136 | { | 1305 | { |
1137 | struct rtl_works *rtlworks = container_of_dwork_rtl(data, | 1306 | struct rtl_works *rtlworks = container_of_dwork_rtl(data, |
@@ -1142,6 +1311,8 @@ void rtl_watchdog_wq_callback(void *data) | |||
1142 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1311 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1143 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1312 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1144 | bool busytraffic = false; | 1313 | bool busytraffic = false; |
1314 | bool tx_busy_traffic = false; | ||
1315 | bool rx_busy_traffic = false; | ||
1145 | bool higher_busytraffic = false; | 1316 | bool higher_busytraffic = false; |
1146 | bool higher_busyrxtraffic = false; | 1317 | bool higher_busyrxtraffic = false; |
1147 | u8 idx, tid; | 1318 | u8 idx, tid; |
@@ -1151,7 +1322,6 @@ void rtl_watchdog_wq_callback(void *data) | |||
1151 | u32 aver_tx_cnt_inperiod = 0; | 1322 | u32 aver_tx_cnt_inperiod = 0; |
1152 | u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; | 1323 | u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; |
1153 | u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; | 1324 | u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; |
1154 | bool enter_ps = false; | ||
1155 | 1325 | ||
1156 | if (is_hal_stop(rtlhal)) | 1326 | if (is_hal_stop(rtlhal)) |
1157 | return; | 1327 | return; |
@@ -1191,8 +1361,13 @@ void rtl_watchdog_wq_callback(void *data) | |||
1191 | aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; | 1361 | aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; |
1192 | 1362 | ||
1193 | /* (2) check traffic busy */ | 1363 | /* (2) check traffic busy */ |
1194 | if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) | 1364 | if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) { |
1195 | busytraffic = true; | 1365 | busytraffic = true; |
1366 | if (aver_rx_cnt_inperiod > aver_tx_cnt_inperiod) | ||
1367 | rx_busy_traffic = true; | ||
1368 | else | ||
1369 | tx_busy_traffic = false; | ||
1370 | } | ||
1196 | 1371 | ||
1197 | /* Higher Tx/Rx data. */ | 1372 | /* Higher Tx/Rx data. */ |
1198 | if (aver_rx_cnt_inperiod > 4000 || | 1373 | if (aver_rx_cnt_inperiod > 4000 || |
@@ -1228,15 +1403,12 @@ void rtl_watchdog_wq_callback(void *data) | |||
1228 | if (((rtlpriv->link_info.num_rx_inperiod + | 1403 | if (((rtlpriv->link_info.num_rx_inperiod + |
1229 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 1404 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
1230 | (rtlpriv->link_info.num_rx_inperiod > 2)) | 1405 | (rtlpriv->link_info.num_rx_inperiod > 2)) |
1231 | enter_ps = false; | 1406 | rtlpriv->enter_ps = true; |
1232 | else | 1407 | else |
1233 | enter_ps = true; | 1408 | rtlpriv->enter_ps = false; |
1234 | 1409 | ||
1235 | /* LeisurePS only work in infra mode. */ | 1410 | /* LeisurePS only work in infra mode. */ |
1236 | if (enter_ps) | 1411 | schedule_work(&rtlpriv->works.lps_change_work); |
1237 | rtl_lps_enter(hw); | ||
1238 | else | ||
1239 | rtl_lps_leave(hw); | ||
1240 | } | 1412 | } |
1241 | 1413 | ||
1242 | rtlpriv->link_info.num_rx_inperiod = 0; | 1414 | rtlpriv->link_info.num_rx_inperiod = 0; |
@@ -1246,10 +1418,37 @@ void rtl_watchdog_wq_callback(void *data) | |||
1246 | 1418 | ||
1247 | rtlpriv->link_info.busytraffic = busytraffic; | 1419 | rtlpriv->link_info.busytraffic = busytraffic; |
1248 | rtlpriv->link_info.higher_busytraffic = higher_busytraffic; | 1420 | rtlpriv->link_info.higher_busytraffic = higher_busytraffic; |
1421 | rtlpriv->link_info.rx_busy_traffic = rx_busy_traffic; | ||
1422 | rtlpriv->link_info.tx_busy_traffic = tx_busy_traffic; | ||
1249 | rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; | 1423 | rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; |
1250 | 1424 | ||
1251 | /* <3> DM */ | 1425 | /* <3> DM */ |
1252 | rtlpriv->cfg->ops->dm_watchdog(hw); | 1426 | rtlpriv->cfg->ops->dm_watchdog(hw); |
1427 | |||
1428 | /* <4> roaming */ | ||
1429 | if (mac->link_state == MAC80211_LINKED && | ||
1430 | mac->opmode == NL80211_IFTYPE_STATION) { | ||
1431 | if ((rtlpriv->link_info.bcn_rx_inperiod + | ||
1432 | rtlpriv->link_info.num_rx_inperiod) == 0) { | ||
1433 | rtlpriv->link_info.roam_times++; | ||
1434 | RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, | ||
1435 | "AP off for %d s\n", | ||
1436 | (rtlpriv->link_info.roam_times * 2)); | ||
1437 | |||
1438 | /* if we can't recv beacon for 6s, we should | ||
1439 | * reconnect this AP | ||
1440 | */ | ||
1441 | if (rtlpriv->link_info.roam_times >= 3) { | ||
1442 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1443 | "AP off, try to reconnect now\n"); | ||
1444 | rtlpriv->link_info.roam_times = 0; | ||
1445 | ieee80211_connection_loss(rtlpriv->mac80211.vif); | ||
1446 | } | ||
1447 | } else { | ||
1448 | rtlpriv->link_info.roam_times = 0; | ||
1449 | } | ||
1450 | } | ||
1451 | rtlpriv->link_info.bcn_rx_inperiod = 0; | ||
1253 | } | 1452 | } |
1254 | 1453 | ||
1255 | void rtl_watch_dog_timer_callback(unsigned long data) | 1454 | void rtl_watch_dog_timer_callback(unsigned long data) |
@@ -1264,6 +1463,28 @@ void rtl_watch_dog_timer_callback(unsigned long data) | |||
1264 | jiffies + MSECS(RTL_WATCH_DOG_TIME)); | 1463 | jiffies + MSECS(RTL_WATCH_DOG_TIME)); |
1265 | } | 1464 | } |
1266 | 1465 | ||
1466 | void rtl_fwevt_wq_callback(void *data) | ||
1467 | { | ||
1468 | struct rtl_works *rtlworks = | ||
1469 | container_of_dwork_rtl(data, struct rtl_works, fwevt_wq); | ||
1470 | struct ieee80211_hw *hw = rtlworks->hw; | ||
1471 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1472 | |||
1473 | rtlpriv->cfg->ops->c2h_command_handle(hw); | ||
1474 | } | ||
1475 | |||
1476 | void rtl_easy_concurrent_retrytimer_callback(unsigned long data) | ||
1477 | { | ||
1478 | struct ieee80211_hw *hw = (struct ieee80211_hw *)data; | ||
1479 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1480 | struct rtl_priv *buddy_priv = rtlpriv->buddy_priv; | ||
1481 | |||
1482 | if (buddy_priv == NULL) | ||
1483 | return; | ||
1484 | |||
1485 | rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); | ||
1486 | } | ||
1487 | |||
1267 | /********************************************************* | 1488 | /********************************************************* |
1268 | * | 1489 | * |
1269 | * frame process functions | 1490 | * frame process functions |
@@ -1334,14 +1555,16 @@ static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, | |||
1334 | } | 1555 | } |
1335 | 1556 | ||
1336 | int rtl_send_smps_action(struct ieee80211_hw *hw, | 1557 | int rtl_send_smps_action(struct ieee80211_hw *hw, |
1337 | struct ieee80211_sta *sta, u8 *da, u8 *bssid, | 1558 | struct ieee80211_sta *sta, |
1338 | enum ieee80211_smps_mode smps) | 1559 | enum ieee80211_smps_mode smps) |
1339 | { | 1560 | { |
1340 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1561 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1341 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1562 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1342 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 1563 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
1343 | struct sk_buff *skb = rtl_make_smps_action(hw, smps, da, bssid); | 1564 | struct sk_buff *skb = NULL; |
1344 | struct rtl_tcb_desc tcb_desc; | 1565 | struct rtl_tcb_desc tcb_desc; |
1566 | u8 bssid[ETH_ALEN] = {0}; | ||
1567 | |||
1345 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); | 1568 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); |
1346 | 1569 | ||
1347 | if (rtlpriv->mac80211.act_scanning) | 1570 | if (rtlpriv->mac80211.act_scanning) |
@@ -1356,21 +1579,67 @@ int rtl_send_smps_action(struct ieee80211_hw *hw, | |||
1356 | if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) | 1579 | if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) |
1357 | goto err_free; | 1580 | goto err_free; |
1358 | 1581 | ||
1582 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) | ||
1583 | memcpy(bssid, rtlpriv->efuse.dev_addr, ETH_ALEN); | ||
1584 | else | ||
1585 | memcpy(bssid, rtlpriv->mac80211.bssid, ETH_ALEN); | ||
1586 | |||
1587 | skb = rtl_make_smps_action(hw, smps, sta->addr, bssid); | ||
1359 | /* this is a type = mgmt * stype = action frame */ | 1588 | /* this is a type = mgmt * stype = action frame */ |
1360 | if (skb) { | 1589 | if (skb) { |
1361 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1590 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1362 | struct rtl_sta_info *sta_entry = | 1591 | struct rtl_sta_info *sta_entry = |
1363 | (struct rtl_sta_info *) sta->drv_priv; | 1592 | (struct rtl_sta_info *) sta->drv_priv; |
1364 | sta_entry->mimo_ps = smps; | 1593 | sta_entry->mimo_ps = smps; |
1365 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); | ||
1366 | 1594 | ||
1367 | info->control.rates[0].idx = 0; | 1595 | info->control.rates[0].idx = 0; |
1368 | info->band = hw->conf.chandef.chan->band; | 1596 | info->band = hw->conf.chandef.chan->band; |
1369 | rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); | 1597 | rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); |
1370 | } | 1598 | } |
1599 | return 1; | ||
1600 | |||
1371 | err_free: | 1601 | err_free: |
1372 | return 0; | 1602 | return 0; |
1373 | } | 1603 | } |
1604 | EXPORT_SYMBOL(rtl_send_smps_action); | ||
1605 | |||
1606 | /* There seem to be issues in mac80211 regarding when del ba frames can be | ||
1607 | * received. As a work around, we make a fake del_ba if we receive a ba_req; | ||
1608 | * however, rx_agg was opened to let mac80211 release some ba related | ||
1609 | * resources. This del_ba is for tx only. | ||
1610 | */ | ||
1611 | struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, | ||
1612 | u8 *sa, u8 *bssid, u16 tid) | ||
1613 | { | ||
1614 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1615 | struct sk_buff *skb; | ||
1616 | struct ieee80211_mgmt *action_frame; | ||
1617 | u16 params; | ||
1618 | |||
1619 | /* 27 = header + category + action + smps mode */ | ||
1620 | skb = dev_alloc_skb(34 + hw->extra_tx_headroom); | ||
1621 | if (!skb) | ||
1622 | return NULL; | ||
1623 | |||
1624 | skb_reserve(skb, hw->extra_tx_headroom); | ||
1625 | action_frame = (void *)skb_put(skb, 34); | ||
1626 | memset(action_frame, 0, 34); | ||
1627 | memcpy(action_frame->sa, sa, ETH_ALEN); | ||
1628 | memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN); | ||
1629 | memcpy(action_frame->bssid, bssid, ETH_ALEN); | ||
1630 | action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
1631 | IEEE80211_STYPE_ACTION); | ||
1632 | action_frame->u.action.category = WLAN_CATEGORY_BACK; | ||
1633 | action_frame->u.action.u.delba.action_code = WLAN_ACTION_DELBA; | ||
1634 | params = (u16)(1 << 11); /* bit 11 initiator */ | ||
1635 | params |= (u16)(tid << 12); /* bit 15:12 TID number */ | ||
1636 | |||
1637 | action_frame->u.action.u.delba.params = cpu_to_le16(params); | ||
1638 | action_frame->u.action.u.delba.reason_code = | ||
1639 | cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); | ||
1640 | |||
1641 | return skb; | ||
1642 | } | ||
1374 | 1643 | ||
1375 | /********************************************************* | 1644 | /********************************************************* |
1376 | * | 1645 | * |
@@ -1587,11 +1856,17 @@ MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>"); | |||
1587 | MODULE_LICENSE("GPL"); | 1856 | MODULE_LICENSE("GPL"); |
1588 | MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); | 1857 | MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); |
1589 | 1858 | ||
1859 | struct rtl_global_var global_var = {}; | ||
1860 | |||
1590 | static int __init rtl_core_module_init(void) | 1861 | static int __init rtl_core_module_init(void) |
1591 | { | 1862 | { |
1592 | if (rtl_rate_control_register()) | 1863 | if (rtl_rate_control_register()) |
1593 | pr_err("Unable to register rtl_rc, use default RC !!\n"); | 1864 | pr_err("Unable to register rtl_rc, use default RC !!\n"); |
1594 | 1865 | ||
1866 | /* init some global vars */ | ||
1867 | INIT_LIST_HEAD(&global_var.glb_priv_list); | ||
1868 | spin_lock_init(&global_var.glb_list_lock); | ||
1869 | |||
1595 | return 0; | 1870 | return 0; |
1596 | } | 1871 | } |
1597 | 1872 | ||
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h index 5a8c80e259f7..8576bc34b032 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/rtlwifi/base.h | |||
@@ -113,6 +113,7 @@ void rtl_init_rx_config(struct ieee80211_hw *hw); | |||
113 | void rtl_init_rfkill(struct ieee80211_hw *hw); | 113 | void rtl_init_rfkill(struct ieee80211_hw *hw); |
114 | void rtl_deinit_rfkill(struct ieee80211_hw *hw); | 114 | void rtl_deinit_rfkill(struct ieee80211_hw *hw); |
115 | 115 | ||
116 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
116 | void rtl_watch_dog_timer_callback(unsigned long data); | 117 | void rtl_watch_dog_timer_callback(unsigned long data); |
117 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw); | 118 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw); |
118 | 119 | ||
@@ -126,7 +127,12 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | |||
126 | u16 tid); | 127 | u16 tid); |
127 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 128 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
128 | u16 tid); | 129 | u16 tid); |
130 | int rtl_rx_agg_start(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | ||
131 | u16 tid); | ||
132 | int rtl_rx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | ||
133 | u16 tid); | ||
129 | void rtl_watchdog_wq_callback(void *data); | 134 | void rtl_watchdog_wq_callback(void *data); |
135 | void rtl_fwevt_wq_callback(void *data); | ||
130 | 136 | ||
131 | void rtl_get_tcb_desc(struct ieee80211_hw *hw, | 137 | void rtl_get_tcb_desc(struct ieee80211_hw *hw, |
132 | struct ieee80211_tx_info *info, | 138 | struct ieee80211_tx_info *info, |
@@ -134,14 +140,18 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, | |||
134 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); | 140 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); |
135 | 141 | ||
136 | int rtl_send_smps_action(struct ieee80211_hw *hw, | 142 | int rtl_send_smps_action(struct ieee80211_hw *hw, |
137 | struct ieee80211_sta *sta, u8 *da, u8 *bssid, | 143 | struct ieee80211_sta *sta, |
138 | enum ieee80211_smps_mode smps); | 144 | enum ieee80211_smps_mode smps); |
139 | u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); | 145 | u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); |
140 | void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); | 146 | void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); |
141 | u8 rtl_tid_to_ac(u8 tid); | 147 | u8 rtl_tid_to_ac(u8 tid); |
142 | extern struct attribute_group rtl_attribute_group; | 148 | extern struct attribute_group rtl_attribute_group; |
149 | void rtl_easy_concurrent_retrytimer_callback(unsigned long data); | ||
150 | extern struct rtl_global_var global_var; | ||
143 | int rtlwifi_rate_mapping(struct ieee80211_hw *hw, | 151 | int rtlwifi_rate_mapping(struct ieee80211_hw *hw, |
144 | bool isht, u8 desc_rate, bool first_ampdu); | 152 | bool isht, u8 desc_rate, bool first_ampdu); |
145 | bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); | 153 | bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); |
154 | struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, | ||
155 | u8 *sa, u8 *bssid, u16 tid); | ||
146 | 156 | ||
147 | #endif | 157 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 64a41ecf86cf..ee84844be008 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -104,9 +104,12 @@ static void rtl_op_stop(struct ieee80211_hw *hw) | |||
104 | if (is_hal_stop(rtlhal)) | 104 | if (is_hal_stop(rtlhal)) |
105 | return; | 105 | return; |
106 | 106 | ||
107 | /* here is must, because adhoc do stop and start, | ||
108 | * but stop with RFOFF may cause something wrong, | ||
109 | * like adhoc TP | ||
110 | */ | ||
107 | if (unlikely(ppsc->rfpwr_state == ERFOFF)) { | 111 | if (unlikely(ppsc->rfpwr_state == ERFOFF)) { |
108 | rtl_ips_nic_on(hw); | 112 | rtl_ips_nic_on(hw); |
109 | mdelay(1); | ||
110 | } | 113 | } |
111 | 114 | ||
112 | mutex_lock(&rtlpriv->locks.conf_mutex); | 115 | mutex_lock(&rtlpriv->locks.conf_mutex); |
@@ -167,7 +170,11 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
167 | rtl_ips_nic_on(hw); | 170 | rtl_ips_nic_on(hw); |
168 | 171 | ||
169 | mutex_lock(&rtlpriv->locks.conf_mutex); | 172 | mutex_lock(&rtlpriv->locks.conf_mutex); |
170 | switch (vif->type) { | 173 | |
174 | switch (ieee80211_vif_type_p2p(vif)) { | ||
175 | case NL80211_IFTYPE_P2P_CLIENT: | ||
176 | mac->p2p = P2P_ROLE_CLIENT; | ||
177 | /*fall through*/ | ||
171 | case NL80211_IFTYPE_STATION: | 178 | case NL80211_IFTYPE_STATION: |
172 | if (mac->beacon_enabled == 1) { | 179 | if (mac->beacon_enabled == 1) { |
173 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | 180 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, |
@@ -192,6 +199,9 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
192 | (u8 *) (&mac->basic_rates)); | 199 | (u8 *) (&mac->basic_rates)); |
193 | 200 | ||
194 | break; | 201 | break; |
202 | case NL80211_IFTYPE_P2P_GO: | ||
203 | mac->p2p = P2P_ROLE_GO; | ||
204 | /*fall through*/ | ||
195 | case NL80211_IFTYPE_AP: | 205 | case NL80211_IFTYPE_AP: |
196 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | 206 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, |
197 | "NL80211_IFTYPE_AP\n"); | 207 | "NL80211_IFTYPE_AP\n"); |
@@ -205,6 +215,19 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
205 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, | 215 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, |
206 | (u8 *) (&mac->basic_rates)); | 216 | (u8 *) (&mac->basic_rates)); |
207 | break; | 217 | break; |
218 | case NL80211_IFTYPE_MESH_POINT: | ||
219 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | ||
220 | "NL80211_IFTYPE_MESH_POINT\n"); | ||
221 | |||
222 | mac->link_state = MAC80211_LINKED; | ||
223 | rtlpriv->cfg->ops->set_bcn_reg(hw); | ||
224 | if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) | ||
225 | mac->basic_rates = 0xfff; | ||
226 | else | ||
227 | mac->basic_rates = 0xff0; | ||
228 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, | ||
229 | (u8 *)(&mac->basic_rates)); | ||
230 | break; | ||
208 | default: | 231 | default: |
209 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 232 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
210 | "operation mode %d is not supported!\n", vif->type); | 233 | "operation mode %d is not supported!\n", vif->type); |
@@ -212,6 +235,13 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
212 | goto out; | 235 | goto out; |
213 | } | 236 | } |
214 | 237 | ||
238 | if (mac->p2p) { | ||
239 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | ||
240 | "p2p role %x\n", vif->type); | ||
241 | mac->basic_rates = 0xff0;/*disable cck rate for p2p*/ | ||
242 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, | ||
243 | (u8 *)(&mac->basic_rates)); | ||
244 | } | ||
215 | mac->vif = vif; | 245 | mac->vif = vif; |
216 | mac->opmode = vif->type; | 246 | mac->opmode = vif->type; |
217 | rtlpriv->cfg->ops->set_network_type(hw, vif->type); | 247 | rtlpriv->cfg->ops->set_network_type(hw, vif->type); |
@@ -232,9 +262,9 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
232 | mutex_lock(&rtlpriv->locks.conf_mutex); | 262 | mutex_lock(&rtlpriv->locks.conf_mutex); |
233 | 263 | ||
234 | /* Free beacon resources */ | 264 | /* Free beacon resources */ |
235 | if ((mac->opmode == NL80211_IFTYPE_AP) || | 265 | if ((vif->type == NL80211_IFTYPE_AP) || |
236 | (mac->opmode == NL80211_IFTYPE_ADHOC) || | 266 | (vif->type == NL80211_IFTYPE_ADHOC) || |
237 | (mac->opmode == NL80211_IFTYPE_MESH_POINT)) { | 267 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { |
238 | if (mac->beacon_enabled == 1) { | 268 | if (mac->beacon_enabled == 1) { |
239 | mac->beacon_enabled = 0; | 269 | mac->beacon_enabled = 0; |
240 | rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, | 270 | rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, |
@@ -247,6 +277,7 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
247 | *Note: We assume NL80211_IFTYPE_UNSPECIFIED as | 277 | *Note: We assume NL80211_IFTYPE_UNSPECIFIED as |
248 | *NO LINK for our hardware. | 278 | *NO LINK for our hardware. |
249 | */ | 279 | */ |
280 | mac->p2p = 0; | ||
250 | mac->vif = NULL; | 281 | mac->vif = NULL; |
251 | mac->link_state = MAC80211_NOLINK; | 282 | mac->link_state = MAC80211_NOLINK; |
252 | memset(mac->bssid, 0, 6); | 283 | memset(mac->bssid, 0, 6); |
@@ -256,6 +287,22 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
256 | mutex_unlock(&rtlpriv->locks.conf_mutex); | 287 | mutex_unlock(&rtlpriv->locks.conf_mutex); |
257 | } | 288 | } |
258 | 289 | ||
290 | static int rtl_op_change_interface(struct ieee80211_hw *hw, | ||
291 | struct ieee80211_vif *vif, | ||
292 | enum nl80211_iftype new_type, bool p2p) | ||
293 | { | ||
294 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
295 | int ret; | ||
296 | rtl_op_remove_interface(hw, vif); | ||
297 | |||
298 | vif->type = new_type; | ||
299 | vif->p2p = p2p; | ||
300 | ret = rtl_op_add_interface(hw, vif); | ||
301 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | ||
302 | "p2p %x\n", p2p); | ||
303 | return ret; | ||
304 | } | ||
305 | |||
259 | static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | 306 | static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) |
260 | { | 307 | { |
261 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 308 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -264,6 +311,9 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
264 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 311 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
265 | struct ieee80211_conf *conf = &hw->conf; | 312 | struct ieee80211_conf *conf = &hw->conf; |
266 | 313 | ||
314 | if (mac->skip_scan) | ||
315 | return 1; | ||
316 | |||
267 | mutex_lock(&rtlpriv->locks.conf_mutex); | 317 | mutex_lock(&rtlpriv->locks.conf_mutex); |
268 | if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/ | 318 | if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/ |
269 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | 319 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, |
@@ -323,6 +373,16 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
323 | struct ieee80211_channel *channel = hw->conf.chandef.chan; | 373 | struct ieee80211_channel *channel = hw->conf.chandef.chan; |
324 | u8 wide_chan = (u8) channel->hw_value; | 374 | u8 wide_chan = (u8) channel->hw_value; |
325 | 375 | ||
376 | if (mac->act_scanning) | ||
377 | mac->n_channels++; | ||
378 | |||
379 | if (rtlpriv->dm.supp_phymode_switch && | ||
380 | mac->link_state < MAC80211_LINKED && | ||
381 | !mac->act_scanning) { | ||
382 | if (rtlpriv->cfg->ops->chk_switch_dmdp) | ||
383 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); | ||
384 | } | ||
385 | |||
326 | /* | 386 | /* |
327 | *because we should back channel to | 387 | *because we should back channel to |
328 | *current_network.chan in in scanning, | 388 | *current_network.chan in in scanning, |
@@ -373,13 +433,13 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
373 | if (wide_chan <= 0) | 433 | if (wide_chan <= 0) |
374 | wide_chan = 1; | 434 | wide_chan = 1; |
375 | 435 | ||
376 | /* In scanning, before we go offchannel we may send a ps=1 null | 436 | /* In scanning, before we go offchannel we may send a ps = 1 |
377 | * to AP, and then we may send a ps = 0 null to AP quickly, but | 437 | * null to AP, and then we may send a ps = 0 null to AP quickly, |
378 | * first null may have caused AP to put lots of packet to hw tx | 438 | * but first null may have caused AP to put lots of packet to |
379 | * buffer. These packets must be tx'd before we go off channel | 439 | * hw tx buffer. These packets must be tx'd before we go off |
380 | * so we must delay more time to let AP flush these packets | 440 | * channel so we must delay more time to let AP flush these |
381 | * before going offchannel, or dis-association or delete BA will | 441 | * packets before going offchannel, or dis-association or |
382 | * happen by AP | 442 | * delete BA will be caused by AP |
383 | */ | 443 | */ |
384 | if (rtlpriv->mac80211.offchan_delay) { | 444 | if (rtlpriv->mac80211.offchan_delay) { |
385 | rtlpriv->mac80211.offchan_delay = false; | 445 | rtlpriv->mac80211.offchan_delay = false; |
@@ -441,7 +501,8 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, | |||
441 | * and nolink check bssid is set in set network_type */ | 501 | * and nolink check bssid is set in set network_type */ |
442 | if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && | 502 | if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && |
443 | (mac->link_state >= MAC80211_LINKED)) { | 503 | (mac->link_state >= MAC80211_LINKED)) { |
444 | if (mac->opmode != NL80211_IFTYPE_AP) { | 504 | if (mac->opmode != NL80211_IFTYPE_AP && |
505 | mac->opmode != NL80211_IFTYPE_MESH_POINT) { | ||
445 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { | 506 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { |
446 | rtlpriv->cfg->ops->set_chk_bssid(hw, false); | 507 | rtlpriv->cfg->ops->set_chk_bssid(hw, false); |
447 | } else { | 508 | } else { |
@@ -481,32 +542,43 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw, | |||
481 | { | 542 | { |
482 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 543 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
483 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 544 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
545 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
484 | struct rtl_sta_info *sta_entry; | 546 | struct rtl_sta_info *sta_entry; |
485 | 547 | ||
486 | if (sta) { | 548 | if (sta) { |
487 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; | 549 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
550 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
551 | list_add_tail(&sta_entry->list, &rtlpriv->entry_list); | ||
552 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
488 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { | 553 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { |
489 | sta_entry->wireless_mode = WIRELESS_MODE_G; | 554 | sta_entry->wireless_mode = WIRELESS_MODE_G; |
490 | if (sta->supp_rates[0] <= 0xf) | 555 | if (sta->supp_rates[0] <= 0xf) |
491 | sta_entry->wireless_mode = WIRELESS_MODE_B; | 556 | sta_entry->wireless_mode = WIRELESS_MODE_B; |
492 | if (sta->ht_cap.ht_supported) | 557 | if (sta->ht_cap.ht_supported == true) |
493 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; | 558 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; |
559 | |||
560 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
561 | sta_entry->wireless_mode = WIRELESS_MODE_G; | ||
494 | } else if (rtlhal->current_bandtype == BAND_ON_5G) { | 562 | } else if (rtlhal->current_bandtype == BAND_ON_5G) { |
495 | sta_entry->wireless_mode = WIRELESS_MODE_A; | 563 | sta_entry->wireless_mode = WIRELESS_MODE_A; |
496 | if (sta->ht_cap.ht_supported) | 564 | if (sta->ht_cap.ht_supported == true) |
497 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; | 565 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; |
498 | } | ||
499 | 566 | ||
500 | /* I found some times mac80211 give wrong supp_rates for adhoc*/ | 567 | if (vif->type == NL80211_IFTYPE_ADHOC) |
501 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) | 568 | sta_entry->wireless_mode = WIRELESS_MODE_A; |
502 | sta_entry->wireless_mode = WIRELESS_MODE_G; | 569 | } |
570 | /*disable cck rate for p2p*/ | ||
571 | if (mac->p2p) | ||
572 | sta->supp_rates[0] &= 0xfffffff0; | ||
503 | 573 | ||
574 | memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN); | ||
504 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, | 575 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, |
505 | "Add sta addr is %pM\n", sta->addr); | 576 | "Add sta addr is %pM\n", sta->addr); |
506 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); | 577 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); |
507 | } | 578 | } |
508 | return 0; | 579 | return 0; |
509 | } | 580 | } |
581 | |||
510 | static int rtl_op_sta_remove(struct ieee80211_hw *hw, | 582 | static int rtl_op_sta_remove(struct ieee80211_hw *hw, |
511 | struct ieee80211_vif *vif, | 583 | struct ieee80211_vif *vif, |
512 | struct ieee80211_sta *sta) | 584 | struct ieee80211_sta *sta) |
@@ -519,9 +591,14 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw, | |||
519 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; | 591 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
520 | sta_entry->wireless_mode = 0; | 592 | sta_entry->wireless_mode = 0; |
521 | sta_entry->ratr_index = 0; | 593 | sta_entry->ratr_index = 0; |
594 | |||
595 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
596 | list_del(&sta_entry->list); | ||
597 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
522 | } | 598 | } |
523 | return 0; | 599 | return 0; |
524 | } | 600 | } |
601 | |||
525 | static int _rtl_get_hal_qnum(u16 queue) | 602 | static int _rtl_get_hal_qnum(u16 queue) |
526 | { | 603 | { |
527 | int qnum; | 604 | int qnum; |
@@ -547,8 +624,8 @@ static int _rtl_get_hal_qnum(u16 queue) | |||
547 | } | 624 | } |
548 | 625 | ||
549 | /* | 626 | /* |
550 | *for mac80211 VO=0, VI=1, BE=2, BK=3 | 627 | *for mac80211 VO = 0, VI = 1, BE = 2, BK = 3 |
551 | *for rtl819x BE=0, BK=1, VI=2, VO=3 | 628 | *for rtl819x BE = 0, BK = 1, VI = 2, VO = 3 |
552 | */ | 629 | */ |
553 | static int rtl_op_conf_tx(struct ieee80211_hw *hw, | 630 | static int rtl_op_conf_tx(struct ieee80211_hw *hw, |
554 | struct ieee80211_vif *vif, u16 queue, | 631 | struct ieee80211_vif *vif, u16 queue, |
@@ -630,6 +707,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
630 | /*TODO: reference to enum ieee80211_bss_change */ | 707 | /*TODO: reference to enum ieee80211_bss_change */ |
631 | if (changed & BSS_CHANGED_ASSOC) { | 708 | if (changed & BSS_CHANGED_ASSOC) { |
632 | if (bss_conf->assoc) { | 709 | if (bss_conf->assoc) { |
710 | struct ieee80211_sta *sta = NULL; | ||
633 | /* we should reset all sec info & cam | 711 | /* we should reset all sec info & cam |
634 | * before set cam after linked, we should not | 712 | * before set cam after linked, we should not |
635 | * reset in disassoc, that will cause tkip->wep | 713 | * reset in disassoc, that will cause tkip->wep |
@@ -647,23 +725,39 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
647 | 725 | ||
648 | if (rtlpriv->cfg->ops->linked_set_reg) | 726 | if (rtlpriv->cfg->ops->linked_set_reg) |
649 | rtlpriv->cfg->ops->linked_set_reg(hw); | 727 | rtlpriv->cfg->ops->linked_set_reg(hw); |
650 | if (mac->opmode == NL80211_IFTYPE_STATION && sta) | 728 | rcu_read_lock(); |
729 | sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); | ||
730 | |||
731 | if (vif->type == NL80211_IFTYPE_STATION && sta) | ||
651 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); | 732 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); |
733 | RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD, | ||
734 | "send PS STATIC frame\n"); | ||
735 | if (rtlpriv->dm.supp_phymode_switch) { | ||
736 | if (sta->ht_cap.ht_supported) | ||
737 | rtl_send_smps_action(hw, sta, | ||
738 | IEEE80211_SMPS_STATIC); | ||
739 | } | ||
740 | rcu_read_unlock(); | ||
741 | |||
652 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, | 742 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, |
653 | "BSS_CHANGED_ASSOC\n"); | 743 | "BSS_CHANGED_ASSOC\n"); |
654 | } else { | 744 | } else { |
655 | if (mac->link_state == MAC80211_LINKED) | 745 | if (mac->link_state == MAC80211_LINKED) { |
656 | rtl_lps_leave(hw); | 746 | rtlpriv->enter_ps = false; |
747 | schedule_work(&rtlpriv->works.lps_change_work); | ||
748 | } | ||
657 | 749 | ||
750 | if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) | ||
751 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
658 | mac->link_state = MAC80211_NOLINK; | 752 | mac->link_state = MAC80211_NOLINK; |
659 | memset(mac->bssid, 0, 6); | 753 | memset(mac->bssid, 0, 6); |
660 | |||
661 | /* reset sec info */ | ||
662 | rtl_cam_reset_sec_info(hw); | ||
663 | |||
664 | rtl_cam_reset_all_entry(hw); | ||
665 | mac->vendor = PEER_UNKNOWN; | 754 | mac->vendor = PEER_UNKNOWN; |
666 | 755 | ||
756 | if (rtlpriv->dm.supp_phymode_switch) { | ||
757 | if (rtlpriv->cfg->ops->chk_switch_dmdp) | ||
758 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); | ||
759 | } | ||
760 | |||
667 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, | 761 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, |
668 | "BSS_CHANGED_UN_ASSOC\n"); | 762 | "BSS_CHANGED_UN_ASSOC\n"); |
669 | } | 763 | } |
@@ -778,7 +872,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
778 | } | 872 | } |
779 | 873 | ||
780 | if (changed & BSS_CHANGED_BASIC_RATES) { | 874 | if (changed & BSS_CHANGED_BASIC_RATES) { |
781 | /* for 5G must << RATE_6M_INDEX=4, | 875 | /* for 5G must << RATE_6M_INDEX = 4, |
782 | * because 5G have no cck rate*/ | 876 | * because 5G have no cck rate*/ |
783 | if (rtlhal->current_bandtype == BAND_ON_5G) | 877 | if (rtlhal->current_bandtype == BAND_ON_5G) |
784 | basic_rates = sta->supp_rates[1] << 4; | 878 | basic_rates = sta->supp_rates[1] << 4; |
@@ -815,6 +909,9 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
815 | ppsc->report_linked = false; | 909 | ppsc->report_linked = false; |
816 | } | 910 | } |
817 | } | 911 | } |
912 | if (rtlpriv->cfg->ops->bt_wifi_media_status_notify) | ||
913 | rtlpriv->cfg->ops->bt_wifi_media_status_notify(hw, | ||
914 | ppsc->report_linked); | ||
818 | } | 915 | } |
819 | 916 | ||
820 | out: | 917 | out: |
@@ -885,7 +982,6 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, | |||
885 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 982 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
886 | "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); | 983 | "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); |
887 | return rtl_tx_agg_stop(hw, sta, tid); | 984 | return rtl_tx_agg_stop(hw, sta, tid); |
888 | break; | ||
889 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 985 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
890 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 986 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
891 | "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid); | 987 | "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid); |
@@ -894,11 +990,11 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, | |||
894 | case IEEE80211_AMPDU_RX_START: | 990 | case IEEE80211_AMPDU_RX_START: |
895 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 991 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
896 | "IEEE80211_AMPDU_RX_START:TID:%d\n", tid); | 992 | "IEEE80211_AMPDU_RX_START:TID:%d\n", tid); |
897 | break; | 993 | return rtl_rx_agg_start(hw, sta, tid); |
898 | case IEEE80211_AMPDU_RX_STOP: | 994 | case IEEE80211_AMPDU_RX_STOP: |
899 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 995 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
900 | "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid); | 996 | "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid); |
901 | break; | 997 | return rtl_rx_agg_stop(hw, sta, tid); |
902 | default: | 998 | default: |
903 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 999 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
904 | "IEEE80211_AMPDU_ERR!!!!:\n"); | 1000 | "IEEE80211_AMPDU_ERR!!!!:\n"); |
@@ -912,12 +1008,20 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) | |||
912 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1008 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
913 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1009 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
914 | 1010 | ||
915 | mac->act_scanning = true; | ||
916 | |||
917 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); | 1011 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); |
1012 | mac->act_scanning = true; | ||
1013 | if (rtlpriv->link_info.higher_busytraffic) { | ||
1014 | mac->skip_scan = true; | ||
1015 | return; | ||
1016 | } | ||
918 | 1017 | ||
1018 | if (rtlpriv->dm.supp_phymode_switch) { | ||
1019 | if (rtlpriv->cfg->ops->chk_switch_dmdp) | ||
1020 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); | ||
1021 | } | ||
919 | if (mac->link_state == MAC80211_LINKED) { | 1022 | if (mac->link_state == MAC80211_LINKED) { |
920 | rtl_lps_leave(hw); | 1023 | rtlpriv->enter_ps = false; |
1024 | schedule_work(&rtlpriv->works.lps_change_work); | ||
921 | mac->link_state = MAC80211_LINKED_SCANNING; | 1025 | mac->link_state = MAC80211_LINKED_SCANNING; |
922 | } else { | 1026 | } else { |
923 | rtl_ips_nic_on(hw); | 1027 | rtl_ips_nic_on(hw); |
@@ -937,6 +1041,16 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) | |||
937 | 1041 | ||
938 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); | 1042 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); |
939 | mac->act_scanning = false; | 1043 | mac->act_scanning = false; |
1044 | mac->skip_scan = false; | ||
1045 | if (rtlpriv->link_info.higher_busytraffic) | ||
1046 | return; | ||
1047 | |||
1048 | /*p2p will use 1/6/11 to scan */ | ||
1049 | if (mac->n_channels == 3) | ||
1050 | mac->p2p_in_use = true; | ||
1051 | else | ||
1052 | mac->p2p_in_use = false; | ||
1053 | mac->n_channels = 0; | ||
940 | /* Dual mac */ | 1054 | /* Dual mac */ |
941 | rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; | 1055 | rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; |
942 | 1056 | ||
@@ -970,6 +1084,11 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
970 | "not open hw encryption\n"); | 1084 | "not open hw encryption\n"); |
971 | return -ENOSPC; /*User disabled HW-crypto */ | 1085 | return -ENOSPC; /*User disabled HW-crypto */ |
972 | } | 1086 | } |
1087 | /* To support IBSS, use sw-crypto for GTK */ | ||
1088 | if (((vif->type == NL80211_IFTYPE_ADHOC) || | ||
1089 | (vif->type == NL80211_IFTYPE_MESH_POINT)) && | ||
1090 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
1091 | return -ENOSPC; | ||
973 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 1092 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
974 | "%s hardware based encryption for keyidx: %d, mac: %pM\n", | 1093 | "%s hardware based encryption for keyidx: %d, mac: %pM\n", |
975 | cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, | 1094 | cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, |
@@ -996,6 +1115,14 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
996 | key_type = AESCCMP_ENCRYPTION; | 1115 | key_type = AESCCMP_ENCRYPTION; |
997 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n"); | 1116 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n"); |
998 | break; | 1117 | break; |
1118 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
1119 | /*HW doesn't support CMAC encryption, use software CMAC */ | ||
1120 | key_type = AESCMAC_ENCRYPTION; | ||
1121 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n"); | ||
1122 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
1123 | "HW don't support CMAC encryption, use software CMAC\n"); | ||
1124 | err = -EOPNOTSUPP; | ||
1125 | goto out_unlock; | ||
999 | default: | 1126 | default: |
1000 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n", | 1127 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n", |
1001 | key->cipher); | 1128 | key->cipher); |
@@ -1017,13 +1144,14 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1017 | * 1) wep only: is just for wep enc, in this condition | 1144 | * 1) wep only: is just for wep enc, in this condition |
1018 | * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION | 1145 | * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION |
1019 | * will be true & enable_hw_sec will be set when wep | 1146 | * will be true & enable_hw_sec will be set when wep |
1020 | * ke setting. | 1147 | * key setting. |
1021 | * 2) wep(group) + AES(pairwise): some AP like cisco | 1148 | * 2) wep(group) + AES(pairwise): some AP like cisco |
1022 | * may use it, in this condition enable_hw_sec will not | 1149 | * may use it, in this condition enable_hw_sec will not |
1023 | * be set when wep key setting */ | 1150 | * be set when wep key setting */ |
1024 | /* we must reset sec_info after lingked before set key, | 1151 | /* we must reset sec_info after lingked before set key, |
1025 | * or some flag will be wrong*/ | 1152 | * or some flag will be wrong*/ |
1026 | if (mac->opmode == NL80211_IFTYPE_AP) { | 1153 | if (vif->type == NL80211_IFTYPE_AP || |
1154 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
1027 | if (!group_key || key_type == WEP40_ENCRYPTION || | 1155 | if (!group_key || key_type == WEP40_ENCRYPTION || |
1028 | key_type == WEP104_ENCRYPTION) { | 1156 | key_type == WEP104_ENCRYPTION) { |
1029 | if (group_key) | 1157 | if (group_key) |
@@ -1098,12 +1226,16 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1098 | key->hw_key_idx = key_idx; | 1226 | key->hw_key_idx = key_idx; |
1099 | if (key_type == TKIP_ENCRYPTION) | 1227 | if (key_type == TKIP_ENCRYPTION) |
1100 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1228 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1229 | /*use software CCMP encryption for management frames (MFP) */ | ||
1230 | if (key_type == AESCCMP_ENCRYPTION) | ||
1231 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; | ||
1101 | break; | 1232 | break; |
1102 | case DISABLE_KEY: | 1233 | case DISABLE_KEY: |
1103 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 1234 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
1104 | "disable key delete one entry\n"); | 1235 | "disable key delete one entry\n"); |
1105 | /*set local buf about wep key. */ | 1236 | /*set local buf about wep key. */ |
1106 | if (mac->opmode == NL80211_IFTYPE_AP) { | 1237 | if (vif->type == NL80211_IFTYPE_AP || |
1238 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
1107 | if (sta) | 1239 | if (sta) |
1108 | rtl_cam_del_entry(hw, sta->addr); | 1240 | rtl_cam_del_entry(hw, sta->addr); |
1109 | } | 1241 | } |
@@ -1163,7 +1295,7 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw) | |||
1163 | } | 1295 | } |
1164 | 1296 | ||
1165 | /* this function is called by mac80211 to flush tx buffer | 1297 | /* this function is called by mac80211 to flush tx buffer |
1166 | * before switch channle or power save, or tx buffer packet | 1298 | * before switch channel or power save, or tx buffer packet |
1167 | * maybe send after offchannel or rf sleep, this may cause | 1299 | * maybe send after offchannel or rf sleep, this may cause |
1168 | * dis-association by AP */ | 1300 | * dis-association by AP */ |
1169 | static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | 1301 | static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
@@ -1180,6 +1312,7 @@ const struct ieee80211_ops rtl_ops = { | |||
1180 | .tx = rtl_op_tx, | 1312 | .tx = rtl_op_tx, |
1181 | .add_interface = rtl_op_add_interface, | 1313 | .add_interface = rtl_op_add_interface, |
1182 | .remove_interface = rtl_op_remove_interface, | 1314 | .remove_interface = rtl_op_remove_interface, |
1315 | .change_interface = rtl_op_change_interface, | ||
1183 | .config = rtl_op_config, | 1316 | .config = rtl_op_config, |
1184 | .configure_filter = rtl_op_configure_filter, | 1317 | .configure_filter = rtl_op_configure_filter, |
1185 | .sta_add = rtl_op_sta_add, | 1318 | .sta_add = rtl_op_sta_add, |
diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c index bdda9b2fffe1..7d52d3d7769f 100644 --- a/drivers/net/wireless/rtlwifi/debug.c +++ b/drivers/net/wireless/rtlwifi/debug.c | |||
@@ -41,7 +41,10 @@ void rtl_dbgp_flag_init(struct ieee80211_hw *hw) | |||
41 | COMP_BEACON | COMP_RATE | COMP_RXDESC | COMP_DIG | COMP_TXAGC | | 41 | COMP_BEACON | COMP_RATE | COMP_RXDESC | COMP_DIG | COMP_TXAGC | |
42 | COMP_POWER | COMP_POWER_TRACKING | COMP_BB_POWERSAVING | COMP_SWAS | | 42 | COMP_POWER | COMP_POWER_TRACKING | COMP_BB_POWERSAVING | COMP_SWAS | |
43 | COMP_RF | COMP_TURBO | COMP_RATR | COMP_CMD | | 43 | COMP_RF | COMP_TURBO | COMP_RATR | COMP_CMD | |
44 | COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN; | 44 | COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN | |
45 | COMP_EASY_CONCURRENT | COMP_EFUSE | COMP_QOS | COMP_MAC80211 | | ||
46 | COMP_REGD | COMP_CHAN | COMP_BT_COEXIST; | ||
47 | |||
45 | 48 | ||
46 | for (i = 0; i < DBGP_TYPE_MAX; i++) | 49 | for (i = 0; i < DBGP_TYPE_MAX; i++) |
47 | rtlpriv->dbg.dbgp_type[i] = 0; | 50 | rtlpriv->dbg.dbgp_type[i] = 0; |
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h index fd3269f47685..6d669364e3d9 100644 --- a/drivers/net/wireless/rtlwifi/debug.h +++ b/drivers/net/wireless/rtlwifi/debug.h | |||
@@ -115,11 +115,11 @@ | |||
115 | /* Define EEPROM and EFUSE check module bit*/ | 115 | /* Define EEPROM and EFUSE check module bit*/ |
116 | #define EEPROM_W BIT(0) | 116 | #define EEPROM_W BIT(0) |
117 | #define EFUSE_PG BIT(1) | 117 | #define EFUSE_PG BIT(1) |
118 | #define EFUSE_READ_ALL BIT(2) | 118 | #define EFUSE_READ_ALL BIT(2) |
119 | 119 | ||
120 | /* Define init check for module bit*/ | 120 | /* Define init check for module bit*/ |
121 | #define INIT_EEPROM BIT(0) | 121 | #define INIT_EEPROM BIT(0) |
122 | #define INIT_TxPower BIT(1) | 122 | #define INIT_TXPOWER BIT(1) |
123 | #define INIT_IQK BIT(2) | 123 | #define INIT_IQK BIT(2) |
124 | #define INIT_RF BIT(3) | 124 | #define INIT_RF BIT(3) |
125 | 125 | ||
@@ -135,6 +135,15 @@ | |||
135 | #define PHY_TXPWR BIT(8) | 135 | #define PHY_TXPWR BIT(8) |
136 | #define PHY_PWRDIFF BIT(9) | 136 | #define PHY_PWRDIFF BIT(9) |
137 | 137 | ||
138 | /* Define Dynamic Mechanism check module bit --> FDM */ | ||
139 | #define WA_IOT BIT(0) | ||
140 | #define DM_PWDB BIT(1) | ||
141 | #define DM_MONITOR BIT(2) | ||
142 | #define DM_DIG BIT(3) | ||
143 | #define DM_EDCA_TURBO BIT(4) | ||
144 | |||
145 | #define DM_PWDB BIT(1) | ||
146 | |||
138 | enum dbgp_flag_e { | 147 | enum dbgp_flag_e { |
139 | FQOS = 0, | 148 | FQOS = 0, |
140 | FTX = 1, | 149 | FTX = 1, |
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 8e2f9afb125a..9e3894178e77 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c | |||
@@ -35,8 +35,6 @@ static const u8 MAX_PGPKT_SIZE = 9; | |||
35 | static const u8 PGPKT_DATA_SIZE = 8; | 35 | static const u8 PGPKT_DATA_SIZE = 8; |
36 | static const int EFUSE_MAX_SIZE = 512; | 36 | static const int EFUSE_MAX_SIZE = 512; |
37 | 37 | ||
38 | static const u8 EFUSE_OOB_PROTECT_BYTES = 15; | ||
39 | |||
40 | static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { | 38 | static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { |
41 | {0, 0, 0, 2}, | 39 | {0, 0, 0, 2}, |
42 | {0, 1, 0, 2}, | 40 | {0, 1, 0, 2}, |
@@ -240,6 +238,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
240 | u8 rtemp8[1]; | 238 | u8 rtemp8[1]; |
241 | u16 efuse_addr = 0; | 239 | u16 efuse_addr = 0; |
242 | u8 offset, wren; | 240 | u8 offset, wren; |
241 | u8 u1temp = 0; | ||
243 | u16 i; | 242 | u16 i; |
244 | u16 j; | 243 | u16 j; |
245 | const u16 efuse_max_section = | 244 | const u16 efuse_max_section = |
@@ -285,10 +284,31 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
285 | } | 284 | } |
286 | 285 | ||
287 | while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { | 286 | while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { |
288 | offset = ((*rtemp8 >> 4) & 0x0f); | 287 | /* Check PG header for section num. */ |
288 | if ((*rtemp8 & 0x1F) == 0x0F) {/* extended header */ | ||
289 | u1temp = ((*rtemp8 & 0xE0) >> 5); | ||
290 | read_efuse_byte(hw, efuse_addr, rtemp8); | ||
289 | 291 | ||
290 | if (offset < efuse_max_section) { | 292 | if ((*rtemp8 & 0x0F) == 0x0F) { |
293 | efuse_addr++; | ||
294 | read_efuse_byte(hw, efuse_addr, rtemp8); | ||
295 | |||
296 | if (*rtemp8 != 0xFF && | ||
297 | (efuse_addr < efuse_len)) { | ||
298 | efuse_addr++; | ||
299 | } | ||
300 | continue; | ||
301 | } else { | ||
302 | offset = ((*rtemp8 & 0xF0) >> 1) | u1temp; | ||
303 | wren = (*rtemp8 & 0x0F); | ||
304 | efuse_addr++; | ||
305 | } | ||
306 | } else { | ||
307 | offset = ((*rtemp8 >> 4) & 0x0f); | ||
291 | wren = (*rtemp8 & 0x0f); | 308 | wren = (*rtemp8 & 0x0f); |
309 | } | ||
310 | |||
311 | if (offset < efuse_max_section) { | ||
292 | RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, | 312 | RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, |
293 | "offset-%d Worden=%x\n", offset, wren); | 313 | "offset-%d Worden=%x\n", offset, wren); |
294 | 314 | ||
@@ -391,7 +411,8 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) | |||
391 | efuse_used = rtlefuse->efuse_usedbytes; | 411 | efuse_used = rtlefuse->efuse_usedbytes; |
392 | 412 | ||
393 | if ((totalbytes + efuse_used) >= | 413 | if ((totalbytes + efuse_used) >= |
394 | (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) | 414 | (EFUSE_MAX_SIZE - |
415 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) | ||
395 | result = false; | 416 | result = false; |
396 | 417 | ||
397 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, | 418 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, |
@@ -932,8 +953,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
932 | u8 badworden = 0x0F; | 953 | u8 badworden = 0x0F; |
933 | static int repeat_times; | 954 | static int repeat_times; |
934 | 955 | ||
935 | if (efuse_get_current_size(hw) >= | 956 | if (efuse_get_current_size(hw) >= (EFUSE_MAX_SIZE - |
936 | (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) { | 957 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { |
937 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, | 958 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, |
938 | "efuse_pg_packet_write error\n"); | 959 | "efuse_pg_packet_write error\n"); |
939 | return false; | 960 | return false; |
@@ -949,8 +970,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
949 | 970 | ||
950 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n"); | 971 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n"); |
951 | 972 | ||
952 | while (continual && (efuse_addr < | 973 | while (continual && (efuse_addr < (EFUSE_MAX_SIZE - |
953 | (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) { | 974 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) { |
954 | 975 | ||
955 | if (write_state == PG_STATE_HEADER) { | 976 | if (write_state == PG_STATE_HEADER) { |
956 | badworden = 0x0F; | 977 | badworden = 0x0F; |
@@ -1003,7 +1024,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
1003 | } | 1024 | } |
1004 | } | 1025 | } |
1005 | 1026 | ||
1006 | if (efuse_addr >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) { | 1027 | if (efuse_addr >= (EFUSE_MAX_SIZE - |
1028 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { | ||
1007 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, | 1029 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, |
1008 | "efuse_addr(%#x) Out of size!!\n", efuse_addr); | 1030 | "efuse_addr(%#x) Out of size!!\n", efuse_addr); |
1009 | } | 1031 | } |
@@ -1102,8 +1124,11 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) | |||
1102 | u8 tempval; | 1124 | u8 tempval; |
1103 | u16 tmpV16; | 1125 | u16 tmpV16; |
1104 | 1126 | ||
1105 | if (pwrstate && (rtlhal->hw_type != | 1127 | if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) { |
1106 | HARDWARE_TYPE_RTL8192SE)) { | 1128 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE) |
1129 | rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS], | ||
1130 | 0x69); | ||
1131 | |||
1107 | tmpV16 = rtl_read_word(rtlpriv, | 1132 | tmpV16 = rtl_read_word(rtlpriv, |
1108 | rtlpriv->cfg->maps[SYS_ISO_CTRL]); | 1133 | rtlpriv->cfg->maps[SYS_ISO_CTRL]); |
1109 | if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { | 1134 | if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { |
@@ -1153,6 +1178,10 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) | |||
1153 | } | 1178 | } |
1154 | 1179 | ||
1155 | } else { | 1180 | } else { |
1181 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE) | ||
1182 | rtl_write_byte(rtlpriv, | ||
1183 | rtlpriv->cfg->maps[EFUSE_ACCESS], 0); | ||
1184 | |||
1156 | if (write) { | 1185 | if (write) { |
1157 | tempval = rtl_read_byte(rtlpriv, | 1186 | tempval = rtl_read_byte(rtlpriv, |
1158 | rtlpriv->cfg->maps[EFUSE_TEST] + | 1187 | rtlpriv->cfg->maps[EFUSE_TEST] + |
diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h index 2bdea9a8699e..395a326acfb4 100644 --- a/drivers/net/wireless/rtlwifi/efuse.h +++ b/drivers/net/wireless/rtlwifi/efuse.h | |||
@@ -32,7 +32,6 @@ | |||
32 | 32 | ||
33 | #define EFUSE_IC_ID_OFFSET 506 | 33 | #define EFUSE_IC_ID_OFFSET 506 |
34 | 34 | ||
35 | #define EFUSE_REAL_CONTENT_LEN 512 | ||
36 | #define EFUSE_MAP_LEN 128 | 35 | #define EFUSE_MAP_LEN 128 |
37 | #define EFUSE_MAX_WORD_UNIT 4 | 36 | #define EFUSE_MAX_WORD_UNIT 4 |
38 | 37 | ||
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 4261e8ecc4c3..999ffc12578b 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -59,7 +59,7 @@ static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, | |||
59 | 59 | ||
60 | if (unlikely(ieee80211_is_beacon(fc))) | 60 | if (unlikely(ieee80211_is_beacon(fc))) |
61 | return BEACON_QUEUE; | 61 | return BEACON_QUEUE; |
62 | if (ieee80211_is_mgmt(fc)) | 62 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) |
63 | return MGNT_QUEUE; | 63 | return MGNT_QUEUE; |
64 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) | 64 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) |
65 | if (ieee80211_is_nullfunc(fc)) | 65 | if (ieee80211_is_nullfunc(fc)) |
@@ -271,9 +271,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) | |||
271 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 271 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
272 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 272 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
273 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 273 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
274 | u8 pcibridge_busnum = pcipriv->ndis_adapter.pcibridge_busnum; | ||
275 | u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum; | ||
276 | u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum; | ||
277 | u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; | 274 | u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; |
278 | u8 num4bytes = pcipriv->ndis_adapter.num4bytes; | 275 | u8 num4bytes = pcipriv->ndis_adapter.num4bytes; |
279 | u16 aspmlevel; | 276 | u16 aspmlevel; |
@@ -302,8 +299,7 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) | |||
302 | u_pcibridge_aspmsetting); | 299 | u_pcibridge_aspmsetting); |
303 | 300 | ||
304 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | 301 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, |
305 | "PlatformEnableASPM():PciBridge busnumber[%x], DevNumbe[%x], funcnumber[%x], Write reg[%x] = %x\n", | 302 | "PlatformEnableASPM(): Write reg[%x] = %x\n", |
306 | pcibridge_busnum, pcibridge_devnum, pcibridge_funcnum, | ||
307 | (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), | 303 | (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), |
308 | u_pcibridge_aspmsetting); | 304 | u_pcibridge_aspmsetting); |
309 | 305 | ||
@@ -349,6 +345,49 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) | |||
349 | return status; | 345 | return status; |
350 | } | 346 | } |
351 | 347 | ||
348 | static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw, | ||
349 | struct rtl_priv **buddy_priv) | ||
350 | { | ||
351 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
352 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
353 | bool find_buddy_priv = false; | ||
354 | struct rtl_priv *tpriv = NULL; | ||
355 | struct rtl_pci_priv *tpcipriv = NULL; | ||
356 | |||
357 | if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) { | ||
358 | list_for_each_entry(tpriv, &rtlpriv->glb_var->glb_priv_list, | ||
359 | list) { | ||
360 | if (tpriv) { | ||
361 | tpcipriv = (struct rtl_pci_priv *)tpriv->priv; | ||
362 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
363 | "pcipriv->ndis_adapter.funcnumber %x\n", | ||
364 | pcipriv->ndis_adapter.funcnumber); | ||
365 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
366 | "tpcipriv->ndis_adapter.funcnumber %x\n", | ||
367 | tpcipriv->ndis_adapter.funcnumber); | ||
368 | |||
369 | if ((pcipriv->ndis_adapter.busnumber == | ||
370 | tpcipriv->ndis_adapter.busnumber) && | ||
371 | (pcipriv->ndis_adapter.devnumber == | ||
372 | tpcipriv->ndis_adapter.devnumber) && | ||
373 | (pcipriv->ndis_adapter.funcnumber != | ||
374 | tpcipriv->ndis_adapter.funcnumber)) { | ||
375 | find_buddy_priv = true; | ||
376 | break; | ||
377 | } | ||
378 | } | ||
379 | } | ||
380 | } | ||
381 | |||
382 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
383 | "find_buddy_priv %d\n", find_buddy_priv); | ||
384 | |||
385 | if (find_buddy_priv) | ||
386 | *buddy_priv = tpriv; | ||
387 | |||
388 | return find_buddy_priv; | ||
389 | } | ||
390 | |||
352 | static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) | 391 | static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) |
353 | { | 392 | { |
354 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 393 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
@@ -420,17 +459,14 @@ static void _rtl_pci_io_handler_init(struct device *dev, | |||
420 | 459 | ||
421 | } | 460 | } |
422 | 461 | ||
423 | static void _rtl_pci_io_handler_release(struct ieee80211_hw *hw) | ||
424 | { | ||
425 | } | ||
426 | |||
427 | static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, | 462 | static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, |
428 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) | 463 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) |
429 | { | 464 | { |
430 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 465 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
431 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 466 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
432 | u8 additionlen = FCS_LEN; | 467 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
433 | struct sk_buff *next_skb; | 468 | struct sk_buff *next_skb; |
469 | u8 additionlen = FCS_LEN; | ||
434 | 470 | ||
435 | /* here open is 4, wep/tkip is 8, aes is 12*/ | 471 | /* here open is 4, wep/tkip is 8, aes is 12*/ |
436 | if (info->control.hw_key) | 472 | if (info->control.hw_key) |
@@ -455,7 +491,7 @@ static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, | |||
455 | next_skb)) | 491 | next_skb)) |
456 | break; | 492 | break; |
457 | 493 | ||
458 | if (tcb_desc->empkt_num >= 5) | 494 | if (tcb_desc->empkt_num >= rtlhal->max_earlymode_num) |
459 | break; | 495 | break; |
460 | } | 496 | } |
461 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); | 497 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); |
@@ -471,11 +507,17 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) | |||
471 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 507 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
472 | struct sk_buff *skb = NULL; | 508 | struct sk_buff *skb = NULL; |
473 | struct ieee80211_tx_info *info = NULL; | 509 | struct ieee80211_tx_info *info = NULL; |
510 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
474 | int tid; | 511 | int tid; |
475 | 512 | ||
476 | if (!rtlpriv->rtlhal.earlymode_enable) | 513 | if (!rtlpriv->rtlhal.earlymode_enable) |
477 | return; | 514 | return; |
478 | 515 | ||
516 | if (rtlpriv->dm.supp_phymode_switch && | ||
517 | (rtlpriv->easy_concurrent_ctl.switch_in_process || | ||
518 | (rtlpriv->buddy_priv && | ||
519 | rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process))) | ||
520 | return; | ||
479 | /* we juse use em for BE/BK/VI/VO */ | 521 | /* we juse use em for BE/BK/VI/VO */ |
480 | for (tid = 7; tid >= 0; tid--) { | 522 | for (tid = 7; tid >= 0; tid--) { |
481 | u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)]; | 523 | u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)]; |
@@ -487,7 +529,8 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) | |||
487 | 529 | ||
488 | spin_lock_bh(&rtlpriv->locks.waitq_lock); | 530 | spin_lock_bh(&rtlpriv->locks.waitq_lock); |
489 | if (!skb_queue_empty(&mac->skb_waitq[tid]) && | 531 | if (!skb_queue_empty(&mac->skb_waitq[tid]) && |
490 | (ring->entries - skb_queue_len(&ring->queue) > 5)) { | 532 | (ring->entries - skb_queue_len(&ring->queue) > |
533 | rtlhal->max_earlymode_num)) { | ||
491 | skb = skb_dequeue(&mac->skb_waitq[tid]); | 534 | skb = skb_dequeue(&mac->skb_waitq[tid]); |
492 | } else { | 535 | } else { |
493 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); | 536 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); |
@@ -525,9 +568,8 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
525 | u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, | 568 | u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, |
526 | HW_DESC_OWN); | 569 | HW_DESC_OWN); |
527 | 570 | ||
528 | /* | 571 | /*beacon packet will only use the first |
529 | *beacon packet will only use the first | 572 | *descriptor by defaut, and the own may not |
530 | *descriptor defautly,and the own may not | ||
531 | *be cleared by the hardware | 573 | *be cleared by the hardware |
532 | */ | 574 | */ |
533 | if (own) | 575 | if (own) |
@@ -558,8 +600,9 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
558 | } | 600 | } |
559 | 601 | ||
560 | /* for sw LPS, just after NULL skb send out, we can | 602 | /* for sw LPS, just after NULL skb send out, we can |
561 | * sure AP kown we are sleeped, our we should not let | 603 | * sure AP knows we are sleeping, we should not let |
562 | * rf to sleep*/ | 604 | * rf sleep |
605 | */ | ||
563 | fc = rtl_get_fc(skb); | 606 | fc = rtl_get_fc(skb); |
564 | if (ieee80211_is_nullfunc(fc)) { | 607 | if (ieee80211_is_nullfunc(fc)) { |
565 | if (ieee80211_has_pm(fc)) { | 608 | if (ieee80211_has_pm(fc)) { |
@@ -569,6 +612,15 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
569 | rtlpriv->psc.state_inap = false; | 612 | rtlpriv->psc.state_inap = false; |
570 | } | 613 | } |
571 | } | 614 | } |
615 | if (ieee80211_is_action(fc)) { | ||
616 | struct ieee80211_mgmt *action_frame = | ||
617 | (struct ieee80211_mgmt *)skb->data; | ||
618 | if (action_frame->u.action.u.ht_smps.action == | ||
619 | WLAN_HT_ACTION_SMPS) { | ||
620 | dev_kfree_skb(skb); | ||
621 | goto tx_status_ok; | ||
622 | } | ||
623 | } | ||
572 | 624 | ||
573 | /* update tid tx pkt num */ | 625 | /* update tid tx pkt num */ |
574 | tid = rtl_get_tid(skb); | 626 | tid = rtl_get_tid(skb); |
@@ -602,7 +654,8 @@ tx_status_ok: | |||
602 | if (((rtlpriv->link_info.num_rx_inperiod + | 654 | if (((rtlpriv->link_info.num_rx_inperiod + |
603 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 655 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
604 | (rtlpriv->link_info.num_rx_inperiod > 2)) { | 656 | (rtlpriv->link_info.num_rx_inperiod > 2)) { |
605 | schedule_work(&rtlpriv->works.lps_leave_work); | 657 | rtlpriv->enter_ps = false; |
658 | schedule_work(&rtlpriv->works.lps_change_work); | ||
606 | } | 659 | } |
607 | } | 660 | } |
608 | 661 | ||
@@ -637,6 +690,10 @@ static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
637 | rtlpriv->link_info.num_rx_inperiod++; | 690 | rtlpriv->link_info.num_rx_inperiod++; |
638 | } | 691 | } |
639 | 692 | ||
693 | /* static bcn for roaming */ | ||
694 | rtl_beacon_statistic(hw, skb); | ||
695 | rtl_p2p_info(hw, (void *)skb->data, skb->len); | ||
696 | |||
640 | /* for sw lps */ | 697 | /* for sw lps */ |
641 | rtl_swlps_beacon(hw, (void *)skb->data, skb->len); | 698 | rtl_swlps_beacon(hw, (void *)skb->data, skb->len); |
642 | rtl_recognize_peer(hw, (void *)skb->data, skb->len); | 699 | rtl_recognize_peer(hw, (void *)skb->data, skb->len); |
@@ -727,9 +784,10 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
727 | _rtl_receive_one(hw, skb, rx_status); | 784 | _rtl_receive_one(hw, skb, rx_status); |
728 | 785 | ||
729 | if (((rtlpriv->link_info.num_rx_inperiod + | 786 | if (((rtlpriv->link_info.num_rx_inperiod + |
730 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 787 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
731 | (rtlpriv->link_info.num_rx_inperiod > 2)) { | 788 | (rtlpriv->link_info.num_rx_inperiod > 2)) { |
732 | schedule_work(&rtlpriv->works.lps_leave_work); | 789 | rtlpriv->enter_ps = false; |
790 | schedule_work(&rtlpriv->works.lps_change_work); | ||
733 | } | 791 | } |
734 | 792 | ||
735 | dev_kfree_skb_any(skb); | 793 | dev_kfree_skb_any(skb); |
@@ -803,7 +861,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) | |||
803 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "beacon interrupt!\n"); | 861 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "beacon interrupt!\n"); |
804 | } | 862 | } |
805 | 863 | ||
806 | if (inta & rtlpriv->cfg->maps[RTL_IMR_BcnInt]) { | 864 | if (inta & rtlpriv->cfg->maps[RTL_IMR_BCNINT]) { |
807 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, | 865 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, |
808 | "prepare beacon for interrupt!\n"); | 866 | "prepare beacon for interrupt!\n"); |
809 | tasklet_schedule(&rtlpriv->works.irq_prepare_bcn_tasklet); | 867 | tasklet_schedule(&rtlpriv->works.irq_prepare_bcn_tasklet); |
@@ -884,6 +942,16 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) | |||
884 | _rtl_pci_rx_interrupt(hw); | 942 | _rtl_pci_rx_interrupt(hw); |
885 | } | 943 | } |
886 | 944 | ||
945 | /*fw related*/ | ||
946 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723AE) { | ||
947 | if (inta & rtlpriv->cfg->maps[RTL_IMR_C2HCMD]) { | ||
948 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, | ||
949 | "firmware interrupt!\n"); | ||
950 | queue_delayed_work(rtlpriv->works.rtl_wq, | ||
951 | &rtlpriv->works.fwevt_wq, 0); | ||
952 | } | ||
953 | } | ||
954 | |||
887 | if (rtlpriv->rtlhal.earlymode_enable) | 955 | if (rtlpriv->rtlhal.earlymode_enable) |
888 | tasklet_schedule(&rtlpriv->works.irq_tasklet); | 956 | tasklet_schedule(&rtlpriv->works.irq_tasklet); |
889 | 957 | ||
@@ -939,13 +1007,17 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) | |||
939 | return; | 1007 | return; |
940 | } | 1008 | } |
941 | 1009 | ||
942 | static void rtl_lps_leave_work_callback(struct work_struct *work) | 1010 | static void rtl_lps_change_work_callback(struct work_struct *work) |
943 | { | 1011 | { |
944 | struct rtl_works *rtlworks = | 1012 | struct rtl_works *rtlworks = |
945 | container_of(work, struct rtl_works, lps_leave_work); | 1013 | container_of(work, struct rtl_works, lps_change_work); |
946 | struct ieee80211_hw *hw = rtlworks->hw; | 1014 | struct ieee80211_hw *hw = rtlworks->hw; |
1015 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
947 | 1016 | ||
948 | rtl_lps_leave(hw); | 1017 | if (rtlpriv->enter_ps) |
1018 | rtl_lps_enter(hw); | ||
1019 | else | ||
1020 | rtl_lps_leave(hw); | ||
949 | } | 1021 | } |
950 | 1022 | ||
951 | static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) | 1023 | static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) |
@@ -1009,7 +1081,8 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, | |||
1009 | tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, | 1081 | tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, |
1010 | (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, | 1082 | (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, |
1011 | (unsigned long)hw); | 1083 | (unsigned long)hw); |
1012 | INIT_WORK(&rtlpriv->works.lps_leave_work, rtl_lps_leave_work_callback); | 1084 | INIT_WORK(&rtlpriv->works.lps_change_work, |
1085 | rtl_lps_change_work_callback); | ||
1013 | } | 1086 | } |
1014 | 1087 | ||
1015 | static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | 1088 | static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, |
@@ -1458,10 +1531,14 @@ static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop) | |||
1458 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1531 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1459 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 1532 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
1460 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1533 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1534 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1461 | u16 i = 0; | 1535 | u16 i = 0; |
1462 | int queue_id; | 1536 | int queue_id; |
1463 | struct rtl8192_tx_ring *ring; | 1537 | struct rtl8192_tx_ring *ring; |
1464 | 1538 | ||
1539 | if (mac->skip_scan) | ||
1540 | return; | ||
1541 | |||
1465 | for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { | 1542 | for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { |
1466 | u32 queue_len; | 1543 | u32 queue_len; |
1467 | ring = &pcipriv->dev.tx_ring[queue_id]; | 1544 | ring = &pcipriv->dev.tx_ring[queue_id]; |
@@ -1491,7 +1568,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw) | |||
1491 | 1568 | ||
1492 | synchronize_irq(rtlpci->pdev->irq); | 1569 | synchronize_irq(rtlpci->pdev->irq); |
1493 | tasklet_kill(&rtlpriv->works.irq_tasklet); | 1570 | tasklet_kill(&rtlpriv->works.irq_tasklet); |
1494 | cancel_work_sync(&rtlpriv->works.lps_leave_work); | 1571 | cancel_work_sync(&rtlpriv->works.lps_change_work); |
1495 | 1572 | ||
1496 | flush_workqueue(rtlpriv->works.rtl_wq); | 1573 | flush_workqueue(rtlpriv->works.rtl_wq); |
1497 | destroy_workqueue(rtlpriv->works.rtl_wq); | 1574 | destroy_workqueue(rtlpriv->works.rtl_wq); |
@@ -1566,7 +1643,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) | |||
1566 | set_hal_stop(rtlhal); | 1643 | set_hal_stop(rtlhal); |
1567 | 1644 | ||
1568 | rtlpriv->cfg->ops->disable_interrupt(hw); | 1645 | rtlpriv->cfg->ops->disable_interrupt(hw); |
1569 | cancel_work_sync(&rtlpriv->works.lps_leave_work); | 1646 | cancel_work_sync(&rtlpriv->works.lps_change_work); |
1570 | 1647 | ||
1571 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); | 1648 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); |
1572 | while (ppsc->rfchange_inprogress) { | 1649 | while (ppsc->rfchange_inprogress) { |
@@ -1673,6 +1750,10 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, | |||
1673 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | 1750 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
1674 | "8192D PCI-E is found - vid/did=%x/%x\n", | 1751 | "8192D PCI-E is found - vid/did=%x/%x\n", |
1675 | venderid, deviceid); | 1752 | venderid, deviceid); |
1753 | } else if (deviceid == RTL_PCI_8188EE_DID) { | ||
1754 | rtlhal->hw_type = HARDWARE_TYPE_RTL8188EE; | ||
1755 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1756 | "Find adapter, Hardware type is 8188EE\n"); | ||
1676 | } else { | 1757 | } else { |
1677 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | 1758 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, |
1678 | "Err: Unknown device - vid/did=%x/%x\n", | 1759 | "Err: Unknown device - vid/did=%x/%x\n", |
@@ -1704,6 +1785,9 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, | |||
1704 | pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); | 1785 | pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); |
1705 | pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn); | 1786 | pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn); |
1706 | 1787 | ||
1788 | /* some ARM have no bridge_pdev and will crash here | ||
1789 | * so we should check if bridge_pdev is NULL | ||
1790 | */ | ||
1707 | if (bridge_pdev) { | 1791 | if (bridge_pdev) { |
1708 | /*find bridge info if available */ | 1792 | /*find bridge info if available */ |
1709 | pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; | 1793 | pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; |
@@ -1758,6 +1842,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, | |||
1758 | pcipriv->ndis_adapter.amd_l1_patch); | 1842 | pcipriv->ndis_adapter.amd_l1_patch); |
1759 | 1843 | ||
1760 | rtl_pci_parse_configuration(pdev, hw); | 1844 | rtl_pci_parse_configuration(pdev, hw); |
1845 | list_add_tail(&rtlpriv->list, &rtlpriv->glb_var->glb_priv_list); | ||
1761 | 1846 | ||
1762 | return true; | 1847 | return true; |
1763 | } | 1848 | } |
@@ -1804,6 +1889,7 @@ int rtl_pci_probe(struct pci_dev *pdev, | |||
1804 | pci_set_drvdata(pdev, hw); | 1889 | pci_set_drvdata(pdev, hw); |
1805 | 1890 | ||
1806 | rtlpriv = hw->priv; | 1891 | rtlpriv = hw->priv; |
1892 | rtlpriv->hw = hw; | ||
1807 | pcipriv = (void *)rtlpriv->priv; | 1893 | pcipriv = (void *)rtlpriv->priv; |
1808 | pcipriv->dev.pdev = pdev; | 1894 | pcipriv->dev.pdev = pdev; |
1809 | init_completion(&rtlpriv->firmware_loading_complete); | 1895 | init_completion(&rtlpriv->firmware_loading_complete); |
@@ -1812,6 +1898,7 @@ int rtl_pci_probe(struct pci_dev *pdev, | |||
1812 | rtlpriv->rtlhal.interface = INTF_PCI; | 1898 | rtlpriv->rtlhal.interface = INTF_PCI; |
1813 | rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); | 1899 | rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); |
1814 | rtlpriv->intf_ops = &rtl_pci_ops; | 1900 | rtlpriv->intf_ops = &rtl_pci_ops; |
1901 | rtlpriv->glb_var = &global_var; | ||
1815 | 1902 | ||
1816 | /* | 1903 | /* |
1817 | *init dbgp flags before all | 1904 | *init dbgp flags before all |
@@ -1916,7 +2003,6 @@ int rtl_pci_probe(struct pci_dev *pdev, | |||
1916 | 2003 | ||
1917 | fail3: | 2004 | fail3: |
1918 | rtl_deinit_core(hw); | 2005 | rtl_deinit_core(hw); |
1919 | _rtl_pci_io_handler_release(hw); | ||
1920 | 2006 | ||
1921 | if (rtlpriv->io.pci_mem_start != 0) | 2007 | if (rtlpriv->io.pci_mem_start != 0) |
1922 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); | 2008 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); |
@@ -1965,14 +2051,15 @@ void rtl_pci_disconnect(struct pci_dev *pdev) | |||
1965 | 2051 | ||
1966 | rtl_pci_deinit(hw); | 2052 | rtl_pci_deinit(hw); |
1967 | rtl_deinit_core(hw); | 2053 | rtl_deinit_core(hw); |
1968 | _rtl_pci_io_handler_release(hw); | ||
1969 | rtlpriv->cfg->ops->deinit_sw_vars(hw); | 2054 | rtlpriv->cfg->ops->deinit_sw_vars(hw); |
1970 | 2055 | ||
1971 | if (rtlpci->irq_alloc) { | 2056 | if (rtlpci->irq_alloc) { |
2057 | synchronize_irq(rtlpci->pdev->irq); | ||
1972 | free_irq(rtlpci->pdev->irq, hw); | 2058 | free_irq(rtlpci->pdev->irq, hw); |
1973 | rtlpci->irq_alloc = 0; | 2059 | rtlpci->irq_alloc = 0; |
1974 | } | 2060 | } |
1975 | 2061 | ||
2062 | list_del(&rtlpriv->list); | ||
1976 | if (rtlpriv->io.pci_mem_start != 0) { | 2063 | if (rtlpriv->io.pci_mem_start != 0) { |
1977 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); | 2064 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); |
1978 | pci_release_regions(pdev); | 2065 | pci_release_regions(pdev); |
@@ -2034,6 +2121,7 @@ struct rtl_intf_ops rtl_pci_ops = { | |||
2034 | .read_efuse_byte = read_efuse_byte, | 2121 | .read_efuse_byte = read_efuse_byte, |
2035 | .adapter_start = rtl_pci_start, | 2122 | .adapter_start = rtl_pci_start, |
2036 | .adapter_stop = rtl_pci_stop, | 2123 | .adapter_stop = rtl_pci_stop, |
2124 | .check_buddy_priv = rtl_pci_check_buddy_priv, | ||
2037 | .adapter_tx = rtl_pci_tx, | 2125 | .adapter_tx = rtl_pci_tx, |
2038 | .flush = rtl_pci_flush, | 2126 | .flush = rtl_pci_flush, |
2039 | .reset_trx_ring = rtl_pci_reset_trx_ring, | 2127 | .reset_trx_ring = rtl_pci_reset_trx_ring, |
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index 65b08f50022e..d3262ec45d23 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h | |||
@@ -94,6 +94,7 @@ | |||
94 | #define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ | 94 | #define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ |
95 | #define RTL_PCI_8192DE_DID 0x8193 /*8192de */ | 95 | #define RTL_PCI_8192DE_DID 0x8193 /*8192de */ |
96 | #define RTL_PCI_8192DE_DID2 0x002B /*92DE*/ | 96 | #define RTL_PCI_8192DE_DID2 0x002B /*92DE*/ |
97 | #define RTL_PCI_8188EE_DID 0x8179 /*8188ee*/ | ||
97 | 98 | ||
98 | /*8192 support 16 pages of IO registers*/ | 99 | /*8192 support 16 pages of IO registers*/ |
99 | #define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 | 100 | #define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 |
@@ -175,6 +176,7 @@ struct rtl_pci { | |||
175 | /*irq */ | 176 | /*irq */ |
176 | u8 irq_alloc; | 177 | u8 irq_alloc; |
177 | u32 irq_mask[2]; | 178 | u32 irq_mask[2]; |
179 | u32 sys_irq_mask; | ||
178 | 180 | ||
179 | /*Bcn control register setting */ | 181 | /*Bcn control register setting */ |
180 | u32 reg_bcn_ctrl_val; | 182 | u32 reg_bcn_ctrl_val; |
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 13ad33e85577..884bceae38a9 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c | |||
@@ -180,6 +180,9 @@ void rtl_ips_nic_off_wq_callback(void *data) | |||
180 | return; | 180 | return; |
181 | } | 181 | } |
182 | 182 | ||
183 | if (mac->p2p_in_use) | ||
184 | return; | ||
185 | |||
183 | if (mac->link_state > MAC80211_NOLINK) | 186 | if (mac->link_state > MAC80211_NOLINK) |
184 | return; | 187 | return; |
185 | 188 | ||
@@ -189,6 +192,9 @@ void rtl_ips_nic_off_wq_callback(void *data) | |||
189 | if (rtlpriv->sec.being_setkey) | 192 | if (rtlpriv->sec.being_setkey) |
190 | return; | 193 | return; |
191 | 194 | ||
195 | if (rtlpriv->cfg->ops->bt_coex_off_before_lps) | ||
196 | rtlpriv->cfg->ops->bt_coex_off_before_lps(hw); | ||
197 | |||
192 | if (ppsc->inactiveps) { | 198 | if (ppsc->inactiveps) { |
193 | rtstate = ppsc->rfpwr_state; | 199 | rtstate = ppsc->rfpwr_state; |
194 | 200 | ||
@@ -231,6 +237,9 @@ void rtl_ips_nic_off(struct ieee80211_hw *hw) | |||
231 | &rtlpriv->works.ips_nic_off_wq, MSECS(100)); | 237 | &rtlpriv->works.ips_nic_off_wq, MSECS(100)); |
232 | } | 238 | } |
233 | 239 | ||
240 | /* NOTICE: any opmode should exc nic_on, or disable without | ||
241 | * nic_on may something wrong, like adhoc TP | ||
242 | */ | ||
234 | void rtl_ips_nic_on(struct ieee80211_hw *hw) | 243 | void rtl_ips_nic_on(struct ieee80211_hw *hw) |
235 | { | 244 | { |
236 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 245 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -299,7 +308,7 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) | |||
299 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 308 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
300 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 309 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
301 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 310 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
302 | u8 rpwm_val, fw_pwrmode; | 311 | bool enter_fwlps; |
303 | 312 | ||
304 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | 313 | if (mac->opmode == NL80211_IFTYPE_ADHOC) |
305 | return; | 314 | return; |
@@ -324,43 +333,31 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) | |||
324 | */ | 333 | */ |
325 | 334 | ||
326 | if ((ppsc->fwctrl_lps) && ppsc->report_linked) { | 335 | if ((ppsc->fwctrl_lps) && ppsc->report_linked) { |
327 | bool fw_current_inps; | ||
328 | if (ppsc->dot11_psmode == EACTIVE) { | 336 | if (ppsc->dot11_psmode == EACTIVE) { |
329 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | 337 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, |
330 | "FW LPS leave ps_mode:%x\n", | 338 | "FW LPS leave ps_mode:%x\n", |
331 | FW_PS_ACTIVE_MODE); | 339 | FW_PS_ACTIVE_MODE); |
332 | 340 | enter_fwlps = false; | |
333 | rpwm_val = 0x0C; /* RF on */ | 341 | ppsc->pwr_mode = FW_PS_ACTIVE_MODE; |
334 | fw_pwrmode = FW_PS_ACTIVE_MODE; | 342 | ppsc->smart_ps = 0; |
335 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
336 | &rpwm_val); | ||
337 | rtlpriv->cfg->ops->set_hw_reg(hw, | 343 | rtlpriv->cfg->ops->set_hw_reg(hw, |
338 | HW_VAR_H2C_FW_PWRMODE, | 344 | HW_VAR_FW_LPS_ACTION, |
339 | &fw_pwrmode); | 345 | (u8 *)(&enter_fwlps)); |
340 | fw_current_inps = false; | 346 | if (ppsc->p2p_ps_info.opp_ps) |
341 | 347 | rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); | |
342 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
343 | HW_VAR_FW_PSMODE_STATUS, | ||
344 | (u8 *) (&fw_current_inps)); | ||
345 | 348 | ||
346 | } else { | 349 | } else { |
347 | if (rtl_get_fwlps_doze(hw)) { | 350 | if (rtl_get_fwlps_doze(hw)) { |
348 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | 351 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, |
349 | "FW LPS enter ps_mode:%x\n", | 352 | "FW LPS enter ps_mode:%x\n", |
350 | ppsc->fwctrl_psmode); | 353 | ppsc->fwctrl_psmode); |
351 | 354 | enter_fwlps = true; | |
352 | rpwm_val = 0x02; /* RF off */ | 355 | ppsc->pwr_mode = ppsc->fwctrl_psmode; |
353 | fw_current_inps = true; | 356 | ppsc->smart_ps = 2; |
354 | rtlpriv->cfg->ops->set_hw_reg(hw, | 357 | rtlpriv->cfg->ops->set_hw_reg(hw, |
355 | HW_VAR_FW_PSMODE_STATUS, | 358 | HW_VAR_FW_LPS_ACTION, |
356 | (u8 *) (&fw_current_inps)); | 359 | (u8 *)(&enter_fwlps)); |
357 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
358 | HW_VAR_H2C_FW_PWRMODE, | ||
359 | &ppsc->fwctrl_psmode); | ||
360 | 360 | ||
361 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
362 | HW_VAR_SET_RPWM, | ||
363 | &rpwm_val); | ||
364 | } else { | 361 | } else { |
365 | /* Reset the power save related parameters. */ | 362 | /* Reset the power save related parameters. */ |
366 | ppsc->dot11_psmode = EACTIVE; | 363 | ppsc->dot11_psmode = EACTIVE; |
@@ -642,3 +639,286 @@ void rtl_swlps_wq_callback(void *data) | |||
642 | rtlpriv->psc.state = ps; | 639 | rtlpriv->psc.state = ps; |
643 | } | 640 | } |
644 | } | 641 | } |
642 | |||
643 | static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data, | ||
644 | unsigned int len) | ||
645 | { | ||
646 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
647 | struct ieee80211_mgmt *mgmt = (void *)data; | ||
648 | struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); | ||
649 | u8 *pos, *end, *ie; | ||
650 | u16 noa_len; | ||
651 | static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; | ||
652 | u8 noa_num, index, i, noa_index = 0; | ||
653 | bool find_p2p_ie = false , find_p2p_ps_ie = false; | ||
654 | pos = (u8 *)mgmt->u.beacon.variable; | ||
655 | end = data + len; | ||
656 | ie = NULL; | ||
657 | |||
658 | while (pos + 1 < end) { | ||
659 | if (pos + 2 + pos[1] > end) | ||
660 | return; | ||
661 | |||
662 | if (pos[0] == 221 && pos[1] > 4) { | ||
663 | if (memcmp(&pos[2], p2p_oui_ie_type, 4) == 0) { | ||
664 | ie = pos + 2+4; | ||
665 | break; | ||
666 | } | ||
667 | } | ||
668 | pos += 2 + pos[1]; | ||
669 | } | ||
670 | |||
671 | if (ie == NULL) | ||
672 | return; | ||
673 | find_p2p_ie = true; | ||
674 | /*to find noa ie*/ | ||
675 | while (ie + 1 < end) { | ||
676 | noa_len = READEF2BYTE(&ie[1]); | ||
677 | if (ie + 3 + ie[1] > end) | ||
678 | return; | ||
679 | |||
680 | if (ie[0] == 12) { | ||
681 | find_p2p_ps_ie = true; | ||
682 | if ((noa_len - 2) % 13 != 0) { | ||
683 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
684 | "P2P notice of absence: invalid length.%d\n", | ||
685 | noa_len); | ||
686 | return; | ||
687 | } else { | ||
688 | noa_num = (noa_len - 2) / 13; | ||
689 | } | ||
690 | noa_index = ie[3]; | ||
691 | if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == | ||
692 | P2P_PS_NONE || noa_index != p2pinfo->noa_index) { | ||
693 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
694 | "update NOA ie.\n"); | ||
695 | p2pinfo->noa_index = noa_index; | ||
696 | p2pinfo->opp_ps = (ie[4] >> 7); | ||
697 | p2pinfo->ctwindow = ie[4] & 0x7F; | ||
698 | p2pinfo->noa_num = noa_num; | ||
699 | index = 5; | ||
700 | for (i = 0; i < noa_num; i++) { | ||
701 | p2pinfo->noa_count_type[i] = | ||
702 | READEF1BYTE(ie+index); | ||
703 | index += 1; | ||
704 | p2pinfo->noa_duration[i] = | ||
705 | READEF4BYTE(ie+index); | ||
706 | index += 4; | ||
707 | p2pinfo->noa_interval[i] = | ||
708 | READEF4BYTE(ie+index); | ||
709 | index += 4; | ||
710 | p2pinfo->noa_start_time[i] = | ||
711 | READEF4BYTE(ie+index); | ||
712 | index += 4; | ||
713 | } | ||
714 | |||
715 | if (p2pinfo->opp_ps == 1) { | ||
716 | p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW; | ||
717 | /* Driver should wait LPS entering | ||
718 | * CTWindow | ||
719 | */ | ||
720 | if (rtlpriv->psc.fw_current_inpsmode) | ||
721 | rtl_p2p_ps_cmd(hw, | ||
722 | P2P_PS_ENABLE); | ||
723 | } else if (p2pinfo->noa_num > 0) { | ||
724 | p2pinfo->p2p_ps_mode = P2P_PS_NOA; | ||
725 | rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); | ||
726 | } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
727 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
728 | } | ||
729 | } | ||
730 | break; | ||
731 | } | ||
732 | ie += 3 + noa_len; | ||
733 | } | ||
734 | |||
735 | if (find_p2p_ie == true) { | ||
736 | if ((p2pinfo->p2p_ps_mode > P2P_PS_NONE) && | ||
737 | (find_p2p_ps_ie == false)) | ||
738 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data, | ||
743 | unsigned int len) | ||
744 | { | ||
745 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
746 | struct ieee80211_mgmt *mgmt = (void *)data; | ||
747 | struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); | ||
748 | u8 noa_num, index, i, noa_index = 0; | ||
749 | u8 *pos, *end, *ie; | ||
750 | u16 noa_len; | ||
751 | static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; | ||
752 | |||
753 | pos = (u8 *)&mgmt->u.action.category; | ||
754 | end = data + len; | ||
755 | ie = NULL; | ||
756 | |||
757 | if (pos[0] == 0x7f) { | ||
758 | if (memcmp(&pos[1], p2p_oui_ie_type, 4) == 0) | ||
759 | ie = pos + 3+4; | ||
760 | } | ||
761 | |||
762 | if (ie == NULL) | ||
763 | return; | ||
764 | |||
765 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "action frame find P2P IE.\n"); | ||
766 | /*to find noa ie*/ | ||
767 | while (ie + 1 < end) { | ||
768 | noa_len = READEF2BYTE(&ie[1]); | ||
769 | if (ie + 3 + ie[1] > end) | ||
770 | return; | ||
771 | |||
772 | if (ie[0] == 12) { | ||
773 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "find NOA IE.\n"); | ||
774 | RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, "noa ie ", | ||
775 | ie, noa_len); | ||
776 | if ((noa_len - 2) % 13 != 0) { | ||
777 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
778 | "P2P notice of absence: invalid length.%d\n", | ||
779 | noa_len); | ||
780 | return; | ||
781 | } else { | ||
782 | noa_num = (noa_len - 2) / 13; | ||
783 | } | ||
784 | noa_index = ie[3]; | ||
785 | if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == | ||
786 | P2P_PS_NONE || noa_index != p2pinfo->noa_index) { | ||
787 | p2pinfo->noa_index = noa_index; | ||
788 | p2pinfo->opp_ps = (ie[4] >> 7); | ||
789 | p2pinfo->ctwindow = ie[4] & 0x7F; | ||
790 | p2pinfo->noa_num = noa_num; | ||
791 | index = 5; | ||
792 | for (i = 0; i < noa_num; i++) { | ||
793 | p2pinfo->noa_count_type[i] = | ||
794 | READEF1BYTE(ie+index); | ||
795 | index += 1; | ||
796 | p2pinfo->noa_duration[i] = | ||
797 | READEF4BYTE(ie+index); | ||
798 | index += 4; | ||
799 | p2pinfo->noa_interval[i] = | ||
800 | READEF4BYTE(ie+index); | ||
801 | index += 4; | ||
802 | p2pinfo->noa_start_time[i] = | ||
803 | READEF4BYTE(ie+index); | ||
804 | index += 4; | ||
805 | } | ||
806 | |||
807 | if (p2pinfo->opp_ps == 1) { | ||
808 | p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW; | ||
809 | /* Driver should wait LPS entering | ||
810 | * CTWindow | ||
811 | */ | ||
812 | if (rtlpriv->psc.fw_current_inpsmode) | ||
813 | rtl_p2p_ps_cmd(hw, | ||
814 | P2P_PS_ENABLE); | ||
815 | } else if (p2pinfo->noa_num > 0) { | ||
816 | p2pinfo->p2p_ps_mode = P2P_PS_NOA; | ||
817 | rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); | ||
818 | } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
819 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
820 | } | ||
821 | } | ||
822 | break; | ||
823 | } | ||
824 | ie += 3 + noa_len; | ||
825 | } | ||
826 | } | ||
827 | |||
828 | void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | ||
829 | { | ||
830 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
831 | struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); | ||
832 | struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); | ||
833 | |||
834 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, " p2p state %x\n", p2p_ps_state); | ||
835 | switch (p2p_ps_state) { | ||
836 | case P2P_PS_DISABLE: | ||
837 | p2pinfo->p2p_ps_state = p2p_ps_state; | ||
838 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
839 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
840 | (u8 *)(&p2p_ps_state)); | ||
841 | |||
842 | p2pinfo->noa_index = 0; | ||
843 | p2pinfo->ctwindow = 0; | ||
844 | p2pinfo->opp_ps = 0; | ||
845 | p2pinfo->noa_num = 0; | ||
846 | p2pinfo->p2p_ps_mode = P2P_PS_NONE; | ||
847 | if (rtlps->fw_current_inpsmode == true) { | ||
848 | if (rtlps->smart_ps == 0) { | ||
849 | rtlps->smart_ps = 2; | ||
850 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
851 | HW_VAR_H2C_FW_PWRMODE, | ||
852 | (u8 *)(&rtlps->pwr_mode)); | ||
853 | } | ||
854 | } | ||
855 | break; | ||
856 | case P2P_PS_ENABLE: | ||
857 | if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
858 | p2pinfo->p2p_ps_state = p2p_ps_state; | ||
859 | |||
860 | if (p2pinfo->ctwindow > 0) { | ||
861 | if (rtlps->smart_ps != 0) { | ||
862 | rtlps->smart_ps = 0; | ||
863 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
864 | HW_VAR_H2C_FW_PWRMODE, | ||
865 | (u8 *)(&rtlps->pwr_mode)); | ||
866 | } | ||
867 | } | ||
868 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
869 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
870 | (u8 *)(&p2p_ps_state)); | ||
871 | } | ||
872 | break; | ||
873 | case P2P_PS_SCAN: | ||
874 | case P2P_PS_SCAN_DONE: | ||
875 | case P2P_PS_ALLSTASLEEP: | ||
876 | if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
877 | p2pinfo->p2p_ps_state = p2p_ps_state; | ||
878 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
879 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
880 | (u8 *)(&p2p_ps_state)); | ||
881 | } | ||
882 | break; | ||
883 | default: | ||
884 | break; | ||
885 | } | ||
886 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
887 | "ctwindow %x oppps %x\n", p2pinfo->ctwindow, p2pinfo->opp_ps); | ||
888 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
889 | "count %x duration %x index %x interval %x start time %x noa num %x\n", | ||
890 | p2pinfo->noa_count_type[0], p2pinfo->noa_duration[0], | ||
891 | p2pinfo->noa_index, p2pinfo->noa_interval[0], | ||
892 | p2pinfo->noa_start_time[0], p2pinfo->noa_num); | ||
893 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "end\n"); | ||
894 | } | ||
895 | |||
896 | void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len) | ||
897 | { | ||
898 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
899 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
900 | struct ieee80211_hdr *hdr = (void *)data; | ||
901 | |||
902 | if (!mac->p2p) | ||
903 | return; | ||
904 | if (mac->link_state != MAC80211_LINKED) | ||
905 | return; | ||
906 | /* min. beacon length + FCS_LEN */ | ||
907 | if (len <= 40 + FCS_LEN) | ||
908 | return; | ||
909 | |||
910 | /* and only beacons from the associated BSSID, please */ | ||
911 | if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) | ||
912 | return; | ||
913 | |||
914 | /* check if this really is a beacon */ | ||
915 | if (!(ieee80211_is_beacon(hdr->frame_control) || | ||
916 | ieee80211_is_probe_resp(hdr->frame_control) || | ||
917 | ieee80211_is_action(hdr->frame_control))) | ||
918 | return; | ||
919 | |||
920 | if (ieee80211_is_action(hdr->frame_control)) | ||
921 | rtl_p2p_action_ie(hw, data, len - FCS_LEN); | ||
922 | else | ||
923 | rtl_p2p_noa_ie(hw, data, len - FCS_LEN); | ||
924 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h index 1357856998c2..4d682b753f50 100644 --- a/drivers/net/wireless/rtlwifi/ps.h +++ b/drivers/net/wireless/rtlwifi/ps.h | |||
@@ -47,5 +47,7 @@ void rtl_swlps_wq_callback(void *data); | |||
47 | void rtl_swlps_rfon_wq_callback(void *data); | 47 | void rtl_swlps_rfon_wq_callback(void *data); |
48 | void rtl_swlps_rf_awake(struct ieee80211_hw *hw); | 48 | void rtl_swlps_rf_awake(struct ieee80211_hw *hw); |
49 | void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); | 49 | void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); |
50 | void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); | ||
51 | void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len); | ||
50 | 52 | ||
51 | #endif | 53 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile b/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile new file mode 100644 index 000000000000..5b194e97f4b3 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile | |||
@@ -0,0 +1,16 @@ | |||
1 | rtl8188ee-objs := \ | ||
2 | dm.o \ | ||
3 | fw.o \ | ||
4 | hw.o \ | ||
5 | led.o \ | ||
6 | phy.o \ | ||
7 | pwrseq.o \ | ||
8 | pwrseqcmd.o \ | ||
9 | rf.o \ | ||
10 | sw.o \ | ||
11 | table.o \ | ||
12 | trx.o | ||
13 | |||
14 | obj-$(CONFIG_RTL8188EE) += rtl8188ee.o | ||
15 | |||
16 | ccflags-y += -Idrivers/net/wireless/rtlwifi -D__CHECK_ENDIAN__ | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/rtlwifi/rtl8188ee/def.h new file mode 100644 index 000000000000..c764fff9ebe6 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/def.h | |||
@@ -0,0 +1,324 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92C_DEF_H__ | ||
31 | #define __RTL92C_DEF_H__ | ||
32 | |||
33 | #define HAL_RETRY_LIMIT_INFRA 48 | ||
34 | #define HAL_RETRY_LIMIT_AP_ADHOC 7 | ||
35 | |||
36 | #define RESET_DELAY_8185 20 | ||
37 | |||
38 | #define RT_IBSS_INT_MASKS (IMR_BCNINT | IMR_TBDOK | IMR_TBDER) | ||
39 | #define RT_AC_INT_MASKS (IMR_VIDOK | IMR_VODOK | IMR_BEDOK|IMR_BKDOK) | ||
40 | |||
41 | #define NUM_OF_FIRMWARE_QUEUE 10 | ||
42 | #define NUM_OF_PAGES_IN_FW 0x100 | ||
43 | #define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x07 | ||
44 | #define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x07 | ||
45 | #define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x07 | ||
46 | #define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x07 | ||
47 | #define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0x0 | ||
48 | #define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x0 | ||
49 | #define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x02 | ||
50 | #define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0x02 | ||
51 | #define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x2 | ||
52 | #define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xA1 | ||
53 | |||
54 | #define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM 0x026 | ||
55 | #define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM 0x048 | ||
56 | #define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM 0x048 | ||
57 | #define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM 0x026 | ||
58 | #define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM 0x00 | ||
59 | |||
60 | #define MAX_LINES_HWCONFIG_TXT 1000 | ||
61 | #define MAX_BYTES_LINE_HWCONFIG_TXT 256 | ||
62 | |||
63 | #define SW_THREE_WIRE 0 | ||
64 | #define HW_THREE_WIRE 2 | ||
65 | |||
66 | #define BT_DEMO_BOARD 0 | ||
67 | #define BT_QA_BOARD 1 | ||
68 | #define BT_FPGA 2 | ||
69 | |||
70 | #define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 | ||
71 | #define HAL_PRIME_CHNL_OFFSET_LOWER 1 | ||
72 | #define HAL_PRIME_CHNL_OFFSET_UPPER 2 | ||
73 | |||
74 | #define MAX_H2C_QUEUE_NUM 10 | ||
75 | |||
76 | #define RX_MPDU_QUEUE 0 | ||
77 | #define RX_CMD_QUEUE 1 | ||
78 | #define RX_MAX_QUEUE 2 | ||
79 | #define AC2QUEUEID(_AC) (_AC) | ||
80 | |||
81 | #define C2H_RX_CMD_HDR_LEN 8 | ||
82 | #define GET_C2H_CMD_CMD_LEN(__prxhdr) \ | ||
83 | LE_BITS_TO_4BYTE((__prxhdr), 0, 16) | ||
84 | #define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ | ||
85 | LE_BITS_TO_4BYTE((__prxhdr), 16, 8) | ||
86 | #define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ | ||
87 | LE_BITS_TO_4BYTE((__prxhdr), 24, 7) | ||
88 | #define GET_C2H_CMD_CONTINUE(__prxhdr) \ | ||
89 | LE_BITS_TO_4BYTE((__prxhdr), 31, 1) | ||
90 | #define GET_C2H_CMD_CONTENT(__prxhdr) \ | ||
91 | ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) | ||
92 | |||
93 | #define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ | ||
94 | LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) | ||
95 | #define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ | ||
96 | LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) | ||
97 | #define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ | ||
98 | LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) | ||
99 | #define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ | ||
100 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) | ||
101 | #define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ | ||
102 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) | ||
103 | #define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ | ||
104 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) | ||
105 | #define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ | ||
106 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) | ||
107 | #define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ | ||
108 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) | ||
109 | #define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ | ||
110 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) | ||
111 | |||
112 | #define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) | ||
113 | |||
114 | |||
115 | /* [15:12] IC version(CUT): A-cut=0, B-cut=1, C-cut=2, D-cut=3 | ||
116 | * [7] Manufacturer: TSMC=0, UMC=1 | ||
117 | * [6:4] RF type: 1T1R=0, 1T2R=1, 2T2R=2 | ||
118 | * [3] Chip type: TEST=0, NORMAL=1 | ||
119 | * [2:0] IC type: 81xxC=0, 8723=1, 92D=2 | ||
120 | */ | ||
121 | #define CHIP_8723 BIT(0) | ||
122 | #define CHIP_92D BIT(1) | ||
123 | #define NORMAL_CHIP BIT(3) | ||
124 | #define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6))) | ||
125 | #define RF_TYPE_1T2R BIT(4) | ||
126 | #define RF_TYPE_2T2R BIT(5) | ||
127 | #define CHIP_VENDOR_UMC BIT(7) | ||
128 | #define B_CUT_VERSION BIT(12) | ||
129 | #define C_CUT_VERSION BIT(13) | ||
130 | #define D_CUT_VERSION ((BIT(12)|BIT(13))) | ||
131 | #define E_CUT_VERSION BIT(14) | ||
132 | |||
133 | |||
134 | /* MASK */ | ||
135 | #define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) | ||
136 | #define CHIP_TYPE_MASK BIT(3) | ||
137 | #define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6)) | ||
138 | #define MANUFACTUER_MASK BIT(7) | ||
139 | #define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8)) | ||
140 | #define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12)) | ||
141 | |||
142 | /* Get element */ | ||
143 | #define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK) | ||
144 | #define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK) | ||
145 | #define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK) | ||
146 | #define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK) | ||
147 | #define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK) | ||
148 | #define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK) | ||
149 | |||
150 | |||
151 | #define IS_81XXC(version) \ | ||
152 | ((GET_CVID_IC_TYPE(version) == 0) ? true : false) | ||
153 | #define IS_8723_SERIES(version) \ | ||
154 | ((GET_CVID_IC_TYPE(version) == CHIP_8723) ? true : false) | ||
155 | #define IS_92D(version) \ | ||
156 | ((GET_CVID_IC_TYPE(version) == CHIP_92D) ? true : false) | ||
157 | |||
158 | #define IS_NORMAL_CHIP(version) \ | ||
159 | ((GET_CVID_CHIP_TYPE(version)) ? true : false) | ||
160 | #define IS_NORMAL_CHIP92D(version) \ | ||
161 | ((GET_CVID_CHIP_TYPE(version)) ? true : false) | ||
162 | |||
163 | #define IS_1T1R(version) \ | ||
164 | ((GET_CVID_RF_TYPE(version)) ? false : true) | ||
165 | #define IS_1T2R(version) \ | ||
166 | ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false) | ||
167 | #define IS_2T2R(version) \ | ||
168 | ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false) | ||
169 | #define IS_CHIP_VENDOR_UMC(version) \ | ||
170 | ((GET_CVID_MANUFACTUER(version)) ? true : false) | ||
171 | |||
172 | #define IS_92C_SERIAL(version) \ | ||
173 | ((IS_81XXC(version) && IS_2T2R(version)) ? true : false) | ||
174 | #define IS_81xxC_VENDOR_UMC_A_CUT(version) \ | ||
175 | (IS_81XXC(version) ? ((IS_CHIP_VENDOR_UMC(version)) ? \ | ||
176 | ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) : false) | ||
177 | #define IS_81xxC_VENDOR_UMC_B_CUT(version) \ | ||
178 | (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \ | ||
179 | ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true \ | ||
180 | : false) : false) : false) | ||
181 | |||
182 | enum version_8188e { | ||
183 | VERSION_TEST_CHIP_88E = 0x00, | ||
184 | VERSION_NORMAL_CHIP_88E = 0x01, | ||
185 | VERSION_UNKNOWN = 0xFF, | ||
186 | }; | ||
187 | |||
188 | enum rx_packet_type { | ||
189 | NORMAL_RX, | ||
190 | TX_REPORT1, | ||
191 | TX_REPORT2, | ||
192 | HIS_REPORT, | ||
193 | }; | ||
194 | |||
195 | enum rtl819x_loopback_e { | ||
196 | RTL819X_NO_LOOPBACK = 0, | ||
197 | RTL819X_MAC_LOOPBACK = 1, | ||
198 | RTL819X_DMA_LOOPBACK = 2, | ||
199 | RTL819X_CCK_LOOPBACK = 3, | ||
200 | }; | ||
201 | |||
202 | enum rf_optype { | ||
203 | RF_OP_BY_SW_3WIRE = 0, | ||
204 | RF_OP_BY_FW, | ||
205 | RF_OP_MAX | ||
206 | }; | ||
207 | |||
208 | enum rf_power_state { | ||
209 | RF_ON, | ||
210 | RF_OFF, | ||
211 | RF_SLEEP, | ||
212 | RF_SHUT_DOWN, | ||
213 | }; | ||
214 | |||
215 | enum power_save_mode { | ||
216 | POWER_SAVE_MODE_ACTIVE, | ||
217 | POWER_SAVE_MODE_SAVE, | ||
218 | }; | ||
219 | |||
220 | enum power_polocy_config { | ||
221 | POWERCFG_MAX_POWER_SAVINGS, | ||
222 | POWERCFG_GLOBAL_POWER_SAVINGS, | ||
223 | POWERCFG_LOCAL_POWER_SAVINGS, | ||
224 | POWERCFG_LENOVO, | ||
225 | }; | ||
226 | |||
227 | enum interface_select_pci { | ||
228 | INTF_SEL1_MINICARD, | ||
229 | INTF_SEL0_PCIE, | ||
230 | INTF_SEL2_RSV, | ||
231 | INTF_SEL3_RSV, | ||
232 | }; | ||
233 | |||
234 | enum hal_fw_c2h_cmd_id { | ||
235 | HAL_FW_C2H_CMD_Read_MACREG, | ||
236 | HAL_FW_C2H_CMD_Read_BBREG, | ||
237 | HAL_FW_C2H_CMD_Read_RFREG, | ||
238 | HAL_FW_C2H_CMD_Read_EEPROM, | ||
239 | HAL_FW_C2H_CMD_Read_EFUSE, | ||
240 | HAL_FW_C2H_CMD_Read_CAM, | ||
241 | HAL_FW_C2H_CMD_Get_BasicRate, | ||
242 | HAL_FW_C2H_CMD_Get_DataRate, | ||
243 | HAL_FW_C2H_CMD_Survey, | ||
244 | HAL_FW_C2H_CMD_SurveyDone, | ||
245 | HAL_FW_C2H_CMD_JoinBss, | ||
246 | HAL_FW_C2H_CMD_AddSTA, | ||
247 | HAL_FW_C2H_CMD_DelSTA, | ||
248 | HAL_FW_C2H_CMD_AtimDone, | ||
249 | HAL_FW_C2H_CMD_TX_Report, | ||
250 | HAL_FW_C2H_CMD_CCX_Report, | ||
251 | HAL_FW_C2H_CMD_DTM_Report, | ||
252 | HAL_FW_C2H_CMD_TX_Rate_Statistics, | ||
253 | HAL_FW_C2H_CMD_C2HLBK, | ||
254 | HAL_FW_C2H_CMD_C2HDBG, | ||
255 | HAL_FW_C2H_CMD_C2HFEEDBACK, | ||
256 | HAL_FW_C2H_CMD_MAX | ||
257 | }; | ||
258 | |||
259 | enum wake_on_wlan_mode { | ||
260 | ewowlandisable, | ||
261 | ewakeonmagicpacketonly, | ||
262 | ewakeonpatternmatchonly, | ||
263 | ewakeonbothtypepacket | ||
264 | }; | ||
265 | |||
266 | enum rtl_desc_qsel { | ||
267 | QSLT_BK = 0x2, | ||
268 | QSLT_BE = 0x0, | ||
269 | QSLT_VI = 0x5, | ||
270 | QSLT_VO = 0x7, | ||
271 | QSLT_BEACON = 0x10, | ||
272 | QSLT_HIGH = 0x11, | ||
273 | QSLT_MGNT = 0x12, | ||
274 | QSLT_CMD = 0x13, | ||
275 | }; | ||
276 | |||
277 | enum rtl_desc92c_rate { | ||
278 | DESC92C_RATE1M = 0x00, | ||
279 | DESC92C_RATE2M = 0x01, | ||
280 | DESC92C_RATE5_5M = 0x02, | ||
281 | DESC92C_RATE11M = 0x03, | ||
282 | |||
283 | DESC92C_RATE6M = 0x04, | ||
284 | DESC92C_RATE9M = 0x05, | ||
285 | DESC92C_RATE12M = 0x06, | ||
286 | DESC92C_RATE18M = 0x07, | ||
287 | DESC92C_RATE24M = 0x08, | ||
288 | DESC92C_RATE36M = 0x09, | ||
289 | DESC92C_RATE48M = 0x0a, | ||
290 | DESC92C_RATE54M = 0x0b, | ||
291 | |||
292 | DESC92C_RATEMCS0 = 0x0c, | ||
293 | DESC92C_RATEMCS1 = 0x0d, | ||
294 | DESC92C_RATEMCS2 = 0x0e, | ||
295 | DESC92C_RATEMCS3 = 0x0f, | ||
296 | DESC92C_RATEMCS4 = 0x10, | ||
297 | DESC92C_RATEMCS5 = 0x11, | ||
298 | DESC92C_RATEMCS6 = 0x12, | ||
299 | DESC92C_RATEMCS7 = 0x13, | ||
300 | DESC92C_RATEMCS8 = 0x14, | ||
301 | DESC92C_RATEMCS9 = 0x15, | ||
302 | DESC92C_RATEMCS10 = 0x16, | ||
303 | DESC92C_RATEMCS11 = 0x17, | ||
304 | DESC92C_RATEMCS12 = 0x18, | ||
305 | DESC92C_RATEMCS13 = 0x19, | ||
306 | DESC92C_RATEMCS14 = 0x1a, | ||
307 | DESC92C_RATEMCS15 = 0x1b, | ||
308 | DESC92C_RATEMCS15_SG = 0x1c, | ||
309 | DESC92C_RATEMCS32 = 0x20, | ||
310 | }; | ||
311 | |||
312 | struct phy_sts_cck_8192s_t { | ||
313 | u8 adc_pwdb_X[4]; | ||
314 | u8 sq_rpt; | ||
315 | u8 cck_agc_rpt; | ||
316 | }; | ||
317 | |||
318 | struct h2c_cmd_8192c { | ||
319 | u8 element_id; | ||
320 | u32 cmd_len; | ||
321 | u8 *p_cmdbuffer; | ||
322 | }; | ||
323 | |||
324 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c new file mode 100644 index 000000000000..21a5cf060677 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c | |||
@@ -0,0 +1,1794 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../base.h" | ||
32 | #include "../pci.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "phy.h" | ||
36 | #include "dm.h" | ||
37 | #include "fw.h" | ||
38 | #include "trx.h" | ||
39 | |||
40 | static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { | ||
41 | 0x7f8001fe, /* 0, +6.0dB */ | ||
42 | 0x788001e2, /* 1, +5.5dB */ | ||
43 | 0x71c001c7, /* 2, +5.0dB */ | ||
44 | 0x6b8001ae, /* 3, +4.5dB */ | ||
45 | 0x65400195, /* 4, +4.0dB */ | ||
46 | 0x5fc0017f, /* 5, +3.5dB */ | ||
47 | 0x5a400169, /* 6, +3.0dB */ | ||
48 | 0x55400155, /* 7, +2.5dB */ | ||
49 | 0x50800142, /* 8, +2.0dB */ | ||
50 | 0x4c000130, /* 9, +1.5dB */ | ||
51 | 0x47c0011f, /* 10, +1.0dB */ | ||
52 | 0x43c0010f, /* 11, +0.5dB */ | ||
53 | 0x40000100, /* 12, +0dB */ | ||
54 | 0x3c8000f2, /* 13, -0.5dB */ | ||
55 | 0x390000e4, /* 14, -1.0dB */ | ||
56 | 0x35c000d7, /* 15, -1.5dB */ | ||
57 | 0x32c000cb, /* 16, -2.0dB */ | ||
58 | 0x300000c0, /* 17, -2.5dB */ | ||
59 | 0x2d4000b5, /* 18, -3.0dB */ | ||
60 | 0x2ac000ab, /* 19, -3.5dB */ | ||
61 | 0x288000a2, /* 20, -4.0dB */ | ||
62 | 0x26000098, /* 21, -4.5dB */ | ||
63 | 0x24000090, /* 22, -5.0dB */ | ||
64 | 0x22000088, /* 23, -5.5dB */ | ||
65 | 0x20000080, /* 24, -6.0dB */ | ||
66 | 0x1e400079, /* 25, -6.5dB */ | ||
67 | 0x1c800072, /* 26, -7.0dB */ | ||
68 | 0x1b00006c, /* 27. -7.5dB */ | ||
69 | 0x19800066, /* 28, -8.0dB */ | ||
70 | 0x18000060, /* 29, -8.5dB */ | ||
71 | 0x16c0005b, /* 30, -9.0dB */ | ||
72 | 0x15800056, /* 31, -9.5dB */ | ||
73 | 0x14400051, /* 32, -10.0dB */ | ||
74 | 0x1300004c, /* 33, -10.5dB */ | ||
75 | 0x12000048, /* 34, -11.0dB */ | ||
76 | 0x11000044, /* 35, -11.5dB */ | ||
77 | 0x10000040, /* 36, -12.0dB */ | ||
78 | 0x0f00003c, /* 37, -12.5dB */ | ||
79 | 0x0e400039, /* 38, -13.0dB */ | ||
80 | 0x0d800036, /* 39, -13.5dB */ | ||
81 | 0x0cc00033, /* 40, -14.0dB */ | ||
82 | 0x0c000030, /* 41, -14.5dB */ | ||
83 | 0x0b40002d, /* 42, -15.0dB */ | ||
84 | }; | ||
85 | |||
86 | static const u8 cck_tbl_ch1_13[CCK_TABLE_SIZE][8] = { | ||
87 | {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ | ||
88 | {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ | ||
89 | {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ | ||
90 | {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ | ||
91 | {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ | ||
92 | {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ | ||
93 | {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ | ||
94 | {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ | ||
95 | {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ | ||
96 | {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ | ||
97 | {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ | ||
98 | {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ | ||
99 | {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ | ||
100 | {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ | ||
101 | {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ | ||
102 | {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ | ||
103 | {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ | ||
104 | {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ | ||
105 | {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ | ||
106 | {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ | ||
107 | {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB*/ | ||
108 | {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB*/ | ||
109 | {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB*/ | ||
110 | {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB*/ | ||
111 | {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB*/ | ||
112 | {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB*/ | ||
113 | {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB*/ | ||
114 | {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB*/ | ||
115 | {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB*/ | ||
116 | {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB*/ | ||
117 | {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB*/ | ||
118 | {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB*/ | ||
119 | {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB*/ | ||
120 | }; | ||
121 | |||
122 | static const u8 cck_tbl_ch14[CCK_TABLE_SIZE][8] = { | ||
123 | {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ | ||
124 | {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ | ||
125 | {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ | ||
126 | {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ | ||
127 | {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ | ||
128 | {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ | ||
129 | {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ | ||
130 | {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ | ||
131 | {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ | ||
132 | {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ | ||
133 | {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ | ||
134 | {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ | ||
135 | {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ | ||
136 | {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ | ||
137 | {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ | ||
138 | {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ | ||
139 | {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ | ||
140 | {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ | ||
141 | {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ | ||
142 | {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ | ||
143 | {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB*/ | ||
144 | {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB*/ | ||
145 | {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB*/ | ||
146 | {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB*/ | ||
147 | {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB*/ | ||
148 | {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB*/ | ||
149 | {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB*/ | ||
150 | {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB*/ | ||
151 | {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB*/ | ||
152 | {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB*/ | ||
153 | {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB*/ | ||
154 | {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB*/ | ||
155 | {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB*/ | ||
156 | }; | ||
157 | |||
158 | #define CAL_SWING_OFF(_off, _dir, _size, _del) \ | ||
159 | do { \ | ||
160 | for (_off = 0; _off < _size; _off++) { \ | ||
161 | if (_del < thermal_threshold[_dir][_off]) { \ | ||
162 | if (_off != 0) \ | ||
163 | _off--; \ | ||
164 | break; \ | ||
165 | } \ | ||
166 | } \ | ||
167 | if (_off >= _size) \ | ||
168 | _off = _size - 1; \ | ||
169 | } while (0) | ||
170 | |||
171 | static void rtl88e_set_iqk_matrix(struct ieee80211_hw *hw, | ||
172 | u8 ofdm_index, u8 rfpath, | ||
173 | long iqk_result_x, long iqk_result_y) | ||
174 | { | ||
175 | long ele_a = 0, ele_d, ele_c = 0, value32; | ||
176 | |||
177 | ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000)>>22; | ||
178 | |||
179 | if (iqk_result_x != 0) { | ||
180 | if ((iqk_result_x & 0x00000200) != 0) | ||
181 | iqk_result_x = iqk_result_x | 0xFFFFFC00; | ||
182 | ele_a = ((iqk_result_x * ele_d)>>8)&0x000003FF; | ||
183 | |||
184 | if ((iqk_result_y & 0x00000200) != 0) | ||
185 | iqk_result_y = iqk_result_y | 0xFFFFFC00; | ||
186 | ele_c = ((iqk_result_y * ele_d)>>8)&0x000003FF; | ||
187 | |||
188 | switch (rfpath) { | ||
189 | case RF90_PATH_A: | ||
190 | value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a; | ||
191 | rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD, | ||
192 | value32); | ||
193 | value32 = (ele_c & 0x000003C0) >> 6; | ||
194 | rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32); | ||
195 | value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; | ||
196 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(24), value32); | ||
197 | break; | ||
198 | case RF90_PATH_B: | ||
199 | value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a; | ||
200 | rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBAL, | ||
201 | MASKDWORD, value32); | ||
202 | value32 = (ele_c & 0x000003C0) >> 6; | ||
203 | rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, value32); | ||
204 | value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; | ||
205 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(28), value32); | ||
206 | break; | ||
207 | default: | ||
208 | break; | ||
209 | } | ||
210 | } else { | ||
211 | switch (rfpath) { | ||
212 | case RF90_PATH_A: | ||
213 | rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD, | ||
214 | ofdmswing_table[ofdm_index]); | ||
215 | rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00); | ||
216 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(24), 0x00); | ||
217 | break; | ||
218 | case RF90_PATH_B: | ||
219 | rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBAL, MASKDWORD, | ||
220 | ofdmswing_table[ofdm_index]); | ||
221 | rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, 0x00); | ||
222 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(28), 0x00); | ||
223 | break; | ||
224 | default: | ||
225 | break; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw, | ||
231 | u8 type, u8 *pdirection, u32 *poutwrite_val) | ||
232 | { | ||
233 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
234 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
235 | u8 pwr_val = 0; | ||
236 | u8 cck_base = rtldm->swing_idx_cck_base; | ||
237 | u8 cck_val = rtldm->swing_idx_cck; | ||
238 | u8 ofdm_base = rtldm->swing_idx_ofdm_base; | ||
239 | u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A]; | ||
240 | |||
241 | if (type == 0) { | ||
242 | if (ofdm_val <= ofdm_base) { | ||
243 | *pdirection = 1; | ||
244 | pwr_val = ofdm_base - ofdm_val; | ||
245 | } else { | ||
246 | *pdirection = 2; | ||
247 | pwr_val = ofdm_val - ofdm_base; | ||
248 | } | ||
249 | } else if (type == 1) { | ||
250 | if (cck_val <= cck_base) { | ||
251 | *pdirection = 1; | ||
252 | pwr_val = cck_base - cck_val; | ||
253 | } else { | ||
254 | *pdirection = 2; | ||
255 | pwr_val = cck_val - cck_base; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1)) | ||
260 | pwr_val = TXPWRTRACK_MAX_IDX; | ||
261 | |||
262 | *poutwrite_val = pwr_val | (pwr_val << 8) | (pwr_val << 16) | | ||
263 | (pwr_val << 24); | ||
264 | } | ||
265 | |||
266 | |||
267 | static void rtl88e_chk_tx_track(struct ieee80211_hw *hw, | ||
268 | enum pwr_track_control_method method, | ||
269 | u8 rfpath, u8 index) | ||
270 | { | ||
271 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
272 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
273 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
274 | int jj = rtldm->swing_idx_cck; | ||
275 | int i; | ||
276 | |||
277 | if (method == TXAGC) { | ||
278 | if (rtldm->swing_flag_ofdm == true || | ||
279 | rtldm->swing_flag_cck == true) { | ||
280 | u8 chan = rtlphy->current_channel; | ||
281 | rtl88e_phy_set_txpower_level(hw, chan); | ||
282 | rtldm->swing_flag_ofdm = false; | ||
283 | rtldm->swing_flag_cck = false; | ||
284 | } | ||
285 | } else if (method == BBSWING) { | ||
286 | if (!rtldm->cck_inch14) { | ||
287 | for (i = 0; i < 8; i++) | ||
288 | rtl_write_byte(rtlpriv, 0xa22 + i, | ||
289 | cck_tbl_ch1_13[jj][i]); | ||
290 | } else { | ||
291 | for (i = 0; i < 8; i++) | ||
292 | rtl_write_byte(rtlpriv, 0xa22 + i, | ||
293 | cck_tbl_ch14[jj][i]); | ||
294 | } | ||
295 | |||
296 | if (rfpath == RF90_PATH_A) { | ||
297 | long x = rtlphy->iqk_matrix[index].value[0][0]; | ||
298 | long y = rtlphy->iqk_matrix[index].value[0][1]; | ||
299 | u8 indx = rtldm->swing_idx_ofdm[rfpath]; | ||
300 | rtl88e_set_iqk_matrix(hw, indx, rfpath, x, y); | ||
301 | } else if (rfpath == RF90_PATH_B) { | ||
302 | u8 indx = rtldm->swing_idx_ofdm[rfpath]; | ||
303 | long x = rtlphy->iqk_matrix[indx].value[0][4]; | ||
304 | long y = rtlphy->iqk_matrix[indx].value[0][5]; | ||
305 | rtl88e_set_iqk_matrix(hw, indx, rfpath, x, y); | ||
306 | } | ||
307 | } else { | ||
308 | return; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | static void rtl88e_dm_diginit(struct ieee80211_hw *hw) | ||
313 | { | ||
314 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
315 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
316 | |||
317 | dm_dig->dig_enable_flag = true; | ||
318 | dm_dig->cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f); | ||
319 | dm_dig->pre_igvalue = 0; | ||
320 | dm_dig->cursta_cstate = DIG_STA_DISCONNECT; | ||
321 | dm_dig->presta_cstate = DIG_STA_DISCONNECT; | ||
322 | dm_dig->curmultista_cstate = DIG_MULTISTA_DISCONNECT; | ||
323 | dm_dig->rssi_lowthresh = DM_DIG_THRESH_LOW; | ||
324 | dm_dig->rssi_highthresh = DM_DIG_THRESH_HIGH; | ||
325 | dm_dig->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; | ||
326 | dm_dig->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; | ||
327 | dm_dig->rx_gain_max = DM_DIG_MAX; | ||
328 | dm_dig->rx_gain_min = DM_DIG_MIN; | ||
329 | dm_dig->back_val = DM_DIG_BACKOFF_DEFAULT; | ||
330 | dm_dig->back_range_max = DM_DIG_BACKOFF_MAX; | ||
331 | dm_dig->back_range_min = DM_DIG_BACKOFF_MIN; | ||
332 | dm_dig->pre_cck_cca_thres = 0xff; | ||
333 | dm_dig->cur_cck_cca_thres = 0x83; | ||
334 | dm_dig->forbidden_igi = DM_DIG_MIN; | ||
335 | dm_dig->large_fa_hit = 0; | ||
336 | dm_dig->recover_cnt = 0; | ||
337 | dm_dig->dig_min_0 = 0x25; | ||
338 | dm_dig->dig_min_1 = 0x25; | ||
339 | dm_dig->media_connect_0 = false; | ||
340 | dm_dig->media_connect_1 = false; | ||
341 | rtlpriv->dm.dm_initialgain_enable = true; | ||
342 | } | ||
343 | |||
344 | static u8 rtl88e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) | ||
345 | { | ||
346 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
347 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
348 | long rssi_val_min = 0; | ||
349 | |||
350 | if ((dm_dig->curmultista_cstate == DIG_MULTISTA_CONNECT) && | ||
351 | (dm_dig->cursta_cstate == DIG_STA_CONNECT)) { | ||
352 | if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0) | ||
353 | rssi_val_min = | ||
354 | (rtlpriv->dm.entry_min_undec_sm_pwdb > | ||
355 | rtlpriv->dm.undec_sm_pwdb) ? | ||
356 | rtlpriv->dm.undec_sm_pwdb : | ||
357 | rtlpriv->dm.entry_min_undec_sm_pwdb; | ||
358 | else | ||
359 | rssi_val_min = rtlpriv->dm.undec_sm_pwdb; | ||
360 | } else if (dm_dig->cursta_cstate == DIG_STA_CONNECT || | ||
361 | dm_dig->cursta_cstate == DIG_STA_BEFORE_CONNECT) { | ||
362 | rssi_val_min = rtlpriv->dm.undec_sm_pwdb; | ||
363 | } else if (dm_dig->curmultista_cstate == | ||
364 | DIG_MULTISTA_CONNECT) { | ||
365 | rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; | ||
366 | } | ||
367 | return (u8)rssi_val_min; | ||
368 | } | ||
369 | |||
370 | static void rtl88e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) | ||
371 | { | ||
372 | u32 ret_value; | ||
373 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
374 | struct false_alarm_statistics *alm_cnt = &(rtlpriv->falsealm_cnt); | ||
375 | |||
376 | rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); | ||
377 | rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); | ||
378 | |||
379 | ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); | ||
380 | alm_cnt->cnt_fast_fsync_fail = (ret_value&0xffff); | ||
381 | alm_cnt->cnt_sb_search_fail = ((ret_value&0xffff0000)>>16); | ||
382 | |||
383 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); | ||
384 | alm_cnt->cnt_ofdm_cca = (ret_value&0xffff); | ||
385 | alm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); | ||
386 | |||
387 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); | ||
388 | alm_cnt->cnt_rate_illegal = (ret_value & 0xffff); | ||
389 | alm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); | ||
390 | |||
391 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); | ||
392 | alm_cnt->cnt_mcs_fail = (ret_value & 0xffff); | ||
393 | alm_cnt->cnt_ofdm_fail = alm_cnt->cnt_parity_fail + | ||
394 | alm_cnt->cnt_rate_illegal + | ||
395 | alm_cnt->cnt_crc8_fail + | ||
396 | alm_cnt->cnt_mcs_fail + | ||
397 | alm_cnt->cnt_fast_fsync_fail + | ||
398 | alm_cnt->cnt_sb_search_fail; | ||
399 | |||
400 | ret_value = rtl_get_bbreg(hw, REG_SC_CNT, MASKDWORD); | ||
401 | alm_cnt->cnt_bw_lsc = (ret_value & 0xffff); | ||
402 | alm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16); | ||
403 | |||
404 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(12), 1); | ||
405 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); | ||
406 | |||
407 | ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); | ||
408 | alm_cnt->cnt_cck_fail = ret_value; | ||
409 | |||
410 | ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); | ||
411 | alm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; | ||
412 | |||
413 | ret_value = rtl_get_bbreg(hw, RCCK0_CCA_CNT, MASKDWORD); | ||
414 | alm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) | | ||
415 | ((ret_value&0xFF00)>>8); | ||
416 | |||
417 | alm_cnt->cnt_all = alm_cnt->cnt_fast_fsync_fail + | ||
418 | alm_cnt->cnt_sb_search_fail + | ||
419 | alm_cnt->cnt_parity_fail + | ||
420 | alm_cnt->cnt_rate_illegal + | ||
421 | alm_cnt->cnt_crc8_fail + | ||
422 | alm_cnt->cnt_mcs_fail + | ||
423 | alm_cnt->cnt_cck_fail; | ||
424 | alm_cnt->cnt_cca_all = alm_cnt->cnt_ofdm_cca + alm_cnt->cnt_cck_cca; | ||
425 | |||
426 | rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 1); | ||
427 | rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 0); | ||
428 | rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 1); | ||
429 | rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 0); | ||
430 | rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0); | ||
431 | rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0); | ||
432 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 0); | ||
433 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 2); | ||
434 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 0); | ||
435 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 2); | ||
436 | |||
437 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, | ||
438 | "cnt_parity_fail = %d, cnt_rate_illegal = %d, " | ||
439 | "cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", | ||
440 | alm_cnt->cnt_parity_fail, | ||
441 | alm_cnt->cnt_rate_illegal, | ||
442 | alm_cnt->cnt_crc8_fail, alm_cnt->cnt_mcs_fail); | ||
443 | |||
444 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, | ||
445 | "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", | ||
446 | alm_cnt->cnt_ofdm_fail, | ||
447 | alm_cnt->cnt_cck_fail, alm_cnt->cnt_all); | ||
448 | } | ||
449 | |||
450 | static void rtl88e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) | ||
451 | { | ||
452 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
453 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
454 | u8 cur_cck_cca_thresh; | ||
455 | |||
456 | if (dm_dig->cursta_cstate == DIG_STA_CONNECT) { | ||
457 | dm_dig->rssi_val_min = rtl88e_dm_initial_gain_min_pwdb(hw); | ||
458 | if (dm_dig->rssi_val_min > 25) { | ||
459 | cur_cck_cca_thresh = 0xcd; | ||
460 | } else if ((dm_dig->rssi_val_min <= 25) && | ||
461 | (dm_dig->rssi_val_min > 10)) { | ||
462 | cur_cck_cca_thresh = 0x83; | ||
463 | } else { | ||
464 | if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) | ||
465 | cur_cck_cca_thresh = 0x83; | ||
466 | else | ||
467 | cur_cck_cca_thresh = 0x40; | ||
468 | } | ||
469 | |||
470 | } else { | ||
471 | if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) | ||
472 | cur_cck_cca_thresh = 0x83; | ||
473 | else | ||
474 | cur_cck_cca_thresh = 0x40; | ||
475 | } | ||
476 | |||
477 | if (dm_dig->cur_cck_cca_thres != cur_cck_cca_thresh) | ||
478 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh); | ||
479 | |||
480 | dm_dig->cur_cck_cca_thres = cur_cck_cca_thresh; | ||
481 | dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres; | ||
482 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, | ||
483 | "CCK cca thresh hold =%x\n", dm_dig->cur_cck_cca_thres); | ||
484 | } | ||
485 | |||
486 | static void rtl88e_dm_dig(struct ieee80211_hw *hw) | ||
487 | { | ||
488 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
489 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
490 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
491 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
492 | u8 dig_min, dig_maxofmin; | ||
493 | bool bfirstconnect; | ||
494 | u8 dm_dig_max, dm_dig_min; | ||
495 | u8 current_igi = dm_dig->cur_igvalue; | ||
496 | |||
497 | if (rtlpriv->dm.dm_initialgain_enable == false) | ||
498 | return; | ||
499 | if (dm_dig->dig_enable_flag == false) | ||
500 | return; | ||
501 | if (mac->act_scanning == true) | ||
502 | return; | ||
503 | |||
504 | if (mac->link_state >= MAC80211_LINKED) | ||
505 | dm_dig->cursta_cstate = DIG_STA_CONNECT; | ||
506 | else | ||
507 | dm_dig->cursta_cstate = DIG_STA_DISCONNECT; | ||
508 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || | ||
509 | rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) | ||
510 | dm_dig->cursta_cstate = DIG_STA_DISCONNECT; | ||
511 | |||
512 | dm_dig_max = DM_DIG_MAX; | ||
513 | dm_dig_min = DM_DIG_MIN; | ||
514 | dig_maxofmin = DM_DIG_MAX_AP; | ||
515 | dig_min = dm_dig->dig_min_0; | ||
516 | bfirstconnect = ((mac->link_state >= MAC80211_LINKED) ? true : false) && | ||
517 | (dm_dig->media_connect_0 == false); | ||
518 | |||
519 | dm_dig->rssi_val_min = | ||
520 | rtl88e_dm_initial_gain_min_pwdb(hw); | ||
521 | |||
522 | if (mac->link_state >= MAC80211_LINKED) { | ||
523 | if ((dm_dig->rssi_val_min + 20) > dm_dig_max) | ||
524 | dm_dig->rx_gain_max = dm_dig_max; | ||
525 | else if ((dm_dig->rssi_val_min + 20) < dm_dig_min) | ||
526 | dm_dig->rx_gain_max = dm_dig_min; | ||
527 | else | ||
528 | dm_dig->rx_gain_max = dm_dig->rssi_val_min + 20; | ||
529 | |||
530 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { | ||
531 | dig_min = dm_dig->antdiv_rssi_max; | ||
532 | } else { | ||
533 | if (dm_dig->rssi_val_min < dm_dig_min) | ||
534 | dig_min = dm_dig_min; | ||
535 | else if (dm_dig->rssi_val_min < dig_maxofmin) | ||
536 | dig_min = dig_maxofmin; | ||
537 | else | ||
538 | dig_min = dm_dig->rssi_val_min; | ||
539 | } | ||
540 | } else { | ||
541 | dm_dig->rx_gain_max = dm_dig_max; | ||
542 | dig_min = dm_dig_min; | ||
543 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n"); | ||
544 | } | ||
545 | |||
546 | if (rtlpriv->falsealm_cnt.cnt_all > 10000) { | ||
547 | dm_dig->large_fa_hit++; | ||
548 | if (dm_dig->forbidden_igi < current_igi) { | ||
549 | dm_dig->forbidden_igi = current_igi; | ||
550 | dm_dig->large_fa_hit = 1; | ||
551 | } | ||
552 | |||
553 | if (dm_dig->large_fa_hit >= 3) { | ||
554 | if ((dm_dig->forbidden_igi + 1) > dm_dig->rx_gain_max) | ||
555 | dm_dig->rx_gain_min = dm_dig->rx_gain_max; | ||
556 | else | ||
557 | dm_dig->rx_gain_min = dm_dig->forbidden_igi + 1; | ||
558 | dm_dig->recover_cnt = 3600; | ||
559 | } | ||
560 | } else { | ||
561 | if (dm_dig->recover_cnt != 0) { | ||
562 | dm_dig->recover_cnt--; | ||
563 | } else { | ||
564 | if (dm_dig->large_fa_hit == 0) { | ||
565 | if ((dm_dig->forbidden_igi - 1) < dig_min) { | ||
566 | dm_dig->forbidden_igi = dig_min; | ||
567 | dm_dig->rx_gain_min = dig_min; | ||
568 | } else { | ||
569 | dm_dig->forbidden_igi--; | ||
570 | dm_dig->rx_gain_min = | ||
571 | dm_dig->forbidden_igi + 1; | ||
572 | } | ||
573 | } else if (dm_dig->large_fa_hit == 3) { | ||
574 | dm_dig->large_fa_hit = 0; | ||
575 | } | ||
576 | } | ||
577 | } | ||
578 | |||
579 | if (dm_dig->cursta_cstate == DIG_STA_CONNECT) { | ||
580 | if (bfirstconnect) { | ||
581 | current_igi = dm_dig->rssi_val_min; | ||
582 | } else { | ||
583 | if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) | ||
584 | current_igi += 2; | ||
585 | else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) | ||
586 | current_igi++; | ||
587 | else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) | ||
588 | current_igi--; | ||
589 | } | ||
590 | } else { | ||
591 | if (rtlpriv->falsealm_cnt.cnt_all > 10000) | ||
592 | current_igi += 2; | ||
593 | else if (rtlpriv->falsealm_cnt.cnt_all > 8000) | ||
594 | current_igi++; | ||
595 | else if (rtlpriv->falsealm_cnt.cnt_all < 500) | ||
596 | current_igi--; | ||
597 | } | ||
598 | |||
599 | if (current_igi > DM_DIG_FA_UPPER) | ||
600 | current_igi = DM_DIG_FA_UPPER; | ||
601 | else if (current_igi < DM_DIG_FA_LOWER) | ||
602 | current_igi = DM_DIG_FA_LOWER; | ||
603 | |||
604 | if (rtlpriv->falsealm_cnt.cnt_all > 10000) | ||
605 | current_igi = DM_DIG_FA_UPPER; | ||
606 | |||
607 | dm_dig->cur_igvalue = current_igi; | ||
608 | rtl88e_dm_write_dig(hw); | ||
609 | dm_dig->media_connect_0 = ((mac->link_state >= MAC80211_LINKED) ? | ||
610 | true : false); | ||
611 | dm_dig->dig_min_0 = dig_min; | ||
612 | |||
613 | rtl88e_dm_cck_packet_detection_thresh(hw); | ||
614 | } | ||
615 | |||
616 | static void rtl88e_dm_init_dynamic_txpower(struct ieee80211_hw *hw) | ||
617 | { | ||
618 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
619 | |||
620 | rtlpriv->dm.dynamic_txpower_enable = false; | ||
621 | |||
622 | rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
623 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
624 | } | ||
625 | |||
626 | static void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) | ||
627 | { | ||
628 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
629 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
630 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
631 | long undec_sm_pwdb; | ||
632 | |||
633 | if (!rtlpriv->dm.dynamic_txpower_enable) | ||
634 | return; | ||
635 | |||
636 | if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { | ||
637 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
638 | return; | ||
639 | } | ||
640 | |||
641 | if ((mac->link_state < MAC80211_LINKED) && | ||
642 | (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { | ||
643 | RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, | ||
644 | "Not connected\n"); | ||
645 | |||
646 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
647 | |||
648 | rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
649 | return; | ||
650 | } | ||
651 | |||
652 | if (mac->link_state >= MAC80211_LINKED) { | ||
653 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
654 | undec_sm_pwdb = | ||
655 | rtlpriv->dm.entry_min_undec_sm_pwdb; | ||
656 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
657 | "AP Client PWDB = 0x%lx\n", | ||
658 | undec_sm_pwdb); | ||
659 | } else { | ||
660 | undec_sm_pwdb = | ||
661 | rtlpriv->dm.undec_sm_pwdb; | ||
662 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
663 | "STA Default Port PWDB = 0x%lx\n", | ||
664 | undec_sm_pwdb); | ||
665 | } | ||
666 | } else { | ||
667 | undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | ||
668 | |||
669 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
670 | "AP Ext Port PWDB = 0x%lx\n", undec_sm_pwdb); | ||
671 | } | ||
672 | |||
673 | if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { | ||
674 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; | ||
675 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
676 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x0)\n"); | ||
677 | } else if ((undec_sm_pwdb < | ||
678 | (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && | ||
679 | (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { | ||
680 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; | ||
681 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
682 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x10)\n"); | ||
683 | } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { | ||
684 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
685 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
686 | "TXHIGHPWRLEVEL_NORMAL\n"); | ||
687 | } | ||
688 | |||
689 | if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { | ||
690 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
691 | "PHY_SetTxPowerLevel8192S() Channel = %d\n", | ||
692 | rtlphy->current_channel); | ||
693 | rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel); | ||
694 | } | ||
695 | |||
696 | rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; | ||
697 | } | ||
698 | |||
699 | void rtl88e_dm_write_dig(struct ieee80211_hw *hw) | ||
700 | { | ||
701 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
702 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
703 | |||
704 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, | ||
705 | "cur_igvalue = 0x%x, " | ||
706 | "pre_igvalue = 0x%x, back_val = %d\n", | ||
707 | dm_dig->cur_igvalue, dm_dig->pre_igvalue, | ||
708 | dm_dig->back_val); | ||
709 | |||
710 | if (dm_dig->cur_igvalue > 0x3f) | ||
711 | dm_dig->cur_igvalue = 0x3f; | ||
712 | if (dm_dig->pre_igvalue != dm_dig->cur_igvalue) { | ||
713 | rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, | ||
714 | dm_dig->cur_igvalue); | ||
715 | |||
716 | dm_dig->pre_igvalue = dm_dig->cur_igvalue; | ||
717 | } | ||
718 | } | ||
719 | |||
720 | static void rtl88e_dm_pwdb_monitor(struct ieee80211_hw *hw) | ||
721 | { | ||
722 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
723 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
724 | struct rtl_sta_info *drv_priv; | ||
725 | static u64 last_txok; | ||
726 | static u64 last_rx; | ||
727 | long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff; | ||
728 | |||
729 | if (rtlhal->oem_id == RT_CID_819x_HP) { | ||
730 | u64 cur_txok_cnt = 0; | ||
731 | u64 cur_rxok_cnt = 0; | ||
732 | cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok; | ||
733 | cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rx; | ||
734 | last_txok = cur_txok_cnt; | ||
735 | last_rx = cur_rxok_cnt; | ||
736 | |||
737 | if (cur_rxok_cnt > (cur_txok_cnt * 6)) | ||
738 | rtl_write_dword(rtlpriv, REG_ARFR0, 0x8f015); | ||
739 | else | ||
740 | rtl_write_dword(rtlpriv, REG_ARFR0, 0xff015); | ||
741 | } | ||
742 | |||
743 | /* AP & ADHOC & MESH */ | ||
744 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
745 | list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { | ||
746 | if (drv_priv->rssi_stat.undec_sm_pwdb < tmp_entry_min_pwdb) | ||
747 | tmp_entry_min_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; | ||
748 | if (drv_priv->rssi_stat.undec_sm_pwdb > tmp_entry_max_pwdb) | ||
749 | tmp_entry_max_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; | ||
750 | } | ||
751 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
752 | |||
753 | /* If associated entry is found */ | ||
754 | if (tmp_entry_max_pwdb != 0) { | ||
755 | rtlpriv->dm.entry_max_undec_sm_pwdb = tmp_entry_max_pwdb; | ||
756 | RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMaxPWDB = 0x%lx(%ld)\n", | ||
757 | tmp_entry_max_pwdb, tmp_entry_max_pwdb); | ||
758 | } else { | ||
759 | rtlpriv->dm.entry_max_undec_sm_pwdb = 0; | ||
760 | } | ||
761 | /* If associated entry is found */ | ||
762 | if (tmp_entry_min_pwdb != 0xff) { | ||
763 | rtlpriv->dm.entry_min_undec_sm_pwdb = tmp_entry_min_pwdb; | ||
764 | RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMinPWDB = 0x%lx(%ld)\n", | ||
765 | tmp_entry_min_pwdb, tmp_entry_min_pwdb); | ||
766 | } else { | ||
767 | rtlpriv->dm.entry_min_undec_sm_pwdb = 0; | ||
768 | } | ||
769 | /* Indicate Rx signal strength to FW. */ | ||
770 | if (!rtlpriv->dm.useramask) | ||
771 | rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb); | ||
772 | } | ||
773 | |||
774 | void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw) | ||
775 | { | ||
776 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
777 | |||
778 | rtlpriv->dm.current_turbo_edca = false; | ||
779 | rtlpriv->dm.is_any_nonbepkts = false; | ||
780 | rtlpriv->dm.is_cur_rdlstate = false; | ||
781 | } | ||
782 | |||
783 | static void rtl88e_dm_check_edca_turbo(struct ieee80211_hw *hw) | ||
784 | { | ||
785 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
786 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); | ||
787 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
788 | static u64 last_txok_cnt; | ||
789 | static u64 last_rxok_cnt; | ||
790 | static u32 last_bt_edca_ul; | ||
791 | static u32 last_bt_edca_dl; | ||
792 | u64 cur_txok_cnt = 0; | ||
793 | u64 cur_rxok_cnt = 0; | ||
794 | u32 edca_be_ul = 0x5ea42b; | ||
795 | u32 edca_be_dl = 0x5ea42b; | ||
796 | bool change_edca = false; | ||
797 | |||
798 | if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) || | ||
799 | (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) { | ||
800 | rtlpriv->dm.current_turbo_edca = false; | ||
801 | last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul; | ||
802 | last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl; | ||
803 | } | ||
804 | |||
805 | if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) { | ||
806 | edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul; | ||
807 | change_edca = true; | ||
808 | } | ||
809 | |||
810 | if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) { | ||
811 | edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl; | ||
812 | change_edca = true; | ||
813 | } | ||
814 | |||
815 | if (mac->link_state != MAC80211_LINKED) { | ||
816 | rtlpriv->dm.current_turbo_edca = false; | ||
817 | return; | ||
818 | } | ||
819 | |||
820 | if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) { | ||
821 | if (!(edca_be_ul & 0xffff0000)) | ||
822 | edca_be_ul |= 0x005e0000; | ||
823 | |||
824 | if (!(edca_be_dl & 0xffff0000)) | ||
825 | edca_be_dl |= 0x005e0000; | ||
826 | } | ||
827 | |||
828 | if ((change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && | ||
829 | (!rtlpriv->dm.disable_framebursting))) { | ||
830 | cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; | ||
831 | cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; | ||
832 | |||
833 | if (cur_rxok_cnt > 4 * cur_txok_cnt) { | ||
834 | if (!rtlpriv->dm.is_cur_rdlstate || | ||
835 | !rtlpriv->dm.current_turbo_edca) { | ||
836 | rtl_write_dword(rtlpriv, | ||
837 | REG_EDCA_BE_PARAM, | ||
838 | edca_be_dl); | ||
839 | rtlpriv->dm.is_cur_rdlstate = true; | ||
840 | } | ||
841 | } else { | ||
842 | if (rtlpriv->dm.is_cur_rdlstate || | ||
843 | !rtlpriv->dm.current_turbo_edca) { | ||
844 | rtl_write_dword(rtlpriv, | ||
845 | REG_EDCA_BE_PARAM, | ||
846 | edca_be_ul); | ||
847 | rtlpriv->dm.is_cur_rdlstate = false; | ||
848 | } | ||
849 | } | ||
850 | rtlpriv->dm.current_turbo_edca = true; | ||
851 | } else { | ||
852 | if (rtlpriv->dm.current_turbo_edca) { | ||
853 | u8 tmp = AC0_BE; | ||
854 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
855 | HW_VAR_AC_PARAM, | ||
856 | (u8 *)(&tmp)); | ||
857 | rtlpriv->dm.current_turbo_edca = false; | ||
858 | } | ||
859 | } | ||
860 | |||
861 | rtlpriv->dm.is_any_nonbepkts = false; | ||
862 | last_txok_cnt = rtlpriv->stats.txbytesunicast; | ||
863 | last_rxok_cnt = rtlpriv->stats.rxbytesunicast; | ||
864 | } | ||
865 | |||
866 | static void rtl88e_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw | ||
867 | *hw) | ||
868 | { | ||
869 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
870 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
871 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
872 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
873 | u8 thermalvalue = 0, delta, delta_lck, delta_iqk, off; | ||
874 | u8 th_avg_cnt = 0; | ||
875 | u32 thermalvalue_avg = 0; | ||
876 | long ele_d, temp_cck; | ||
877 | char ofdm_index[2], cck_index = 0, ofdm_old[2] = {0, 0}, cck_old = 0; | ||
878 | int i = 0; | ||
879 | bool is2t = false; | ||
880 | |||
881 | u8 ofdm_min_index = 6, rf = (is2t) ? 2 : 1; | ||
882 | u8 index_for_channel; | ||
883 | enum _dec_inc {dec, power_inc}; | ||
884 | |||
885 | /* 0.1 the following TWO tables decide the final index of | ||
886 | * OFDM/CCK swing table | ||
887 | */ | ||
888 | char del_tbl_idx[2][15] = { | ||
889 | {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11}, | ||
890 | {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10} | ||
891 | }; | ||
892 | u8 thermal_threshold[2][15] = { | ||
893 | {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27}, | ||
894 | {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25} | ||
895 | }; | ||
896 | |||
897 | /*Initilization (7 steps in total) */ | ||
898 | rtlpriv->dm.txpower_trackinginit = true; | ||
899 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
900 | "rtl88e_dm_txpower_tracking_callback_thermalmeter\n"); | ||
901 | |||
902 | thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xfc00); | ||
903 | if (!thermalvalue) | ||
904 | return; | ||
905 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
906 | "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", | ||
907 | thermalvalue, rtlpriv->dm.thermalvalue, | ||
908 | rtlefuse->eeprom_thermalmeter); | ||
909 | |||
910 | /*1. Query OFDM Default Setting: Path A*/ | ||
911 | ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD) & MASKOFDM_D; | ||
912 | for (i = 0; i < OFDM_TABLE_LENGTH; i++) { | ||
913 | if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { | ||
914 | ofdm_old[0] = (u8) i; | ||
915 | rtldm->swing_idx_ofdm_base = (u8)i; | ||
916 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
917 | "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n", | ||
918 | ROFDM0_XATXIQIMBAL, | ||
919 | ele_d, ofdm_old[0]); | ||
920 | break; | ||
921 | } | ||
922 | } | ||
923 | |||
924 | if (is2t) { | ||
925 | ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBAL, | ||
926 | MASKDWORD) & MASKOFDM_D; | ||
927 | for (i = 0; i < OFDM_TABLE_LENGTH; i++) { | ||
928 | if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { | ||
929 | ofdm_old[1] = (u8)i; | ||
930 | |||
931 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, | ||
932 | DBG_LOUD, | ||
933 | "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n", | ||
934 | ROFDM0_XBTXIQIMBAL, ele_d, | ||
935 | ofdm_old[1]); | ||
936 | break; | ||
937 | } | ||
938 | } | ||
939 | } | ||
940 | /*2.Query CCK default setting From 0xa24*/ | ||
941 | temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK; | ||
942 | for (i = 0; i < CCK_TABLE_LENGTH; i++) { | ||
943 | if (rtlpriv->dm.cck_inch14) { | ||
944 | if (memcmp(&temp_cck, &cck_tbl_ch14[i][2], 4) == 0) { | ||
945 | cck_old = (u8)i; | ||
946 | rtldm->swing_idx_cck_base = (u8)i; | ||
947 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
948 | "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch 14 %d\n", | ||
949 | RCCK0_TXFILTER2, temp_cck, cck_old, | ||
950 | rtlpriv->dm.cck_inch14); | ||
951 | break; | ||
952 | } | ||
953 | } else { | ||
954 | if (memcmp(&temp_cck, &cck_tbl_ch1_13[i][2], 4) == 0) { | ||
955 | cck_old = (u8)i; | ||
956 | rtldm->swing_idx_cck_base = (u8)i; | ||
957 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
958 | "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch14 %d\n", | ||
959 | RCCK0_TXFILTER2, temp_cck, cck_old, | ||
960 | rtlpriv->dm.cck_inch14); | ||
961 | break; | ||
962 | } | ||
963 | } | ||
964 | } | ||
965 | |||
966 | /*3 Initialize ThermalValues of RFCalibrateInfo*/ | ||
967 | if (!rtldm->thermalvalue) { | ||
968 | rtlpriv->dm.thermalvalue = rtlefuse->eeprom_thermalmeter; | ||
969 | rtlpriv->dm.thermalvalue_lck = thermalvalue; | ||
970 | rtlpriv->dm.thermalvalue_iqk = thermalvalue; | ||
971 | for (i = 0; i < rf; i++) | ||
972 | rtlpriv->dm.ofdm_index[i] = ofdm_old[i]; | ||
973 | rtlpriv->dm.cck_index = cck_old; | ||
974 | } | ||
975 | |||
976 | /*4 Calculate average thermal meter*/ | ||
977 | rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue; | ||
978 | rtldm->thermalvalue_avg_index++; | ||
979 | if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_88E) | ||
980 | rtldm->thermalvalue_avg_index = 0; | ||
981 | |||
982 | for (i = 0; i < AVG_THERMAL_NUM_88E; i++) { | ||
983 | if (rtldm->thermalvalue_avg[i]) { | ||
984 | thermalvalue_avg += rtldm->thermalvalue_avg[i]; | ||
985 | th_avg_cnt++; | ||
986 | } | ||
987 | } | ||
988 | |||
989 | if (th_avg_cnt) | ||
990 | thermalvalue = (u8)(thermalvalue_avg / th_avg_cnt); | ||
991 | |||
992 | /* 5 Calculate delta, delta_LCK, delta_IQK.*/ | ||
993 | if (rtlhal->reloadtxpowerindex) { | ||
994 | delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? | ||
995 | (thermalvalue - rtlefuse->eeprom_thermalmeter) : | ||
996 | (rtlefuse->eeprom_thermalmeter - thermalvalue); | ||
997 | rtlhal->reloadtxpowerindex = false; | ||
998 | rtlpriv->dm.done_txpower = false; | ||
999 | } else if (rtlpriv->dm.done_txpower) { | ||
1000 | delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? | ||
1001 | (thermalvalue - rtlpriv->dm.thermalvalue) : | ||
1002 | (rtlpriv->dm.thermalvalue - thermalvalue); | ||
1003 | } else { | ||
1004 | delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? | ||
1005 | (thermalvalue - rtlefuse->eeprom_thermalmeter) : | ||
1006 | (rtlefuse->eeprom_thermalmeter - thermalvalue); | ||
1007 | } | ||
1008 | delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? | ||
1009 | (thermalvalue - rtlpriv->dm.thermalvalue_lck) : | ||
1010 | (rtlpriv->dm.thermalvalue_lck - thermalvalue); | ||
1011 | delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? | ||
1012 | (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : | ||
1013 | (rtlpriv->dm.thermalvalue_iqk - thermalvalue); | ||
1014 | |||
1015 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
1016 | "Readback Thermal Meter = 0x%x pre thermal meter 0x%x " | ||
1017 | "eeprom_thermalmeter 0x%x delta 0x%x " | ||
1018 | "delta_lck 0x%x delta_iqk 0x%x\n", | ||
1019 | thermalvalue, rtlpriv->dm.thermalvalue, | ||
1020 | rtlefuse->eeprom_thermalmeter, delta, delta_lck, | ||
1021 | delta_iqk); | ||
1022 | /* 6 If necessary, do LCK.*/ | ||
1023 | if (delta_lck >= 8) { | ||
1024 | rtlpriv->dm.thermalvalue_lck = thermalvalue; | ||
1025 | rtl88e_phy_lc_calibrate(hw); | ||
1026 | } | ||
1027 | |||
1028 | /* 7 If necessary, move the index of swing table to adjust Tx power. */ | ||
1029 | if (delta > 0 && rtlpriv->dm.txpower_track_control) { | ||
1030 | delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? | ||
1031 | (thermalvalue - rtlefuse->eeprom_thermalmeter) : | ||
1032 | (rtlefuse->eeprom_thermalmeter - thermalvalue); | ||
1033 | |||
1034 | /* 7.1 Get the final CCK_index and OFDM_index for each | ||
1035 | * swing table. | ||
1036 | */ | ||
1037 | if (thermalvalue > rtlefuse->eeprom_thermalmeter) { | ||
1038 | CAL_SWING_OFF(off, power_inc, IDX_MAP, delta); | ||
1039 | for (i = 0; i < rf; i++) | ||
1040 | ofdm_index[i] = rtldm->ofdm_index[i] + | ||
1041 | del_tbl_idx[power_inc][off]; | ||
1042 | cck_index = rtldm->cck_index + | ||
1043 | del_tbl_idx[power_inc][off]; | ||
1044 | } else { | ||
1045 | CAL_SWING_OFF(off, dec, IDX_MAP, delta); | ||
1046 | for (i = 0; i < rf; i++) | ||
1047 | ofdm_index[i] = rtldm->ofdm_index[i] + | ||
1048 | del_tbl_idx[dec][off]; | ||
1049 | cck_index = rtldm->cck_index + del_tbl_idx[dec][off]; | ||
1050 | } | ||
1051 | |||
1052 | /* 7.2 Handle boundary conditions of index.*/ | ||
1053 | for (i = 0; i < rf; i++) { | ||
1054 | if (ofdm_index[i] > OFDM_TABLE_SIZE-1) | ||
1055 | ofdm_index[i] = OFDM_TABLE_SIZE-1; | ||
1056 | else if (rtldm->ofdm_index[i] < ofdm_min_index) | ||
1057 | ofdm_index[i] = ofdm_min_index; | ||
1058 | } | ||
1059 | |||
1060 | if (cck_index > CCK_TABLE_SIZE - 1) | ||
1061 | cck_index = CCK_TABLE_SIZE - 1; | ||
1062 | else if (cck_index < 0) | ||
1063 | cck_index = 0; | ||
1064 | |||
1065 | /*7.3Configure the Swing Table to adjust Tx Power.*/ | ||
1066 | if (rtlpriv->dm.txpower_track_control) { | ||
1067 | rtldm->done_txpower = true; | ||
1068 | rtldm->swing_idx_ofdm[RF90_PATH_A] = | ||
1069 | (u8)ofdm_index[RF90_PATH_A]; | ||
1070 | if (is2t) | ||
1071 | rtldm->swing_idx_ofdm[RF90_PATH_B] = | ||
1072 | (u8)ofdm_index[RF90_PATH_B]; | ||
1073 | rtldm->swing_idx_cck = cck_index; | ||
1074 | if (rtldm->swing_idx_ofdm_cur != | ||
1075 | rtldm->swing_idx_ofdm[0]) { | ||
1076 | rtldm->swing_idx_ofdm_cur = | ||
1077 | rtldm->swing_idx_ofdm[0]; | ||
1078 | rtldm->swing_flag_ofdm = true; | ||
1079 | } | ||
1080 | |||
1081 | if (rtldm->swing_idx_cck != rtldm->swing_idx_cck) { | ||
1082 | rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck; | ||
1083 | rtldm->swing_flag_cck = true; | ||
1084 | } | ||
1085 | |||
1086 | rtl88e_chk_tx_track(hw, TXAGC, 0, 0); | ||
1087 | |||
1088 | if (is2t) | ||
1089 | rtl88e_chk_tx_track(hw, BBSWING, | ||
1090 | RF90_PATH_B, | ||
1091 | index_for_channel); | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | if (delta_iqk >= 8) { | ||
1096 | rtlpriv->dm.thermalvalue_iqk = thermalvalue; | ||
1097 | rtl88e_phy_iq_calibrate(hw, false); | ||
1098 | } | ||
1099 | |||
1100 | if (rtldm->txpower_track_control) | ||
1101 | rtldm->thermalvalue = thermalvalue; | ||
1102 | rtldm->txpowercount = 0; | ||
1103 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n"); | ||
1104 | } | ||
1105 | |||
1106 | static void rtl88e_dm_init_txpower_tracking(struct ieee80211_hw *hw) | ||
1107 | { | ||
1108 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1109 | |||
1110 | rtlpriv->dm.txpower_tracking = true; | ||
1111 | rtlpriv->dm.txpower_trackinginit = false; | ||
1112 | rtlpriv->dm.txpowercount = 0; | ||
1113 | rtlpriv->dm.txpower_track_control = true; | ||
1114 | |||
1115 | rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] = 12; | ||
1116 | rtlpriv->dm.swing_idx_ofdm_cur = 12; | ||
1117 | rtlpriv->dm.swing_flag_ofdm = false; | ||
1118 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
1119 | " rtlpriv->dm.txpower_tracking = %d\n", | ||
1120 | rtlpriv->dm.txpower_tracking); | ||
1121 | } | ||
1122 | |||
1123 | void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw) | ||
1124 | { | ||
1125 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1126 | static u8 tm_trigger; | ||
1127 | |||
1128 | if (!rtlpriv->dm.txpower_tracking) | ||
1129 | return; | ||
1130 | |||
1131 | if (!tm_trigger) { | ||
1132 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17)|BIT(16), | ||
1133 | 0x03); | ||
1134 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
1135 | "Trigger 88E Thermal Meter!!\n"); | ||
1136 | tm_trigger = 1; | ||
1137 | return; | ||
1138 | } else { | ||
1139 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
1140 | "Schedule TxPowerTracking !!\n"); | ||
1141 | rtl88e_dm_txpower_tracking_callback_thermalmeter(hw); | ||
1142 | tm_trigger = 0; | ||
1143 | } | ||
1144 | } | ||
1145 | |||
1146 | void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) | ||
1147 | { | ||
1148 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1149 | struct rate_adaptive *p_ra = &(rtlpriv->ra); | ||
1150 | |||
1151 | p_ra->ratr_state = DM_RATR_STA_INIT; | ||
1152 | p_ra->pre_ratr_state = DM_RATR_STA_INIT; | ||
1153 | |||
1154 | if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) | ||
1155 | rtlpriv->dm.useramask = true; | ||
1156 | else | ||
1157 | rtlpriv->dm.useramask = false; | ||
1158 | } | ||
1159 | |||
1160 | static void rtl88e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) | ||
1161 | { | ||
1162 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1163 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1164 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1165 | struct rate_adaptive *p_ra = &(rtlpriv->ra); | ||
1166 | struct ieee80211_sta *sta = NULL; | ||
1167 | u32 low_rssi, hi_rssi; | ||
1168 | |||
1169 | if (is_hal_stop(rtlhal)) { | ||
1170 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1171 | "driver is going to unload\n"); | ||
1172 | return; | ||
1173 | } | ||
1174 | |||
1175 | if (!rtlpriv->dm.useramask) { | ||
1176 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1177 | "driver does not control rate adaptive mask\n"); | ||
1178 | return; | ||
1179 | } | ||
1180 | |||
1181 | if (mac->link_state == MAC80211_LINKED && | ||
1182 | mac->opmode == NL80211_IFTYPE_STATION) { | ||
1183 | switch (p_ra->pre_ratr_state) { | ||
1184 | case DM_RATR_STA_HIGH: | ||
1185 | hi_rssi = 50; | ||
1186 | low_rssi = 20; | ||
1187 | break; | ||
1188 | case DM_RATR_STA_MIDDLE: | ||
1189 | hi_rssi = 55; | ||
1190 | low_rssi = 20; | ||
1191 | break; | ||
1192 | case DM_RATR_STA_LOW: | ||
1193 | hi_rssi = 50; | ||
1194 | low_rssi = 25; | ||
1195 | break; | ||
1196 | default: | ||
1197 | hi_rssi = 50; | ||
1198 | low_rssi = 20; | ||
1199 | break; | ||
1200 | } | ||
1201 | |||
1202 | if (rtlpriv->dm.undec_sm_pwdb > (long)hi_rssi) | ||
1203 | p_ra->ratr_state = DM_RATR_STA_HIGH; | ||
1204 | else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi) | ||
1205 | p_ra->ratr_state = DM_RATR_STA_MIDDLE; | ||
1206 | else | ||
1207 | p_ra->ratr_state = DM_RATR_STA_LOW; | ||
1208 | |||
1209 | if (p_ra->pre_ratr_state != p_ra->ratr_state) { | ||
1210 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1211 | "RSSI = %ld\n", | ||
1212 | rtlpriv->dm.undec_sm_pwdb); | ||
1213 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1214 | "RSSI_LEVEL = %d\n", p_ra->ratr_state); | ||
1215 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1216 | "PreState = %d, CurState = %d\n", | ||
1217 | p_ra->pre_ratr_state, p_ra->ratr_state); | ||
1218 | |||
1219 | rcu_read_lock(); | ||
1220 | sta = rtl_find_sta(hw, mac->bssid); | ||
1221 | if (sta) | ||
1222 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | ||
1223 | p_ra->ratr_state); | ||
1224 | rcu_read_unlock(); | ||
1225 | |||
1226 | p_ra->pre_ratr_state = p_ra->ratr_state; | ||
1227 | } | ||
1228 | } | ||
1229 | } | ||
1230 | |||
1231 | static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) | ||
1232 | { | ||
1233 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1234 | struct ps_t *dm_pstable = &rtlpriv->dm_pstable; | ||
1235 | |||
1236 | dm_pstable->pre_ccastate = CCA_MAX; | ||
1237 | dm_pstable->cur_ccasate = CCA_MAX; | ||
1238 | dm_pstable->pre_rfstate = RF_MAX; | ||
1239 | dm_pstable->cur_rfstate = RF_MAX; | ||
1240 | dm_pstable->rssi_val_min = 0; | ||
1241 | } | ||
1242 | |||
1243 | static void rtl88e_dm_update_rx_idle_ant(struct ieee80211_hw *hw, u8 ant) | ||
1244 | { | ||
1245 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1246 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1247 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1248 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1249 | u32 def_ant, opt_ant; | ||
1250 | |||
1251 | if (fat_tbl->rx_idle_ant != ant) { | ||
1252 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1253 | "need to update rx idle ant\n"); | ||
1254 | if (ant == MAIN_ANT) { | ||
1255 | def_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ? | ||
1256 | MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; | ||
1257 | opt_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ? | ||
1258 | AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; | ||
1259 | } else { | ||
1260 | def_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ? | ||
1261 | AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; | ||
1262 | opt_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ? | ||
1263 | MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; | ||
1264 | } | ||
1265 | |||
1266 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { | ||
1267 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) | | ||
1268 | BIT(4) | BIT(3), def_ant); | ||
1269 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | | ||
1270 | BIT(7) | BIT(6), opt_ant); | ||
1271 | rtl_set_bbreg(hw, DM_REG_ANTSEL_CTRL_11N, BIT(14) | | ||
1272 | BIT(13) | BIT(12), def_ant); | ||
1273 | rtl_set_bbreg(hw, DM_REG_RESP_TX_11N, BIT(6) | BIT(7), | ||
1274 | def_ant); | ||
1275 | } else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) { | ||
1276 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) | | ||
1277 | BIT(4) | BIT(3), def_ant); | ||
1278 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | | ||
1279 | BIT(7) | BIT(6), opt_ant); | ||
1280 | } | ||
1281 | } | ||
1282 | fat_tbl->rx_idle_ant = ant; | ||
1283 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RxIdleAnt %s\n", | ||
1284 | ((ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT"))); | ||
1285 | } | ||
1286 | |||
1287 | static void rtl88e_dm_update_tx_ant(struct ieee80211_hw *hw, | ||
1288 | u8 ant, u32 mac_id) | ||
1289 | { | ||
1290 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1291 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1292 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1293 | u8 target_ant; | ||
1294 | |||
1295 | if (ant == MAIN_ANT) | ||
1296 | target_ant = MAIN_ANT_CG_TRX; | ||
1297 | else | ||
1298 | target_ant = AUX_ANT_CG_TRX; | ||
1299 | |||
1300 | fat_tbl->antsel_a[mac_id] = target_ant & BIT(0); | ||
1301 | fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1)) >> 1; | ||
1302 | fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2)) >> 2; | ||
1303 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "txfrominfo target ant %s\n", | ||
1304 | ((ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT"))); | ||
1305 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "antsel_tr_mux = 3'b%d%d%d\n", | ||
1306 | fat_tbl->antsel_c[mac_id], | ||
1307 | fat_tbl->antsel_b[mac_id], fat_tbl->antsel_a[mac_id]); | ||
1308 | } | ||
1309 | |||
1310 | static void rtl88e_dm_rx_hw_antena_div_init(struct ieee80211_hw *hw) | ||
1311 | { | ||
1312 | u32 value32; | ||
1313 | /*MAC Setting*/ | ||
1314 | value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); | ||
1315 | rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | | ||
1316 | (BIT(23) | BIT(25))); | ||
1317 | /*Pin Setting*/ | ||
1318 | rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); | ||
1319 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); | ||
1320 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 1); | ||
1321 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); | ||
1322 | /*OFDM Setting*/ | ||
1323 | rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); | ||
1324 | /*CCK Setting*/ | ||
1325 | rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1); | ||
1326 | rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); | ||
1327 | rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT); | ||
1328 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201); | ||
1329 | } | ||
1330 | |||
1331 | static void rtl88e_dm_trx_hw_antenna_div_init(struct ieee80211_hw *hw) | ||
1332 | { | ||
1333 | u32 value32; | ||
1334 | |||
1335 | /*MAC Setting*/ | ||
1336 | value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); | ||
1337 | rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | | ||
1338 | (BIT(23) | BIT(25))); | ||
1339 | /*Pin Setting*/ | ||
1340 | rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); | ||
1341 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); | ||
1342 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0); | ||
1343 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); | ||
1344 | /*OFDM Setting*/ | ||
1345 | rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); | ||
1346 | /*CCK Setting*/ | ||
1347 | rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1); | ||
1348 | rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); | ||
1349 | /*TX Setting*/ | ||
1350 | rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 0); | ||
1351 | rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT); | ||
1352 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201); | ||
1353 | } | ||
1354 | |||
1355 | static void rtl88e_dm_fast_training_init(struct ieee80211_hw *hw) | ||
1356 | { | ||
1357 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1358 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1359 | u32 ant_combo = 2; | ||
1360 | u32 value32, i; | ||
1361 | |||
1362 | for (i = 0; i < 6; i++) { | ||
1363 | fat_tbl->bssid[i] = 0; | ||
1364 | fat_tbl->ant_sum[i] = 0; | ||
1365 | fat_tbl->ant_cnt[i] = 0; | ||
1366 | fat_tbl->ant_ave[i] = 0; | ||
1367 | } | ||
1368 | fat_tbl->train_idx = 0; | ||
1369 | fat_tbl->fat_state = FAT_NORMAL_STATE; | ||
1370 | |||
1371 | /*MAC Setting*/ | ||
1372 | value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); | ||
1373 | rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | (BIT(23) | | ||
1374 | BIT(25))); | ||
1375 | value32 = rtl_get_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKDWORD); | ||
1376 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKDWORD, value32 | (BIT(16) | | ||
1377 | BIT(17))); | ||
1378 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKLWORD, 0); | ||
1379 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1, MASKDWORD, 0); | ||
1380 | |||
1381 | /*Pin Setting*/ | ||
1382 | rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); | ||
1383 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); | ||
1384 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0); | ||
1385 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); | ||
1386 | |||
1387 | /*OFDM Setting*/ | ||
1388 | rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); | ||
1389 | /*antenna mapping table*/ | ||
1390 | if (ant_combo == 2) { | ||
1391 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1); | ||
1392 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2); | ||
1393 | } else if (ant_combo == 7) { | ||
1394 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1); | ||
1395 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2); | ||
1396 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE2, 2); | ||
1397 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE3, 3); | ||
1398 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE0, 4); | ||
1399 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE1, 5); | ||
1400 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE2, 6); | ||
1401 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE3, 7); | ||
1402 | } | ||
1403 | |||
1404 | /*TX Setting*/ | ||
1405 | rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1); | ||
1406 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) | BIT(4) | BIT(3), 0); | ||
1407 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | BIT(7) | BIT(6), 1); | ||
1408 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(2) | BIT(1) | BIT(0), | ||
1409 | (ant_combo - 1)); | ||
1410 | |||
1411 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); | ||
1412 | } | ||
1413 | |||
1414 | static void rtl88e_dm_antenna_div_init(struct ieee80211_hw *hw) | ||
1415 | { | ||
1416 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1417 | |||
1418 | if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1419 | rtl88e_dm_rx_hw_antena_div_init(hw); | ||
1420 | else if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) | ||
1421 | rtl88e_dm_trx_hw_antenna_div_init(hw); | ||
1422 | else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) | ||
1423 | rtl88e_dm_fast_training_init(hw); | ||
1424 | } | ||
1425 | |||
1426 | void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, | ||
1427 | u8 *pdesc, u32 mac_id) | ||
1428 | { | ||
1429 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1430 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1431 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1432 | |||
1433 | if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || | ||
1434 | (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)) { | ||
1435 | SET_TX_DESC_ANTSEL_A(pdesc, fat_tbl->antsel_a[mac_id]); | ||
1436 | SET_TX_DESC_ANTSEL_B(pdesc, fat_tbl->antsel_b[mac_id]); | ||
1437 | SET_TX_DESC_ANTSEL_C(pdesc, fat_tbl->antsel_c[mac_id]); | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw, | ||
1442 | u8 antsel_tr_mux, u32 mac_id, u32 rx_pwdb_all) | ||
1443 | { | ||
1444 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1445 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1446 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1447 | |||
1448 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { | ||
1449 | if (antsel_tr_mux == MAIN_ANT_CG_TRX) { | ||
1450 | fat_tbl->main_ant_sum[mac_id] += rx_pwdb_all; | ||
1451 | fat_tbl->main_ant_cnt[mac_id]++; | ||
1452 | } else { | ||
1453 | fat_tbl->aux_ant_sum[mac_id] += rx_pwdb_all; | ||
1454 | fat_tbl->aux_ant_cnt[mac_id]++; | ||
1455 | } | ||
1456 | } else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) { | ||
1457 | if (antsel_tr_mux == MAIN_ANT_CGCS_RX) { | ||
1458 | fat_tbl->main_ant_sum[mac_id] += rx_pwdb_all; | ||
1459 | fat_tbl->main_ant_cnt[mac_id]++; | ||
1460 | } else { | ||
1461 | fat_tbl->aux_ant_sum[mac_id] += rx_pwdb_all; | ||
1462 | fat_tbl->aux_ant_cnt[mac_id]++; | ||
1463 | } | ||
1464 | } | ||
1465 | } | ||
1466 | |||
1467 | static void rtl88e_dm_hw_ant_div(struct ieee80211_hw *hw) | ||
1468 | { | ||
1469 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1470 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
1471 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1472 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1473 | struct rtl_sta_info *drv_priv; | ||
1474 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1475 | u32 i, min_rssi = 0xff, ant_div_max_rssi = 0, max_rssi = 0; | ||
1476 | u32 local_min_rssi, local_max_rssi; | ||
1477 | u32 main_rssi, aux_rssi; | ||
1478 | u8 rx_idle_ant = 0, target_ant = 7; | ||
1479 | |||
1480 | i = 0; | ||
1481 | main_rssi = (fat_tbl->main_ant_cnt[i] != 0) ? | ||
1482 | (fat_tbl->main_ant_sum[i] / | ||
1483 | fat_tbl->main_ant_cnt[i]) : 0; | ||
1484 | aux_rssi = (fat_tbl->aux_ant_cnt[i] != 0) ? | ||
1485 | (fat_tbl->aux_ant_sum[i] / fat_tbl->aux_ant_cnt[i]) : 0; | ||
1486 | target_ant = (main_rssi == aux_rssi) ? | ||
1487 | fat_tbl->rx_idle_ant : ((main_rssi >= aux_rssi) ? | ||
1488 | MAIN_ANT : AUX_ANT); | ||
1489 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1490 | "main_ant_sum %d main_ant_cnt %d\n", | ||
1491 | fat_tbl->main_ant_sum[i], fat_tbl->main_ant_cnt[i]); | ||
1492 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1493 | "aux_ant_sum %d aux_ant_cnt %d\n", | ||
1494 | fat_tbl->aux_ant_sum[i], | ||
1495 | fat_tbl->aux_ant_cnt[i]); | ||
1496 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1497 | "main_rssi %d aux_rssi%d\n", main_rssi, aux_rssi); | ||
1498 | local_max_rssi = (main_rssi > aux_rssi) ? main_rssi : aux_rssi; | ||
1499 | if ((local_max_rssi > ant_div_max_rssi) && (local_max_rssi < 40)) | ||
1500 | ant_div_max_rssi = local_max_rssi; | ||
1501 | if (local_max_rssi > max_rssi) | ||
1502 | max_rssi = local_max_rssi; | ||
1503 | |||
1504 | if ((fat_tbl->rx_idle_ant == MAIN_ANT) && (main_rssi == 0)) | ||
1505 | main_rssi = aux_rssi; | ||
1506 | else if ((fat_tbl->rx_idle_ant == AUX_ANT) && (aux_rssi == 0)) | ||
1507 | aux_rssi = main_rssi; | ||
1508 | |||
1509 | local_min_rssi = (main_rssi > aux_rssi) ? aux_rssi : main_rssi; | ||
1510 | if (local_min_rssi < min_rssi) { | ||
1511 | min_rssi = local_min_rssi; | ||
1512 | rx_idle_ant = target_ant; | ||
1513 | } | ||
1514 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) | ||
1515 | rtl88e_dm_update_tx_ant(hw, target_ant, i); | ||
1516 | |||
1517 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || | ||
1518 | rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) { | ||
1519 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
1520 | list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { | ||
1521 | i++; | ||
1522 | main_rssi = (fat_tbl->main_ant_cnt[i] != 0) ? | ||
1523 | (fat_tbl->main_ant_sum[i] / | ||
1524 | fat_tbl->main_ant_cnt[i]) : 0; | ||
1525 | aux_rssi = (fat_tbl->aux_ant_cnt[i] != 0) ? | ||
1526 | (fat_tbl->aux_ant_sum[i] / | ||
1527 | fat_tbl->aux_ant_cnt[i]) : 0; | ||
1528 | target_ant = (main_rssi == aux_rssi) ? | ||
1529 | fat_tbl->rx_idle_ant : ((main_rssi >= | ||
1530 | aux_rssi) ? MAIN_ANT : AUX_ANT); | ||
1531 | |||
1532 | |||
1533 | local_max_rssi = max_t(u32, main_rssi, aux_rssi); | ||
1534 | if ((local_max_rssi > ant_div_max_rssi) && | ||
1535 | (local_max_rssi < 40)) | ||
1536 | ant_div_max_rssi = local_max_rssi; | ||
1537 | if (local_max_rssi > max_rssi) | ||
1538 | max_rssi = local_max_rssi; | ||
1539 | |||
1540 | if ((fat_tbl->rx_idle_ant == MAIN_ANT) && !main_rssi) | ||
1541 | main_rssi = aux_rssi; | ||
1542 | else if ((fat_tbl->rx_idle_ant == AUX_ANT) && | ||
1543 | (aux_rssi == 0)) | ||
1544 | aux_rssi = main_rssi; | ||
1545 | |||
1546 | local_min_rssi = (main_rssi > aux_rssi) ? | ||
1547 | aux_rssi : main_rssi; | ||
1548 | if (local_min_rssi < min_rssi) { | ||
1549 | min_rssi = local_min_rssi; | ||
1550 | rx_idle_ant = target_ant; | ||
1551 | } | ||
1552 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) | ||
1553 | rtl88e_dm_update_tx_ant(hw, target_ant, i); | ||
1554 | } | ||
1555 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
1556 | } | ||
1557 | |||
1558 | for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { | ||
1559 | fat_tbl->main_ant_sum[i] = 0; | ||
1560 | fat_tbl->aux_ant_sum[i] = 0; | ||
1561 | fat_tbl->main_ant_cnt[i] = 0; | ||
1562 | fat_tbl->aux_ant_cnt[i] = 0; | ||
1563 | } | ||
1564 | |||
1565 | rtl88e_dm_update_rx_idle_ant(hw, rx_idle_ant); | ||
1566 | |||
1567 | dm_dig->antdiv_rssi_max = ant_div_max_rssi; | ||
1568 | dm_dig->rssi_max = max_rssi; | ||
1569 | } | ||
1570 | |||
1571 | static void rtl88e_set_next_mac_address_target(struct ieee80211_hw *hw) | ||
1572 | { | ||
1573 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1574 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1575 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1576 | struct rtl_sta_info *drv_priv; | ||
1577 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1578 | u32 value32, i, j = 0; | ||
1579 | |||
1580 | if (mac->link_state >= MAC80211_LINKED) { | ||
1581 | for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { | ||
1582 | if ((fat_tbl->train_idx + 1) == ASSOCIATE_ENTRY_NUM) | ||
1583 | fat_tbl->train_idx = 0; | ||
1584 | else | ||
1585 | fat_tbl->train_idx++; | ||
1586 | |||
1587 | if (fat_tbl->train_idx == 0) { | ||
1588 | value32 = (mac->mac_addr[5] << 8) | | ||
1589 | mac->mac_addr[4]; | ||
1590 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, | ||
1591 | MASKLWORD, value32); | ||
1592 | |||
1593 | value32 = (mac->mac_addr[3] << 24) | | ||
1594 | (mac->mac_addr[2] << 16) | | ||
1595 | (mac->mac_addr[1] << 8) | | ||
1596 | mac->mac_addr[0]; | ||
1597 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1, | ||
1598 | MASKDWORD, value32); | ||
1599 | break; | ||
1600 | } | ||
1601 | |||
1602 | if (rtlpriv->mac80211.opmode != | ||
1603 | NL80211_IFTYPE_STATION) { | ||
1604 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
1605 | list_for_each_entry(drv_priv, | ||
1606 | &rtlpriv->entry_list, | ||
1607 | list) { | ||
1608 | j++; | ||
1609 | if (j != fat_tbl->train_idx) | ||
1610 | continue; | ||
1611 | |||
1612 | value32 = (drv_priv->mac_addr[5] << 8) | | ||
1613 | drv_priv->mac_addr[4]; | ||
1614 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, | ||
1615 | MASKLWORD, value32); | ||
1616 | |||
1617 | value32 = (drv_priv->mac_addr[3]<<24) | | ||
1618 | (drv_priv->mac_addr[2]<<16) | | ||
1619 | (drv_priv->mac_addr[1]<<8) | | ||
1620 | drv_priv->mac_addr[0]; | ||
1621 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1, | ||
1622 | MASKDWORD, value32); | ||
1623 | break; | ||
1624 | } | ||
1625 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
1626 | /*find entry, break*/ | ||
1627 | if (j == fat_tbl->train_idx) | ||
1628 | break; | ||
1629 | } | ||
1630 | } | ||
1631 | } | ||
1632 | } | ||
1633 | |||
1634 | static void rtl88e_dm_fast_ant_training(struct ieee80211_hw *hw) | ||
1635 | { | ||
1636 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1637 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1638 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1639 | u32 i, max_rssi = 0; | ||
1640 | u8 target_ant = 2; | ||
1641 | bool bpkt_filter_match = false; | ||
1642 | |||
1643 | if (fat_tbl->fat_state == FAT_TRAINING_STATE) { | ||
1644 | for (i = 0; i < 7; i++) { | ||
1645 | if (fat_tbl->ant_cnt[i] == 0) { | ||
1646 | fat_tbl->ant_ave[i] = 0; | ||
1647 | } else { | ||
1648 | fat_tbl->ant_ave[i] = fat_tbl->ant_sum[i] / | ||
1649 | fat_tbl->ant_cnt[i]; | ||
1650 | bpkt_filter_match = true; | ||
1651 | } | ||
1652 | |||
1653 | if (fat_tbl->ant_ave[i] > max_rssi) { | ||
1654 | max_rssi = fat_tbl->ant_ave[i]; | ||
1655 | target_ant = (u8) i; | ||
1656 | } | ||
1657 | } | ||
1658 | |||
1659 | if (bpkt_filter_match == false) { | ||
1660 | rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, | ||
1661 | BIT(16), 0); | ||
1662 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); | ||
1663 | } else { | ||
1664 | rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, | ||
1665 | BIT(16), 0); | ||
1666 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | | ||
1667 | BIT(7) | BIT(6), target_ant); | ||
1668 | rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1); | ||
1669 | |||
1670 | fat_tbl->antsel_a[fat_tbl->train_idx] = | ||
1671 | target_ant & BIT(0); | ||
1672 | fat_tbl->antsel_b[fat_tbl->train_idx] = | ||
1673 | (target_ant & BIT(1)) >> 1; | ||
1674 | fat_tbl->antsel_c[fat_tbl->train_idx] = | ||
1675 | (target_ant & BIT(2)) >> 2; | ||
1676 | |||
1677 | if (target_ant == 0) | ||
1678 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); | ||
1679 | } | ||
1680 | |||
1681 | for (i = 0; i < 7; i++) { | ||
1682 | fat_tbl->ant_sum[i] = 0; | ||
1683 | fat_tbl->ant_cnt[i] = 0; | ||
1684 | } | ||
1685 | |||
1686 | fat_tbl->fat_state = FAT_NORMAL_STATE; | ||
1687 | return; | ||
1688 | } | ||
1689 | |||
1690 | if (fat_tbl->fat_state == FAT_NORMAL_STATE) { | ||
1691 | rtl88e_set_next_mac_address_target(hw); | ||
1692 | |||
1693 | fat_tbl->fat_state = FAT_TRAINING_STATE; | ||
1694 | rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, BIT(16), 1); | ||
1695 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); | ||
1696 | |||
1697 | mod_timer(&rtlpriv->works.fast_antenna_training_timer, | ||
1698 | jiffies + MSECS(RTL_WATCH_DOG_TIME)); | ||
1699 | } | ||
1700 | } | ||
1701 | |||
1702 | void rtl88e_dm_fast_antenna_training_callback(unsigned long data) | ||
1703 | { | ||
1704 | struct ieee80211_hw *hw = (struct ieee80211_hw *)data; | ||
1705 | |||
1706 | rtl88e_dm_fast_ant_training(hw); | ||
1707 | } | ||
1708 | |||
1709 | static void rtl88e_dm_antenna_diversity(struct ieee80211_hw *hw) | ||
1710 | { | ||
1711 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1712 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1713 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1714 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1715 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1716 | |||
1717 | if (mac->link_state < MAC80211_LINKED) { | ||
1718 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No Link\n"); | ||
1719 | if (fat_tbl->becomelinked == true) { | ||
1720 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, | ||
1721 | "need to turn off HW AntDiv\n"); | ||
1722 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); | ||
1723 | rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N, | ||
1724 | BIT(15), 0); | ||
1725 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) | ||
1726 | rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, | ||
1727 | BIT(21), 0); | ||
1728 | fat_tbl->becomelinked = | ||
1729 | (mac->link_state == MAC80211_LINKED) ? true : false; | ||
1730 | } | ||
1731 | return; | ||
1732 | } else { | ||
1733 | if (fat_tbl->becomelinked == false) { | ||
1734 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, | ||
1735 | "Need to turn on HW AntDiv\n"); | ||
1736 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); | ||
1737 | rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N, | ||
1738 | BIT(15), 1); | ||
1739 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) | ||
1740 | rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, | ||
1741 | BIT(21), 1); | ||
1742 | fat_tbl->becomelinked = | ||
1743 | (mac->link_state >= MAC80211_LINKED) ? true : false; | ||
1744 | } | ||
1745 | } | ||
1746 | |||
1747 | if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || | ||
1748 | (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)) | ||
1749 | rtl88e_dm_hw_ant_div(hw); | ||
1750 | else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) | ||
1751 | rtl88e_dm_fast_ant_training(hw); | ||
1752 | } | ||
1753 | |||
1754 | void rtl88e_dm_init(struct ieee80211_hw *hw) | ||
1755 | { | ||
1756 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1757 | |||
1758 | rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; | ||
1759 | rtl88e_dm_diginit(hw); | ||
1760 | rtl88e_dm_init_dynamic_txpower(hw); | ||
1761 | rtl88e_dm_init_edca_turbo(hw); | ||
1762 | rtl88e_dm_init_rate_adaptive_mask(hw); | ||
1763 | rtl88e_dm_init_txpower_tracking(hw); | ||
1764 | rtl92c_dm_init_dynamic_bb_powersaving(hw); | ||
1765 | rtl88e_dm_antenna_div_init(hw); | ||
1766 | } | ||
1767 | |||
1768 | void rtl88e_dm_watchdog(struct ieee80211_hw *hw) | ||
1769 | { | ||
1770 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1771 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1772 | bool fw_current_inpsmode = false; | ||
1773 | bool fw_ps_awake = true; | ||
1774 | |||
1775 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
1776 | (u8 *)(&fw_current_inpsmode)); | ||
1777 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, | ||
1778 | (u8 *)(&fw_ps_awake)); | ||
1779 | if (ppsc->p2p_ps_info.p2p_ps_mode) | ||
1780 | fw_ps_awake = false; | ||
1781 | |||
1782 | if ((ppsc->rfpwr_state == ERFON) && | ||
1783 | ((!fw_current_inpsmode) && fw_ps_awake) && | ||
1784 | (!ppsc->rfchange_inprogress)) { | ||
1785 | rtl88e_dm_pwdb_monitor(hw); | ||
1786 | rtl88e_dm_dig(hw); | ||
1787 | rtl88e_dm_false_alarm_counter_statistics(hw); | ||
1788 | rtl92c_dm_dynamic_txpower(hw); | ||
1789 | rtl88e_dm_check_txpower_tracking(hw); | ||
1790 | rtl88e_dm_refresh_rate_adaptive_mask(hw); | ||
1791 | rtl88e_dm_check_edca_turbo(hw); | ||
1792 | rtl88e_dm_antenna_diversity(hw); | ||
1793 | } | ||
1794 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h new file mode 100644 index 000000000000..0e07f72ea158 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h | |||
@@ -0,0 +1,326 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL88E_DM_H__ | ||
31 | #define __RTL88E_DM_H__ | ||
32 | |||
33 | #define MAIN_ANT 0 | ||
34 | #define AUX_ANT 1 | ||
35 | #define MAIN_ANT_CG_TRX 1 | ||
36 | #define AUX_ANT_CG_TRX 0 | ||
37 | #define MAIN_ANT_CGCS_RX 0 | ||
38 | #define AUX_ANT_CGCS_RX 1 | ||
39 | |||
40 | /*RF REG LIST*/ | ||
41 | #define DM_REG_RF_MODE_11N 0x00 | ||
42 | #define DM_REG_RF_0B_11N 0x0B | ||
43 | #define DM_REG_CHNBW_11N 0x18 | ||
44 | #define DM_REG_T_METER_11N 0x24 | ||
45 | #define DM_REG_RF_25_11N 0x25 | ||
46 | #define DM_REG_RF_26_11N 0x26 | ||
47 | #define DM_REG_RF_27_11N 0x27 | ||
48 | #define DM_REG_RF_2B_11N 0x2B | ||
49 | #define DM_REG_RF_2C_11N 0x2C | ||
50 | #define DM_REG_RXRF_A3_11N 0x3C | ||
51 | #define DM_REG_T_METER_92D_11N 0x42 | ||
52 | #define DM_REG_T_METER_88E_11N 0x42 | ||
53 | |||
54 | /*BB REG LIST*/ | ||
55 | /*PAGE 8 */ | ||
56 | #define DM_REG_BB_CTRL_11N 0x800 | ||
57 | #define DM_REG_RF_PIN_11N 0x804 | ||
58 | #define DM_REG_PSD_CTRL_11N 0x808 | ||
59 | #define DM_REG_TX_ANT_CTRL_11N 0x80C | ||
60 | #define DM_REG_BB_PWR_SAV5_11N 0x818 | ||
61 | #define DM_REG_CCK_RPT_FORMAT_11N 0x824 | ||
62 | #define DM_REG_RX_DEFAULT_A_11N 0x858 | ||
63 | #define DM_REG_RX_DEFAULT_B_11N 0x85A | ||
64 | #define DM_REG_BB_PWR_SAV3_11N 0x85C | ||
65 | #define DM_REG_ANTSEL_CTRL_11N 0x860 | ||
66 | #define DM_REG_RX_ANT_CTRL_11N 0x864 | ||
67 | #define DM_REG_PIN_CTRL_11N 0x870 | ||
68 | #define DM_REG_BB_PWR_SAV1_11N 0x874 | ||
69 | #define DM_REG_ANTSEL_PATH_11N 0x878 | ||
70 | #define DM_REG_BB_3WIRE_11N 0x88C | ||
71 | #define DM_REG_SC_CNT_11N 0x8C4 | ||
72 | #define DM_REG_PSD_DATA_11N 0x8B4 | ||
73 | /*PAGE 9*/ | ||
74 | #define DM_REG_ANT_MAPPING1_11N 0x914 | ||
75 | #define DM_REG_ANT_MAPPING2_11N 0x918 | ||
76 | /*PAGE A*/ | ||
77 | #define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00 | ||
78 | #define DM_REG_CCK_CCA_11N 0xA0A | ||
79 | #define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C | ||
80 | #define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10 | ||
81 | #define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14 | ||
82 | #define DM_REG_CCK_FILTER_PARA1_11N 0xA22 | ||
83 | #define DM_REG_CCK_FILTER_PARA2_11N 0xA23 | ||
84 | #define DM_REG_CCK_FILTER_PARA3_11N 0xA24 | ||
85 | #define DM_REG_CCK_FILTER_PARA4_11N 0xA25 | ||
86 | #define DM_REG_CCK_FILTER_PARA5_11N 0xA26 | ||
87 | #define DM_REG_CCK_FILTER_PARA6_11N 0xA27 | ||
88 | #define DM_REG_CCK_FILTER_PARA7_11N 0xA28 | ||
89 | #define DM_REG_CCK_FILTER_PARA8_11N 0xA29 | ||
90 | #define DM_REG_CCK_FA_RST_11N 0xA2C | ||
91 | #define DM_REG_CCK_FA_MSB_11N 0xA58 | ||
92 | #define DM_REG_CCK_FA_LSB_11N 0xA5C | ||
93 | #define DM_REG_CCK_CCA_CNT_11N 0xA60 | ||
94 | #define DM_REG_BB_PWR_SAV4_11N 0xA74 | ||
95 | /*PAGE B */ | ||
96 | #define DM_REG_LNA_SWITCH_11N 0xB2C | ||
97 | #define DM_REG_PATH_SWITCH_11N 0xB30 | ||
98 | #define DM_REG_RSSI_CTRL_11N 0xB38 | ||
99 | #define DM_REG_CONFIG_ANTA_11N 0xB68 | ||
100 | #define DM_REG_RSSI_BT_11N 0xB9C | ||
101 | /*PAGE C */ | ||
102 | #define DM_REG_OFDM_FA_HOLDC_11N 0xC00 | ||
103 | #define DM_REG_RX_PATH_11N 0xC04 | ||
104 | #define DM_REG_TRMUX_11N 0xC08 | ||
105 | #define DM_REG_OFDM_FA_RSTC_11N 0xC0C | ||
106 | #define DM_REG_RXIQI_MATRIX_11N 0xC14 | ||
107 | #define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C | ||
108 | #define DM_REG_IGI_A_11N 0xC50 | ||
109 | #define DM_REG_ANTDIV_PARA2_11N 0xC54 | ||
110 | #define DM_REG_IGI_B_11N 0xC58 | ||
111 | #define DM_REG_ANTDIV_PARA3_11N 0xC5C | ||
112 | #define DM_REG_BB_PWR_SAV2_11N 0xC70 | ||
113 | #define DM_REG_RX_OFF_11N 0xC7C | ||
114 | #define DM_REG_TXIQK_MATRIXA_11N 0xC80 | ||
115 | #define DM_REG_TXIQK_MATRIXB_11N 0xC88 | ||
116 | #define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 | ||
117 | #define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C | ||
118 | #define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 | ||
119 | #define DM_REG_ANTDIV_PARA1_11N 0xCA4 | ||
120 | #define DM_REG_OFDM_FA_TYPE1_11N 0xCF0 | ||
121 | /*PAGE D */ | ||
122 | #define DM_REG_OFDM_FA_RSTD_11N 0xD00 | ||
123 | #define DM_REG_OFDM_FA_TYPE2_11N 0xDA0 | ||
124 | #define DM_REG_OFDM_FA_TYPE3_11N 0xDA4 | ||
125 | #define DM_REG_OFDM_FA_TYPE4_11N 0xDA8 | ||
126 | /*PAGE E */ | ||
127 | #define DM_REG_TXAGC_A_6_18_11N 0xE00 | ||
128 | #define DM_REG_TXAGC_A_24_54_11N 0xE04 | ||
129 | #define DM_REG_TXAGC_A_1_MCS32_11N 0xE08 | ||
130 | #define DM_REG_TXAGC_A_MCS0_3_11N 0xE10 | ||
131 | #define DM_REG_TXAGC_A_MCS4_7_11N 0xE14 | ||
132 | #define DM_REG_TXAGC_A_MCS8_11_11N 0xE18 | ||
133 | #define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C | ||
134 | #define DM_REG_FPGA0_IQK_11N 0xE28 | ||
135 | #define DM_REG_TXIQK_TONE_A_11N 0xE30 | ||
136 | #define DM_REG_RXIQK_TONE_A_11N 0xE34 | ||
137 | #define DM_REG_TXIQK_PI_A_11N 0xE38 | ||
138 | #define DM_REG_RXIQK_PI_A_11N 0xE3C | ||
139 | #define DM_REG_TXIQK_11N 0xE40 | ||
140 | #define DM_REG_RXIQK_11N 0xE44 | ||
141 | #define DM_REG_IQK_AGC_PTS_11N 0xE48 | ||
142 | #define DM_REG_IQK_AGC_RSP_11N 0xE4C | ||
143 | #define DM_REG_BLUETOOTH_11N 0xE6C | ||
144 | #define DM_REG_RX_WAIT_CCA_11N 0xE70 | ||
145 | #define DM_REG_TX_CCK_RFON_11N 0xE74 | ||
146 | #define DM_REG_TX_CCK_BBON_11N 0xE78 | ||
147 | #define DM_REG_OFDM_RFON_11N 0xE7C | ||
148 | #define DM_REG_OFDM_BBON_11N 0xE80 | ||
149 | #define DM_REG_TX2RX_11N 0xE84 | ||
150 | #define DM_REG_TX2TX_11N 0xE88 | ||
151 | #define DM_REG_RX_CCK_11N 0xE8C | ||
152 | #define DM_REG_RX_OFDM_11N 0xED0 | ||
153 | #define DM_REG_RX_WAIT_RIFS_11N 0xED4 | ||
154 | #define DM_REG_RX2RX_11N 0xED8 | ||
155 | #define DM_REG_STANDBY_11N 0xEDC | ||
156 | #define DM_REG_SLEEP_11N 0xEE0 | ||
157 | #define DM_REG_PMPD_ANAEN_11N 0xEEC | ||
158 | |||
159 | |||
160 | /*MAC REG LIST*/ | ||
161 | #define DM_REG_BB_RST_11N 0x02 | ||
162 | #define DM_REG_ANTSEL_PIN_11N 0x4C | ||
163 | #define DM_REG_EARLY_MODE_11N 0x4D0 | ||
164 | #define DM_REG_RSSI_MONITOR_11N 0x4FE | ||
165 | #define DM_REG_EDCA_VO_11N 0x500 | ||
166 | #define DM_REG_EDCA_VI_11N 0x504 | ||
167 | #define DM_REG_EDCA_BE_11N 0x508 | ||
168 | #define DM_REG_EDCA_BK_11N 0x50C | ||
169 | #define DM_REG_TXPAUSE_11N 0x522 | ||
170 | #define DM_REG_RESP_TX_11N 0x6D8 | ||
171 | #define DM_REG_ANT_TRAIN_1 0x7b0 | ||
172 | #define DM_REG_ANT_TRAIN_2 0x7b4 | ||
173 | |||
174 | /*DIG Related*/ | ||
175 | #define DM_BIT_IGI_11N 0x0000007F | ||
176 | |||
177 | #define HAL_DM_DIG_DISABLE BIT(0) | ||
178 | #define HAL_DM_HIPWR_DISABLE BIT(1) | ||
179 | |||
180 | #define OFDM_TABLE_LENGTH 43 | ||
181 | #define CCK_TABLE_LENGTH 33 | ||
182 | |||
183 | #define OFDM_TABLE_SIZE 43 | ||
184 | #define CCK_TABLE_SIZE 33 | ||
185 | |||
186 | #define BW_AUTO_SWITCH_HIGH_LOW 25 | ||
187 | #define BW_AUTO_SWITCH_LOW_HIGH 30 | ||
188 | |||
189 | #define DM_DIG_THRESH_HIGH 40 | ||
190 | #define DM_DIG_THRESH_LOW 35 | ||
191 | |||
192 | #define DM_FALSEALARM_THRESH_LOW 400 | ||
193 | #define DM_FALSEALARM_THRESH_HIGH 1000 | ||
194 | |||
195 | #define DM_DIG_MAX 0x3e | ||
196 | #define DM_DIG_MIN 0x1e | ||
197 | |||
198 | #define DM_DIG_MAX_AP 0x32 | ||
199 | #define DM_DIG_MIN_AP 0x20 | ||
200 | |||
201 | #define DM_DIG_FA_UPPER 0x3e | ||
202 | #define DM_DIG_FA_LOWER 0x1e | ||
203 | #define DM_DIG_FA_TH0 0x200 | ||
204 | #define DM_DIG_FA_TH1 0x300 | ||
205 | #define DM_DIG_FA_TH2 0x400 | ||
206 | |||
207 | #define DM_DIG_BACKOFF_MAX 12 | ||
208 | #define DM_DIG_BACKOFF_MIN -4 | ||
209 | #define DM_DIG_BACKOFF_DEFAULT 10 | ||
210 | |||
211 | #define RXPATHSELECTION_SS_TH_LOW 30 | ||
212 | #define RXPATHSELECTION_DIFF_TH 18 | ||
213 | |||
214 | #define DM_RATR_STA_INIT 0 | ||
215 | #define DM_RATR_STA_HIGH 1 | ||
216 | #define DM_RATR_STA_MIDDLE 2 | ||
217 | #define DM_RATR_STA_LOW 3 | ||
218 | |||
219 | #define CTS2SELF_THVAL 30 | ||
220 | #define REGC38_TH 20 | ||
221 | |||
222 | #define WAIOTTHVAL 25 | ||
223 | |||
224 | #define TXHIGHPWRLEVEL_NORMAL 0 | ||
225 | #define TXHIGHPWRLEVEL_LEVEL1 1 | ||
226 | #define TXHIGHPWRLEVEL_LEVEL2 2 | ||
227 | #define TXHIGHPWRLEVEL_BT1 3 | ||
228 | #define TXHIGHPWRLEVEL_BT2 4 | ||
229 | |||
230 | #define DM_TYPE_BYFW 0 | ||
231 | #define DM_TYPE_BYDRIVER 1 | ||
232 | |||
233 | #define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 | ||
234 | #define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 | ||
235 | #define TXPWRTRACK_MAX_IDX 6 | ||
236 | |||
237 | struct swat_t { | ||
238 | u8 failure_cnt; | ||
239 | u8 try_flag; | ||
240 | u8 stop_trying; | ||
241 | long pre_rssi; | ||
242 | long trying_threshold; | ||
243 | u8 cur_antenna; | ||
244 | u8 pre_antenna; | ||
245 | }; | ||
246 | |||
247 | enum FAT_STATE { | ||
248 | FAT_NORMAL_STATE = 0, | ||
249 | FAT_TRAINING_STATE = 1, | ||
250 | }; | ||
251 | |||
252 | enum tag_dynamic_init_gain_operation_type_definition { | ||
253 | DIG_TYPE_THRESH_HIGH = 0, | ||
254 | DIG_TYPE_THRESH_LOW = 1, | ||
255 | DIG_TYPE_BACKOFF = 2, | ||
256 | DIG_TYPE_RX_GAIN_MIN = 3, | ||
257 | DIG_TYPE_RX_GAIN_MAX = 4, | ||
258 | DIG_TYPE_ENABLE = 5, | ||
259 | DIG_TYPE_DISABLE = 6, | ||
260 | DIG_OP_TYPE_MAX | ||
261 | }; | ||
262 | |||
263 | enum tag_cck_packet_detection_threshold_type_definition { | ||
264 | CCK_PD_STAGE_LOWRSSI = 0, | ||
265 | CCK_PD_STAGE_HIGHRSSI = 1, | ||
266 | CCK_FA_STAGE_LOW = 2, | ||
267 | CCK_FA_STAGE_HIGH = 3, | ||
268 | CCK_PD_STAGE_MAX = 4, | ||
269 | }; | ||
270 | |||
271 | enum dm_1r_cca_e { | ||
272 | CCA_1R = 0, | ||
273 | CCA_2R = 1, | ||
274 | CCA_MAX = 2, | ||
275 | }; | ||
276 | |||
277 | enum dm_rf_e { | ||
278 | RF_SAVE = 0, | ||
279 | RF_NORMAL = 1, | ||
280 | RF_MAX = 2, | ||
281 | }; | ||
282 | |||
283 | enum dm_sw_ant_switch_e { | ||
284 | ANS_ANTENNA_B = 1, | ||
285 | ANS_ANTENNA_A = 2, | ||
286 | ANS_ANTENNA_MAX = 3, | ||
287 | }; | ||
288 | |||
289 | enum dm_dig_ext_port_alg_e { | ||
290 | DIG_EXT_PORT_STAGE_0 = 0, | ||
291 | DIG_EXT_PORT_STAGE_1 = 1, | ||
292 | DIG_EXT_PORT_STAGE_2 = 2, | ||
293 | DIG_EXT_PORT_STAGE_3 = 3, | ||
294 | DIG_EXT_PORT_STAGE_MAX = 4, | ||
295 | }; | ||
296 | |||
297 | enum dm_dig_connect_e { | ||
298 | DIG_STA_DISCONNECT = 0, | ||
299 | DIG_STA_CONNECT = 1, | ||
300 | DIG_STA_BEFORE_CONNECT = 2, | ||
301 | DIG_MULTISTA_DISCONNECT = 3, | ||
302 | DIG_MULTISTA_CONNECT = 4, | ||
303 | DIG_CONNECT_MAX | ||
304 | }; | ||
305 | |||
306 | enum pwr_track_control_method { | ||
307 | BBSWING, | ||
308 | TXAGC | ||
309 | }; | ||
310 | |||
311 | void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, | ||
312 | u8 *pdesc, u32 mac_id); | ||
313 | void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw, u8 antsel_tr_mux, | ||
314 | u32 mac_id, u32 rx_pwdb_all); | ||
315 | void rtl88e_dm_fast_antenna_training_callback(unsigned long data); | ||
316 | void rtl88e_dm_init(struct ieee80211_hw *hw); | ||
317 | void rtl88e_dm_watchdog(struct ieee80211_hw *hw); | ||
318 | void rtl88e_dm_write_dig(struct ieee80211_hw *hw); | ||
319 | void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw); | ||
320 | void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw); | ||
321 | void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); | ||
322 | void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw, | ||
323 | u8 type, u8 *pdirection, | ||
324 | u32 *poutwrite_val); | ||
325 | |||
326 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c new file mode 100644 index 000000000000..57e4cc5833a9 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c | |||
@@ -0,0 +1,830 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "../base.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "fw.h" | ||
36 | |||
37 | #include <linux/kmemleak.h> | ||
38 | |||
39 | static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable) | ||
40 | { | ||
41 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
42 | u8 tmp; | ||
43 | |||
44 | if (enable) { | ||
45 | tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); | ||
46 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04); | ||
47 | |||
48 | tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); | ||
49 | rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); | ||
50 | |||
51 | tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); | ||
52 | rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); | ||
53 | } else { | ||
54 | tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); | ||
55 | rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); | ||
56 | |||
57 | rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static void _rtl88e_fw_block_write(struct ieee80211_hw *hw, | ||
62 | const u8 *buffer, u32 size) | ||
63 | { | ||
64 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
65 | u32 blk_sz = sizeof(u32); | ||
66 | u8 *buf_ptr = (u8 *)buffer; | ||
67 | u32 *pu4BytePtr = (u32 *)buffer; | ||
68 | u32 i, offset, blk_cnt, remain; | ||
69 | |||
70 | blk_cnt = size / blk_sz; | ||
71 | remain = size % blk_sz; | ||
72 | |||
73 | for (i = 0; i < blk_cnt; i++) { | ||
74 | offset = i * blk_sz; | ||
75 | rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset), | ||
76 | *(pu4BytePtr + i)); | ||
77 | } | ||
78 | |||
79 | if (remain) { | ||
80 | offset = blk_cnt * blk_sz; | ||
81 | buf_ptr += offset; | ||
82 | for (i = 0; i < remain; i++) { | ||
83 | rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS + | ||
84 | offset + i), *(buf_ptr + i)); | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | static void _rtl88e_fw_page_write(struct ieee80211_hw *hw, | ||
90 | u32 page, const u8 *buffer, u32 size) | ||
91 | { | ||
92 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
93 | u8 value8; | ||
94 | u8 u8page = (u8) (page & 0x07); | ||
95 | |||
96 | value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; | ||
97 | |||
98 | rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); | ||
99 | _rtl88e_fw_block_write(hw, buffer, size); | ||
100 | } | ||
101 | |||
102 | static void _rtl88e_fill_dummy(u8 *pfwbuf, u32 *pfwlen) | ||
103 | { | ||
104 | u32 fwlen = *pfwlen; | ||
105 | u8 remain = (u8) (fwlen % 4); | ||
106 | |||
107 | remain = (remain == 0) ? 0 : (4 - remain); | ||
108 | |||
109 | while (remain > 0) { | ||
110 | pfwbuf[fwlen] = 0; | ||
111 | fwlen++; | ||
112 | remain--; | ||
113 | } | ||
114 | |||
115 | *pfwlen = fwlen; | ||
116 | } | ||
117 | |||
118 | static void _rtl88e_write_fw(struct ieee80211_hw *hw, | ||
119 | enum version_8188e version, u8 *buffer, u32 size) | ||
120 | { | ||
121 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
122 | u8 *buf_ptr = (u8 *)buffer; | ||
123 | u32 page_no, remain; | ||
124 | u32 page, offset; | ||
125 | |||
126 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); | ||
127 | |||
128 | _rtl88e_fill_dummy(buf_ptr, &size); | ||
129 | |||
130 | page_no = size / FW_8192C_PAGE_SIZE; | ||
131 | remain = size % FW_8192C_PAGE_SIZE; | ||
132 | |||
133 | if (page_no > 8) { | ||
134 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
135 | "Page numbers should not greater then 8\n"); | ||
136 | } | ||
137 | |||
138 | for (page = 0; page < page_no; page++) { | ||
139 | offset = page * FW_8192C_PAGE_SIZE; | ||
140 | _rtl88e_fw_page_write(hw, page, (buf_ptr + offset), | ||
141 | FW_8192C_PAGE_SIZE); | ||
142 | } | ||
143 | |||
144 | if (remain) { | ||
145 | offset = page_no * FW_8192C_PAGE_SIZE; | ||
146 | page = page_no; | ||
147 | _rtl88e_fw_page_write(hw, page, (buf_ptr + offset), remain); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw) | ||
152 | { | ||
153 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
154 | int err = -EIO; | ||
155 | u32 counter = 0; | ||
156 | u32 value32; | ||
157 | |||
158 | do { | ||
159 | value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); | ||
160 | } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && | ||
161 | (!(value32 & FWDL_CHKSUM_RPT))); | ||
162 | |||
163 | if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { | ||
164 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
165 | "chksum report faill ! REG_MCUFWDL:0x%08x .\n", | ||
166 | value32); | ||
167 | goto exit; | ||
168 | } | ||
169 | |||
170 | RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, | ||
171 | "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); | ||
172 | |||
173 | value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); | ||
174 | value32 |= MCUFWDL_RDY; | ||
175 | value32 &= ~WINTINI_RDY; | ||
176 | rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); | ||
177 | |||
178 | rtl88e_firmware_selfreset(hw); | ||
179 | counter = 0; | ||
180 | |||
181 | do { | ||
182 | value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); | ||
183 | if (value32 & WINTINI_RDY) { | ||
184 | RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, | ||
185 | "Polling FW ready success!! REG_MCUFWDL:0x%08x.\n", | ||
186 | value32); | ||
187 | err = 0; | ||
188 | goto exit; | ||
189 | } | ||
190 | |||
191 | udelay(FW_8192C_POLLING_DELAY); | ||
192 | |||
193 | } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); | ||
194 | |||
195 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
196 | "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32); | ||
197 | |||
198 | exit: | ||
199 | return err; | ||
200 | } | ||
201 | |||
202 | int rtl88e_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) | ||
203 | { | ||
204 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
205 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
206 | struct rtl92c_firmware_header *pfwheader; | ||
207 | u8 *pfwdata; | ||
208 | u32 fwsize; | ||
209 | int err; | ||
210 | enum version_8188e version = rtlhal->version; | ||
211 | |||
212 | if (!rtlhal->pfirmware) | ||
213 | return 1; | ||
214 | |||
215 | pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; | ||
216 | pfwdata = (u8 *)rtlhal->pfirmware; | ||
217 | fwsize = rtlhal->fwsize; | ||
218 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, | ||
219 | "normal Firmware SIZE %d\n", fwsize); | ||
220 | |||
221 | if (IS_FW_HEADER_EXIST(pfwheader)) { | ||
222 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, | ||
223 | "Firmware Version(%d), Signature(%#x), Size(%d)\n", | ||
224 | pfwheader->version, pfwheader->signature, | ||
225 | (int)sizeof(struct rtl92c_firmware_header)); | ||
226 | |||
227 | pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header); | ||
228 | fwsize = fwsize - sizeof(struct rtl92c_firmware_header); | ||
229 | } | ||
230 | |||
231 | if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { | ||
232 | rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); | ||
233 | rtl88e_firmware_selfreset(hw); | ||
234 | } | ||
235 | _rtl88e_enable_fw_download(hw, true); | ||
236 | _rtl88e_write_fw(hw, version, pfwdata, fwsize); | ||
237 | _rtl88e_enable_fw_download(hw, false); | ||
238 | |||
239 | err = _rtl88e_fw_free_to_go(hw); | ||
240 | |||
241 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, | ||
242 | "Firmware is%s ready to run!\n", err ? " not" : ""); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) | ||
247 | { | ||
248 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
249 | u8 val_hmetfr; | ||
250 | |||
251 | val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); | ||
252 | if (((val_hmetfr >> boxnum) & BIT(0)) == 0) | ||
253 | return true; | ||
254 | return false; | ||
255 | } | ||
256 | |||
257 | static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, | ||
258 | u8 element_id, u32 cmd_len, | ||
259 | u8 *cmd_b) | ||
260 | { | ||
261 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
262 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
263 | u8 boxnum; | ||
264 | u16 box_reg = 0, box_extreg = 0; | ||
265 | u8 u1b_tmp; | ||
266 | bool isfw_read = false; | ||
267 | u8 buf_index = 0; | ||
268 | bool write_sucess = false; | ||
269 | u8 wait_h2c_limit = 100; | ||
270 | u8 wait_writeh2c_limit = 100; | ||
271 | u8 boxc[4], boxext[2]; | ||
272 | u32 h2c_waitcounter = 0; | ||
273 | unsigned long flag; | ||
274 | u8 idx; | ||
275 | |||
276 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); | ||
277 | |||
278 | while (true) { | ||
279 | spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); | ||
280 | if (rtlhal->h2c_setinprogress) { | ||
281 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
282 | "H2C set in progress! Wait to set..element_id(%d).\n", | ||
283 | element_id); | ||
284 | |||
285 | while (rtlhal->h2c_setinprogress) { | ||
286 | spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, | ||
287 | flag); | ||
288 | h2c_waitcounter++; | ||
289 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
290 | "Wait 100 us (%d times)...\n", | ||
291 | h2c_waitcounter); | ||
292 | udelay(100); | ||
293 | |||
294 | if (h2c_waitcounter > 1000) | ||
295 | return; | ||
296 | spin_lock_irqsave(&rtlpriv->locks.h2c_lock, | ||
297 | flag); | ||
298 | } | ||
299 | spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); | ||
300 | } else { | ||
301 | rtlhal->h2c_setinprogress = true; | ||
302 | spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); | ||
303 | break; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | while (!write_sucess) { | ||
308 | wait_writeh2c_limit--; | ||
309 | if (wait_writeh2c_limit == 0) { | ||
310 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
311 | "Write H2C fail because no trigger for FW INT!\n"); | ||
312 | break; | ||
313 | } | ||
314 | |||
315 | boxnum = rtlhal->last_hmeboxnum; | ||
316 | switch (boxnum) { | ||
317 | case 0: | ||
318 | box_reg = REG_HMEBOX_0; | ||
319 | box_extreg = REG_HMEBOX_EXT_0; | ||
320 | break; | ||
321 | case 1: | ||
322 | box_reg = REG_HMEBOX_1; | ||
323 | box_extreg = REG_HMEBOX_EXT_1; | ||
324 | break; | ||
325 | case 2: | ||
326 | box_reg = REG_HMEBOX_2; | ||
327 | box_extreg = REG_HMEBOX_EXT_2; | ||
328 | break; | ||
329 | case 3: | ||
330 | box_reg = REG_HMEBOX_3; | ||
331 | box_extreg = REG_HMEBOX_EXT_3; | ||
332 | break; | ||
333 | default: | ||
334 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
335 | "switch case not processed\n"); | ||
336 | break; | ||
337 | } | ||
338 | |||
339 | isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); | ||
340 | while (!isfw_read) { | ||
341 | wait_h2c_limit--; | ||
342 | if (wait_h2c_limit == 0) { | ||
343 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
344 | "Wating too long for FW read " | ||
345 | "clear HMEBox(%d)!\n", boxnum); | ||
346 | break; | ||
347 | } | ||
348 | |||
349 | udelay(10); | ||
350 | |||
351 | isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); | ||
352 | u1b_tmp = rtl_read_byte(rtlpriv, 0x130); | ||
353 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
354 | "Wating for FW read clear HMEBox(%d)!!! " | ||
355 | "0x130 = %2x\n", boxnum, u1b_tmp); | ||
356 | } | ||
357 | |||
358 | if (!isfw_read) { | ||
359 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
360 | "Write H2C register BOX[%d] fail!!!!! " | ||
361 | "Fw do not read.\n", boxnum); | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | memset(boxc, 0, sizeof(boxc)); | ||
366 | memset(boxext, 0, sizeof(boxext)); | ||
367 | boxc[0] = element_id; | ||
368 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
369 | "Write element_id box_reg(%4x) = %2x\n", | ||
370 | box_reg, element_id); | ||
371 | |||
372 | switch (cmd_len) { | ||
373 | case 1: | ||
374 | case 2: | ||
375 | case 3: | ||
376 | /*boxc[0] &= ~(BIT(7));*/ | ||
377 | memcpy((u8 *)(boxc) + 1, cmd_b + buf_index, cmd_len); | ||
378 | |||
379 | for (idx = 0; idx < 4; idx++) | ||
380 | rtl_write_byte(rtlpriv, box_reg+idx, boxc[idx]); | ||
381 | break; | ||
382 | case 4: | ||
383 | case 5: | ||
384 | case 6: | ||
385 | case 7: | ||
386 | /*boxc[0] |= (BIT(7));*/ | ||
387 | memcpy((u8 *)(boxext), cmd_b + buf_index+3, cmd_len-3); | ||
388 | memcpy((u8 *)(boxc) + 1, cmd_b + buf_index, 3); | ||
389 | |||
390 | for (idx = 0; idx < 2; idx++) { | ||
391 | rtl_write_byte(rtlpriv, box_extreg + idx, | ||
392 | boxext[idx]); | ||
393 | } | ||
394 | |||
395 | for (idx = 0; idx < 4; idx++) { | ||
396 | rtl_write_byte(rtlpriv, box_reg + idx, | ||
397 | boxc[idx]); | ||
398 | } | ||
399 | break; | ||
400 | default: | ||
401 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
402 | "switch case not processed\n"); | ||
403 | break; | ||
404 | } | ||
405 | |||
406 | write_sucess = true; | ||
407 | |||
408 | rtlhal->last_hmeboxnum = boxnum + 1; | ||
409 | if (rtlhal->last_hmeboxnum == 4) | ||
410 | rtlhal->last_hmeboxnum = 0; | ||
411 | |||
412 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
413 | "pHalData->last_hmeboxnum = %d\n", | ||
414 | rtlhal->last_hmeboxnum); | ||
415 | } | ||
416 | |||
417 | spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); | ||
418 | rtlhal->h2c_setinprogress = false; | ||
419 | spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); | ||
420 | |||
421 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); | ||
422 | } | ||
423 | |||
424 | void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, | ||
425 | u8 element_id, u32 cmd_len, u8 *cmd_b) | ||
426 | { | ||
427 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
428 | u32 tmp_cmdbuf[2]; | ||
429 | |||
430 | if (rtlhal->fw_ready == false) { | ||
431 | RT_ASSERT(false, "fail H2C cmd - Fw download fail!!!\n"); | ||
432 | return; | ||
433 | } | ||
434 | |||
435 | memset(tmp_cmdbuf, 0, 8); | ||
436 | memcpy(tmp_cmdbuf, cmd_b, cmd_len); | ||
437 | _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); | ||
438 | |||
439 | return; | ||
440 | } | ||
441 | |||
442 | void rtl88e_firmware_selfreset(struct ieee80211_hw *hw) | ||
443 | { | ||
444 | u8 u1b_tmp; | ||
445 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
446 | |||
447 | u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); | ||
448 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); | ||
449 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2))); | ||
450 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
451 | "8051Reset88E(): 8051 reset success.\n"); | ||
452 | } | ||
453 | |||
454 | void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) | ||
455 | { | ||
456 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
457 | u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 }; | ||
458 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
459 | u8 power_state = 0; | ||
460 | |||
461 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); | ||
462 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); | ||
463 | SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, 0); | ||
464 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, | ||
465 | (rtlpriv->mac80211.p2p) ? | ||
466 | ppsc->smart_ps : 1); | ||
467 | SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, | ||
468 | ppsc->reg_max_lps_awakeintvl); | ||
469 | SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); | ||
470 | if (mode == FW_PS_ACTIVE_MODE) | ||
471 | power_state |= FW_PWR_STATE_ACTIVE; | ||
472 | else | ||
473 | power_state |= FW_PWR_STATE_RF_OFF; | ||
474 | SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); | ||
475 | |||
476 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, | ||
477 | "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", | ||
478 | u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH); | ||
479 | rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE, H2C_88E_PWEMODE_LENGTH, | ||
480 | u1_h2c_set_pwrmode); | ||
481 | } | ||
482 | |||
483 | void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) | ||
484 | { | ||
485 | u8 u1_joinbssrpt_parm[1] = { 0 }; | ||
486 | |||
487 | SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); | ||
488 | |||
489 | rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm); | ||
490 | } | ||
491 | |||
492 | void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, | ||
493 | u8 ap_offload_enable) | ||
494 | { | ||
495 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
496 | u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 }; | ||
497 | |||
498 | SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable); | ||
499 | SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid); | ||
500 | SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0); | ||
501 | |||
502 | rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD, H2C_88E_AP_OFFLOAD_LENGTH, | ||
503 | u1_apoffload_parm); | ||
504 | } | ||
505 | |||
506 | static bool _rtl88e_cmd_send_packet(struct ieee80211_hw *hw, | ||
507 | struct sk_buff *skb) | ||
508 | { | ||
509 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
510 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
511 | struct rtl8192_tx_ring *ring; | ||
512 | struct rtl_tx_desc *pdesc; | ||
513 | struct sk_buff *pskb = NULL; | ||
514 | unsigned long flags; | ||
515 | |||
516 | ring = &rtlpci->tx_ring[BEACON_QUEUE]; | ||
517 | |||
518 | pskb = __skb_dequeue(&ring->queue); | ||
519 | if (pskb) | ||
520 | kfree_skb(pskb); | ||
521 | |||
522 | spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); | ||
523 | |||
524 | pdesc = &ring->desc[0]; | ||
525 | |||
526 | rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); | ||
527 | |||
528 | __skb_queue_tail(&ring->queue, skb); | ||
529 | |||
530 | spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); | ||
531 | |||
532 | rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); | ||
533 | |||
534 | return true; | ||
535 | } | ||
536 | |||
537 | #define BEACON_PG 0 /* ->1 */ | ||
538 | #define PSPOLL_PG 2 | ||
539 | #define NULL_PG 3 | ||
540 | #define PROBERSP_PG 4 /* ->5 */ | ||
541 | |||
542 | #define TOTAL_RESERVED_PKT_LEN 768 | ||
543 | |||
544 | static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { | ||
545 | /* page 0 beacon */ | ||
546 | 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, | ||
547 | 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, | ||
548 | 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, | ||
549 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
550 | 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, | ||
551 | 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, | ||
552 | 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, | ||
553 | 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, | ||
554 | 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, | ||
555 | 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, | ||
556 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
557 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
558 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
559 | 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, | ||
560 | 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
561 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
562 | |||
563 | /* page 1 beacon */ | ||
564 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
565 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
566 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
567 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
568 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
569 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
570 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
571 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
572 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
573 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
574 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
575 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
576 | 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, | ||
577 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
578 | 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
579 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
580 | |||
581 | /* page 2 ps-poll */ | ||
582 | 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, | ||
583 | 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, | ||
584 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
585 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
586 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
587 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
588 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
589 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
590 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
591 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
592 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
593 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
594 | 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, | ||
595 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, | ||
596 | 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
597 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
598 | |||
599 | /* page 3 null */ | ||
600 | 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, | ||
601 | 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, | ||
602 | 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, | ||
603 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
604 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
605 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
606 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
607 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
608 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
609 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
610 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
611 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
612 | 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, | ||
613 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, | ||
614 | 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
615 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
616 | |||
617 | /* page 4 probe_resp */ | ||
618 | 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, | ||
619 | 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, | ||
620 | 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, | ||
621 | 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, | ||
622 | 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, | ||
623 | 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, | ||
624 | 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, | ||
625 | 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, | ||
626 | 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, | ||
627 | 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, | ||
628 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
629 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
630 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
631 | 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, | ||
632 | 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
633 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
634 | |||
635 | /* page 5 probe_resp */ | ||
636 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
637 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
638 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
639 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
640 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
641 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
642 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
643 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
644 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
645 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
646 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
647 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
648 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
649 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
650 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
651 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
652 | }; | ||
653 | |||
654 | void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | ||
655 | { | ||
656 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
657 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
658 | struct sk_buff *skb = NULL; | ||
659 | |||
660 | u32 totalpacketlen; | ||
661 | u8 u1RsvdPageLoc[5] = { 0 }; | ||
662 | |||
663 | u8 *beacon; | ||
664 | u8 *pspoll; | ||
665 | u8 *nullfunc; | ||
666 | u8 *probersp; | ||
667 | /*--------------------------------------------------------- | ||
668 | * (1) beacon | ||
669 | *--------------------------------------------------------- | ||
670 | */ | ||
671 | beacon = &reserved_page_packet[BEACON_PG * 128]; | ||
672 | SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); | ||
673 | SET_80211_HDR_ADDRESS3(beacon, mac->bssid); | ||
674 | |||
675 | /*------------------------------------------------------- | ||
676 | * (2) ps-poll | ||
677 | *-------------------------------------------------------- | ||
678 | */ | ||
679 | pspoll = &reserved_page_packet[PSPOLL_PG * 128]; | ||
680 | SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000)); | ||
681 | SET_80211_PS_POLL_BSSID(pspoll, mac->bssid); | ||
682 | SET_80211_PS_POLL_TA(pspoll, mac->mac_addr); | ||
683 | |||
684 | SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); | ||
685 | |||
686 | /*-------------------------------------------------------- | ||
687 | * (3) null data | ||
688 | *--------------------------------------------------------- | ||
689 | */ | ||
690 | nullfunc = &reserved_page_packet[NULL_PG * 128]; | ||
691 | SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); | ||
692 | SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); | ||
693 | SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); | ||
694 | |||
695 | SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); | ||
696 | |||
697 | /*--------------------------------------------------------- | ||
698 | * (4) probe response | ||
699 | *---------------------------------------------------------- | ||
700 | */ | ||
701 | probersp = &reserved_page_packet[PROBERSP_PG * 128]; | ||
702 | SET_80211_HDR_ADDRESS1(probersp, mac->bssid); | ||
703 | SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr); | ||
704 | SET_80211_HDR_ADDRESS3(probersp, mac->bssid); | ||
705 | |||
706 | SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); | ||
707 | |||
708 | totalpacketlen = TOTAL_RESERVED_PKT_LEN; | ||
709 | |||
710 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, | ||
711 | "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", | ||
712 | &reserved_page_packet[0], totalpacketlen); | ||
713 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, | ||
714 | "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", | ||
715 | u1RsvdPageLoc, 3); | ||
716 | |||
717 | skb = dev_alloc_skb(totalpacketlen); | ||
718 | if (!skb) | ||
719 | return; | ||
720 | kmemleak_not_leak(skb); | ||
721 | memcpy(skb_put(skb, totalpacketlen), | ||
722 | &reserved_page_packet, totalpacketlen); | ||
723 | |||
724 | if (_rtl88e_cmd_send_packet(hw, skb)) { | ||
725 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
726 | "Set RSVD page location to Fw.\n"); | ||
727 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, | ||
728 | "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3); | ||
729 | rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE, | ||
730 | sizeof(u1RsvdPageLoc), u1RsvdPageLoc); | ||
731 | } else | ||
732 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
733 | "Set RSVD page location to Fw FAIL!!!!!!.\n"); | ||
734 | } | ||
735 | |||
736 | /*Shoud check FW support p2p or not.*/ | ||
737 | static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) | ||
738 | { | ||
739 | u8 u1_ctwindow_period[1] = {ctwindow}; | ||
740 | |||
741 | rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); | ||
742 | } | ||
743 | |||
744 | void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | ||
745 | { | ||
746 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
747 | struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); | ||
748 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
749 | struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); | ||
750 | struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; | ||
751 | u8 i; | ||
752 | u16 ctwindow; | ||
753 | u32 start_time, tsf_low; | ||
754 | |||
755 | switch (p2p_ps_state) { | ||
756 | case P2P_PS_DISABLE: | ||
757 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); | ||
758 | memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t)); | ||
759 | break; | ||
760 | case P2P_PS_ENABLE: | ||
761 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); | ||
762 | /* update CTWindow value. */ | ||
763 | if (p2pinfo->ctwindow > 0) { | ||
764 | p2p_ps_offload->ctwindow_en = 1; | ||
765 | ctwindow = p2pinfo->ctwindow; | ||
766 | rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow); | ||
767 | } | ||
768 | /* hw only support 2 set of NoA */ | ||
769 | for (i = 0; i < p2pinfo->noa_num; i++) { | ||
770 | /* To control the register setting for which NOA*/ | ||
771 | rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); | ||
772 | if (i == 0) | ||
773 | p2p_ps_offload->noa0_en = 1; | ||
774 | else | ||
775 | p2p_ps_offload->noa1_en = 1; | ||
776 | |||
777 | /* config P2P NoA Descriptor Register */ | ||
778 | rtl_write_dword(rtlpriv, 0x5E0, | ||
779 | p2pinfo->noa_duration[i]); | ||
780 | rtl_write_dword(rtlpriv, 0x5E4, | ||
781 | p2pinfo->noa_interval[i]); | ||
782 | |||
783 | /*Get Current TSF value */ | ||
784 | tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); | ||
785 | |||
786 | start_time = p2pinfo->noa_start_time[i]; | ||
787 | if (p2pinfo->noa_count_type[i] != 1) { | ||
788 | while (start_time <= (tsf_low + (50 * 1024))) { | ||
789 | start_time += p2pinfo->noa_interval[i]; | ||
790 | if (p2pinfo->noa_count_type[i] != 255) | ||
791 | p2pinfo->noa_count_type[i]--; | ||
792 | } | ||
793 | } | ||
794 | rtl_write_dword(rtlpriv, 0x5E8, start_time); | ||
795 | rtl_write_dword(rtlpriv, 0x5EC, | ||
796 | p2pinfo->noa_count_type[i]); | ||
797 | } | ||
798 | |||
799 | if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { | ||
800 | /* rst p2p circuit */ | ||
801 | rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); | ||
802 | |||
803 | p2p_ps_offload->offload_en = 1; | ||
804 | |||
805 | if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { | ||
806 | p2p_ps_offload->role = 1; | ||
807 | p2p_ps_offload->allstasleep = 0; | ||
808 | } else { | ||
809 | p2p_ps_offload->role = 0; | ||
810 | } | ||
811 | |||
812 | p2p_ps_offload->discovery = 0; | ||
813 | } | ||
814 | break; | ||
815 | case P2P_PS_SCAN: | ||
816 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); | ||
817 | p2p_ps_offload->discovery = 1; | ||
818 | break; | ||
819 | case P2P_PS_SCAN_DONE: | ||
820 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); | ||
821 | p2p_ps_offload->discovery = 0; | ||
822 | p2pinfo->p2p_ps_state = P2P_PS_ENABLE; | ||
823 | break; | ||
824 | default: | ||
825 | break; | ||
826 | } | ||
827 | |||
828 | rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1, | ||
829 | (u8 *)p2p_ps_offload); | ||
830 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h new file mode 100644 index 000000000000..854a9875cd5f --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h | |||
@@ -0,0 +1,301 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
26 | * | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #ifndef __RTL92C__FW__H__ | ||
30 | #define __RTL92C__FW__H__ | ||
31 | |||
32 | #define FW_8192C_SIZE 0x8000 | ||
33 | #define FW_8192C_START_ADDRESS 0x1000 | ||
34 | #define FW_8192C_END_ADDRESS 0x5FFF | ||
35 | #define FW_8192C_PAGE_SIZE 4096 | ||
36 | #define FW_8192C_POLLING_DELAY 5 | ||
37 | #define FW_8192C_POLLING_TIMEOUT_COUNT 3000 | ||
38 | |||
39 | #define IS_FW_HEADER_EXIST(_pfwhdr) \ | ||
40 | ((_pfwhdr->signature&0xFFFF) == 0x88E1) | ||
41 | #define USE_OLD_WOWLAN_DEBUG_FW 0 | ||
42 | |||
43 | #define H2C_88E_RSVDPAGE_LOC_LEN 5 | ||
44 | #define H2C_88E_PWEMODE_LENGTH 5 | ||
45 | #define H2C_88E_JOINBSSRPT_LENGTH 1 | ||
46 | #define H2C_88E_AP_OFFLOAD_LENGTH 3 | ||
47 | #define H2C_88E_WOWLAN_LENGTH 3 | ||
48 | #define H2C_88E_KEEP_ALIVE_CTRL_LENGTH 3 | ||
49 | #if (USE_OLD_WOWLAN_DEBUG_FW == 0) | ||
50 | #define H2C_88E_REMOTE_WAKE_CTRL_LEN 1 | ||
51 | #else | ||
52 | #define H2C_88E_REMOTE_WAKE_CTRL_LEN 3 | ||
53 | #endif | ||
54 | #define H2C_88E_AOAC_GLOBAL_INFO_LEN 2 | ||
55 | #define H2C_88E_AOAC_RSVDPAGE_LOC_LEN 7 | ||
56 | |||
57 | /* Fw PS state for RPWM. | ||
58 | * BIT[2:0] = HW state | ||
59 | * BIT[3] = Protocol PS state, 1: register active state, 0: register sleep state | ||
60 | * BIT[4] = sub-state | ||
61 | */ | ||
62 | #define FW_PS_GO_ON BIT(0) | ||
63 | #define FW_PS_TX_NULL BIT(1) | ||
64 | #define FW_PS_RF_ON BIT(2) | ||
65 | #define FW_PS_REGISTER_ACTIVE BIT(3) | ||
66 | |||
67 | #define FW_PS_DPS BIT(0) | ||
68 | #define FW_PS_LCLK (FW_PS_DPS) | ||
69 | #define FW_PS_RF_OFF BIT(1) | ||
70 | #define FW_PS_ALL_ON BIT(2) | ||
71 | #define FW_PS_ST_ACTIVE BIT(3) | ||
72 | #define FW_PS_ISR_ENABLE BIT(4) | ||
73 | #define FW_PS_IMR_ENABLE BIT(5) | ||
74 | |||
75 | |||
76 | #define FW_PS_ACK BIT(6) | ||
77 | #define FW_PS_TOGGLE BIT(7) | ||
78 | |||
79 | /* 88E RPWM value*/ | ||
80 | /* BIT[0] = 1: 32k, 0: 40M*/ | ||
81 | #define FW_PS_CLOCK_OFF BIT(0) /* 32k*/ | ||
82 | #define FW_PS_CLOCK_ON 0 /*40M*/ | ||
83 | |||
84 | #define FW_PS_STATE_MASK (0x0F) | ||
85 | #define FW_PS_STATE_HW_MASK (0x07) | ||
86 | /*ISR_ENABLE, IMR_ENABLE, and PS mode should be inherited.*/ | ||
87 | #define FW_PS_STATE_INT_MASK (0x3F) | ||
88 | |||
89 | #define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x)) | ||
90 | #define FW_PS_STATE_HW(x) (FW_PS_STATE_HW_MASK & (x)) | ||
91 | #define FW_PS_STATE_INT(x) (FW_PS_STATE_INT_MASK & (x)) | ||
92 | #define FW_PS_ISR_VAL(x) ((x) & 0x70) | ||
93 | #define FW_PS_IMR_MASK(x) ((x) & 0xDF) | ||
94 | #define FW_PS_KEEP_IMR(x) ((x) & 0x20) | ||
95 | |||
96 | #define FW_PS_STATE_S0 (FW_PS_DPS) | ||
97 | #define FW_PS_STATE_S1 (FW_PS_LCLK) | ||
98 | #define FW_PS_STATE_S2 (FW_PS_RF_OFF) | ||
99 | #define FW_PS_STATE_S3 (FW_PS_ALL_ON) | ||
100 | #define FW_PS_STATE_S4 ((FW_PS_ST_ACTIVE) | (FW_PS_ALL_ON)) | ||
101 | |||
102 | #define FW_PS_STATE_ALL_ON_88E (FW_PS_CLOCK_ON) | ||
103 | #define FW_PS_STATE_RF_ON_88E (FW_PS_CLOCK_ON) | ||
104 | #define FW_PS_STATE_RF_OFF_88E (FW_PS_CLOCK_ON) | ||
105 | #define FW_PS_STATE_RF_OFF_LOW_PWR_88E (FW_PS_CLOCK_OFF) | ||
106 | |||
107 | #define FW_PS_STATE_ALL_ON_92C (FW_PS_STATE_S4) | ||
108 | #define FW_PS_STATE_RF_ON_92C (FW_PS_STATE_S3) | ||
109 | #define FW_PS_STATE_RF_OFF_92C (FW_PS_STATE_S2) | ||
110 | #define FW_PS_STATE_RF_OFF_LOW_PWR_92C (FW_PS_STATE_S1) | ||
111 | |||
112 | /* For 88E H2C PwrMode Cmd ID 5.*/ | ||
113 | #define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) | ||
114 | #define FW_PWR_STATE_RF_OFF 0 | ||
115 | |||
116 | #define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK) | ||
117 | #define FW_PS_IS_CLK_ON(x) ((x) & (FW_PS_RF_OFF | FW_PS_ALL_ON)) | ||
118 | #define FW_PS_IS_RF_ON(x) ((x) & (FW_PS_ALL_ON)) | ||
119 | #define FW_PS_IS_ACTIVE(x) ((x) & (FW_PS_ST_ACTIVE)) | ||
120 | #define FW_PS_IS_CPWM_INT(x) ((x) & 0x40) | ||
121 | |||
122 | #define FW_CLR_PS_STATE(x) ((x) = ((x) & (0xF0))) | ||
123 | |||
124 | #define IS_IN_LOW_POWER_STATE_88E(fwpsstate) \ | ||
125 | (FW_PS_STATE(fwpsstate) == FW_PS_CLOCK_OFF) | ||
126 | |||
127 | #define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) | ||
128 | #define FW_PWR_STATE_RF_OFF 0 | ||
129 | |||
130 | struct rtl92c_firmware_header { | ||
131 | u16 signature; | ||
132 | u8 category; | ||
133 | u8 function; | ||
134 | u16 version; | ||
135 | u8 subversion; | ||
136 | u8 rsvd1; | ||
137 | u8 month; | ||
138 | u8 date; | ||
139 | u8 hour; | ||
140 | u8 minute; | ||
141 | u16 ramcodesize; | ||
142 | u16 rsvd2; | ||
143 | u32 svnindex; | ||
144 | u32 rsvd3; | ||
145 | u32 rsvd4; | ||
146 | u32 rsvd5; | ||
147 | }; | ||
148 | |||
149 | enum rtl8192c_h2c_cmd { | ||
150 | H2C_88E_RSVDPAGE = 0, | ||
151 | H2C_88E_JOINBSSRPT = 1, | ||
152 | H2C_88E_SCAN = 2, | ||
153 | H2C_88E_KEEP_ALIVE_CTRL = 3, | ||
154 | H2C_88E_DISCONNECT_DECISION = 4, | ||
155 | #if (USE_OLD_WOWLAN_DEBUG_FW == 1) | ||
156 | H2C_88E_WO_WLAN = 5, | ||
157 | #endif | ||
158 | H2C_88E_INIT_OFFLOAD = 6, | ||
159 | #if (USE_OLD_WOWLAN_DEBUG_FW == 1) | ||
160 | H2C_88E_REMOTE_WAKE_CTRL = 7, | ||
161 | #endif | ||
162 | H2C_88E_AP_OFFLOAD = 8, | ||
163 | H2C_88E_BCN_RSVDPAGE = 9, | ||
164 | H2C_88E_PROBERSP_RSVDPAGE = 10, | ||
165 | |||
166 | H2C_88E_SETPWRMODE = 0x20, | ||
167 | H2C_88E_PS_TUNING_PARA = 0x21, | ||
168 | H2C_88E_PS_TUNING_PARA2 = 0x22, | ||
169 | H2C_88E_PS_LPS_PARA = 0x23, | ||
170 | H2C_88E_P2P_PS_OFFLOAD = 024, | ||
171 | |||
172 | #if (USE_OLD_WOWLAN_DEBUG_FW == 0) | ||
173 | H2C_88E_WO_WLAN = 0x80, | ||
174 | H2C_88E_REMOTE_WAKE_CTRL = 0x81, | ||
175 | H2C_88E_AOAC_GLOBAL_INFO = 0x82, | ||
176 | H2C_88E_AOAC_RSVDPAGE = 0x83, | ||
177 | #endif | ||
178 | /* Not defined in new 88E H2C CMD Format */ | ||
179 | H2C_88E_RA_MASK, | ||
180 | H2C_88E_SELECTIVE_SUSPEND_ROF_CMD, | ||
181 | H2C_88E_P2P_PS_MODE, | ||
182 | H2C_88E_PSD_RESULT, | ||
183 | /*Not defined CTW CMD for P2P yet*/ | ||
184 | H2C_88E_P2P_PS_CTW_CMD, | ||
185 | MAX_88E_H2CCMD | ||
186 | }; | ||
187 | |||
188 | #define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) | ||
189 | |||
190 | #define SET_88E_H2CCMD_WOWLAN_FUNC_ENABLE(__cmd, __value) \ | ||
191 | SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) | ||
192 | #define SET_88E_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(__cmd, __value) \ | ||
193 | SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) | ||
194 | #define SET_88E_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(__cmd, __value) \ | ||
195 | SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) | ||
196 | #define SET_88E_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(__cmd, __value) \ | ||
197 | SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) | ||
198 | #define SET_88E_H2CCMD_WOWLAN_ALL_PKT_DROP(__cmd, __value) \ | ||
199 | SET_BITS_TO_LE_1BYTE(__cmd, 4, 1, __value) | ||
200 | #define SET_88E_H2CCMD_WOWLAN_GPIO_ACTIVE(__cmd, __value) \ | ||
201 | SET_BITS_TO_LE_1BYTE(__cmd, 5, 1, __value) | ||
202 | #define SET_88E_H2CCMD_WOWLAN_REKEY_WAKE_UP(__cmd, __value) \ | ||
203 | SET_BITS_TO_LE_1BYTE(__cmd, 6, 1, __value) | ||
204 | #define SET_88E_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(__cmd, __value) \ | ||
205 | SET_BITS_TO_LE_1BYTE(__cmd, 7, 1, __value) | ||
206 | #define SET_88E_H2CCMD_WOWLAN_GPIONUM(__cmd, __value) \ | ||
207 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
208 | #define SET_88E_H2CCMD_WOWLAN_GPIO_DURATION(__cmd, __value) \ | ||
209 | SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) | ||
210 | |||
211 | |||
212 | #define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ | ||
213 | SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) | ||
214 | #define SET_H2CCMD_PWRMODE_PARM_RLBM(__cmd, __value) \ | ||
215 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 4, __value) | ||
216 | #define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__cmd, __value) \ | ||
217 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 4, 4, __value) | ||
218 | #define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__cmd, __value) \ | ||
219 | SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) | ||
220 | #define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__cmd, __value) \ | ||
221 | SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) | ||
222 | #define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __value) \ | ||
223 | SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) | ||
224 | #define GET_88E_H2CCMD_PWRMODE_PARM_MODE(__cmd) \ | ||
225 | LE_BITS_TO_1BYTE(__cmd, 0, 8) | ||
226 | |||
227 | #define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ | ||
228 | SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) | ||
229 | #define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ | ||
230 | SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) | ||
231 | #define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ | ||
232 | SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) | ||
233 | #define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ | ||
234 | SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) | ||
235 | |||
236 | /* AP_OFFLOAD */ | ||
237 | #define SET_H2CCMD_AP_OFFLOAD_ON(__cmd, __value) \ | ||
238 | SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) | ||
239 | #define SET_H2CCMD_AP_OFFLOAD_HIDDEN(__cmd, __value) \ | ||
240 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
241 | #define SET_H2CCMD_AP_OFFLOAD_DENYANY(__cmd, __value) \ | ||
242 | SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) | ||
243 | #define SET_H2CCMD_AP_OFFLOAD_WAKEUP_EVT_RPT(__cmd, __value) \ | ||
244 | SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) | ||
245 | |||
246 | /* Keep Alive Control*/ | ||
247 | #define SET_88E_H2CCMD_KEEP_ALIVE_ENABLE(__cmd, __value) \ | ||
248 | SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) | ||
249 | #define SET_88E_H2CCMD_KEEP_ALIVE_ACCPEPT_USER_DEFINED(__cmd, __value) \ | ||
250 | SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) | ||
251 | #define SET_88E_H2CCMD_KEEP_ALIVE_PERIOD(__cmd, __value) \ | ||
252 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
253 | |||
254 | /*REMOTE_WAKE_CTRL */ | ||
255 | #define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_EN(__cmd, __value) \ | ||
256 | SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) | ||
257 | #if (USE_OLD_WOWLAN_DEBUG_FW == 0) | ||
258 | #define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(__cmd, __value) \ | ||
259 | SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) | ||
260 | #define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_NDP_OFFLOAD_EN(__cmd, __value) \ | ||
261 | SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) | ||
262 | #define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(__cmd, __value) \ | ||
263 | SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) | ||
264 | #else | ||
265 | #define SET_88E_H2_REM_WAKE_ENC_ALG(__cmd, __value) \ | ||
266 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
267 | #define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GROUP_ENC_ALG(__cmd, __value) \ | ||
268 | SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) | ||
269 | #endif | ||
270 | |||
271 | /* GTK_OFFLOAD */ | ||
272 | #define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(__cmd, __value) \ | ||
273 | SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) | ||
274 | #define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(__cmd, __value) \ | ||
275 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
276 | |||
277 | /* AOAC_RSVDPAGE_LOC */ | ||
278 | #define SET_88E_H2CCMD_AOAC_RSVD_LOC_REM_WAKE_CTRL_INFO(__cmd, __value) \ | ||
279 | SET_BITS_TO_LE_1BYTE((__cmd), 0, 8, __value) | ||
280 | #define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(__cmd, __value) \ | ||
281 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
282 | #define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(__cmd, __value) \ | ||
283 | SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) | ||
284 | #define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(__cmd, __value) \ | ||
285 | SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) | ||
286 | #define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(__cmd, __value) \ | ||
287 | SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) | ||
288 | |||
289 | int rtl88e_download_fw(struct ieee80211_hw *hw, | ||
290 | bool buse_wake_on_wlan_fw); | ||
291 | void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, | ||
292 | u32 cmd_len, u8 *p_cmdbuffer); | ||
293 | void rtl88e_firmware_selfreset(struct ieee80211_hw *hw); | ||
294 | void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); | ||
295 | void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, | ||
296 | u8 mstatus); | ||
297 | void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, u8 enable); | ||
298 | void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); | ||
299 | void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); | ||
300 | |||
301 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c new file mode 100644 index 000000000000..b68cae3024fc --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c | |||
@@ -0,0 +1,2530 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../efuse.h" | ||
32 | #include "../base.h" | ||
33 | #include "../regd.h" | ||
34 | #include "../cam.h" | ||
35 | #include "../ps.h" | ||
36 | #include "../pci.h" | ||
37 | #include "reg.h" | ||
38 | #include "def.h" | ||
39 | #include "phy.h" | ||
40 | #include "dm.h" | ||
41 | #include "fw.h" | ||
42 | #include "led.h" | ||
43 | #include "hw.h" | ||
44 | #include "pwrseqcmd.h" | ||
45 | #include "pwrseq.h" | ||
46 | |||
47 | #define LLT_CONFIG 5 | ||
48 | |||
49 | static void _rtl88ee_set_bcn_ctrl_reg(struct ieee80211_hw *hw, | ||
50 | u8 set_bits, u8 clear_bits) | ||
51 | { | ||
52 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
53 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
54 | |||
55 | rtlpci->reg_bcn_ctrl_val |= set_bits; | ||
56 | rtlpci->reg_bcn_ctrl_val &= ~clear_bits; | ||
57 | |||
58 | rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); | ||
59 | } | ||
60 | |||
61 | static void _rtl88ee_stop_tx_beacon(struct ieee80211_hw *hw) | ||
62 | { | ||
63 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
64 | u8 tmp1byte; | ||
65 | |||
66 | tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); | ||
67 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); | ||
68 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); | ||
69 | tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); | ||
70 | tmp1byte &= ~(BIT(0)); | ||
71 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); | ||
72 | } | ||
73 | |||
74 | static void _rtl88ee_resume_tx_beacon(struct ieee80211_hw *hw) | ||
75 | { | ||
76 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
77 | u8 tmp1byte; | ||
78 | |||
79 | tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); | ||
80 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); | ||
81 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); | ||
82 | tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); | ||
83 | tmp1byte |= BIT(0); | ||
84 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); | ||
85 | } | ||
86 | |||
87 | static void _rtl88ee_enable_bcn_sub_func(struct ieee80211_hw *hw) | ||
88 | { | ||
89 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); | ||
90 | } | ||
91 | |||
92 | static void _rtl88ee_return_beacon_queue_skb(struct ieee80211_hw *hw) | ||
93 | { | ||
94 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
95 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
96 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; | ||
97 | |||
98 | while (skb_queue_len(&ring->queue)) { | ||
99 | struct rtl_tx_desc *entry = &ring->desc[ring->idx]; | ||
100 | struct sk_buff *skb = __skb_dequeue(&ring->queue); | ||
101 | |||
102 | pci_unmap_single(rtlpci->pdev, | ||
103 | rtlpriv->cfg->ops->get_desc( | ||
104 | (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), | ||
105 | skb->len, PCI_DMA_TODEVICE); | ||
106 | kfree_skb(skb); | ||
107 | ring->idx = (ring->idx + 1) % ring->entries; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static void _rtl88ee_disable_bcn_sub_func(struct ieee80211_hw *hw) | ||
112 | { | ||
113 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(1), 0); | ||
114 | } | ||
115 | |||
116 | static void _rtl88ee_set_fw_clock_on(struct ieee80211_hw *hw, | ||
117 | u8 rpwm_val, bool need_turn_off_ckk) | ||
118 | { | ||
119 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
120 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
121 | bool support_remote_wake_up; | ||
122 | u32 count = 0, isr_regaddr, content; | ||
123 | bool schedule_timer = need_turn_off_ckk; | ||
124 | |||
125 | rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, | ||
126 | (u8 *)(&support_remote_wake_up)); | ||
127 | if (!rtlhal->fw_ready) | ||
128 | return; | ||
129 | if (!rtlpriv->psc.fw_current_inpsmode) | ||
130 | return; | ||
131 | |||
132 | while (1) { | ||
133 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
134 | if (rtlhal->fw_clk_change_in_progress) { | ||
135 | while (rtlhal->fw_clk_change_in_progress) { | ||
136 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
137 | udelay(100); | ||
138 | if (++count > 1000) | ||
139 | return; | ||
140 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
141 | } | ||
142 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
143 | } else { | ||
144 | rtlhal->fw_clk_change_in_progress = false; | ||
145 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | if (IS_IN_LOW_POWER_STATE_88E(rtlhal->fw_ps_state)) { | ||
150 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, | ||
151 | (u8 *)(&rpwm_val)); | ||
152 | if (FW_PS_IS_ACK(rpwm_val)) { | ||
153 | isr_regaddr = REG_HISR; | ||
154 | content = rtl_read_dword(rtlpriv, isr_regaddr); | ||
155 | while (!(content & IMR_CPWM) && (count < 500)) { | ||
156 | udelay(50); | ||
157 | count++; | ||
158 | content = rtl_read_dword(rtlpriv, isr_regaddr); | ||
159 | } | ||
160 | |||
161 | if (content & IMR_CPWM) { | ||
162 | rtl_write_word(rtlpriv, isr_regaddr, 0x0100); | ||
163 | rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_88E; | ||
164 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
165 | "Receive CPWM INT!!! Set pHalData->FwPSState = %X\n", | ||
166 | rtlhal->fw_ps_state); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
171 | rtlhal->fw_clk_change_in_progress = false; | ||
172 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
173 | if (schedule_timer) { | ||
174 | mod_timer(&rtlpriv->works.fw_clockoff_timer, | ||
175 | jiffies + MSECS(10)); | ||
176 | } | ||
177 | } else { | ||
178 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
179 | rtlhal->fw_clk_change_in_progress = false; | ||
180 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | static void _rtl88ee_set_fw_clock_off(struct ieee80211_hw *hw, | ||
185 | u8 rpwm_val) | ||
186 | { | ||
187 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
188 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
189 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
190 | struct rtl8192_tx_ring *ring; | ||
191 | enum rf_pwrstate rtstate; | ||
192 | bool schedule_timer = false; | ||
193 | u8 queue; | ||
194 | |||
195 | if (!rtlhal->fw_ready) | ||
196 | return; | ||
197 | if (!rtlpriv->psc.fw_current_inpsmode) | ||
198 | return; | ||
199 | if (!rtlhal->allow_sw_to_change_hwclc) | ||
200 | return; | ||
201 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); | ||
202 | if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) | ||
203 | return; | ||
204 | |||
205 | for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { | ||
206 | ring = &rtlpci->tx_ring[queue]; | ||
207 | if (skb_queue_len(&ring->queue)) { | ||
208 | schedule_timer = true; | ||
209 | break; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | if (schedule_timer) { | ||
214 | mod_timer(&rtlpriv->works.fw_clockoff_timer, | ||
215 | jiffies + MSECS(10)); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | if (FW_PS_STATE(rtlhal->fw_ps_state) != | ||
220 | FW_PS_STATE_RF_OFF_LOW_PWR_88E) { | ||
221 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
222 | if (!rtlhal->fw_clk_change_in_progress) { | ||
223 | rtlhal->fw_clk_change_in_progress = true; | ||
224 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
225 | rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); | ||
226 | rtl_write_word(rtlpriv, REG_HISR, 0x0100); | ||
227 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
228 | (u8 *)(&rpwm_val)); | ||
229 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
230 | rtlhal->fw_clk_change_in_progress = false; | ||
231 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
232 | } else { | ||
233 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
234 | mod_timer(&rtlpriv->works.fw_clockoff_timer, | ||
235 | jiffies + MSECS(10)); | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | |||
240 | static void _rtl88ee_set_fw_ps_rf_on(struct ieee80211_hw *hw) | ||
241 | { | ||
242 | u8 rpwm_val = 0; | ||
243 | |||
244 | rpwm_val |= (FW_PS_STATE_RF_OFF_88E | FW_PS_ACK); | ||
245 | _rtl88ee_set_fw_clock_on(hw, rpwm_val, true); | ||
246 | } | ||
247 | |||
248 | static void _rtl88ee_set_fw_ps_rf_off_low_power(struct ieee80211_hw *hw) | ||
249 | { | ||
250 | u8 rpwm_val = 0; | ||
251 | |||
252 | rpwm_val |= FW_PS_STATE_RF_OFF_LOW_PWR_88E; | ||
253 | _rtl88ee_set_fw_clock_off(hw, rpwm_val); | ||
254 | } | ||
255 | |||
256 | void rtl88ee_fw_clk_off_timer_callback(unsigned long data) | ||
257 | { | ||
258 | struct ieee80211_hw *hw = (struct ieee80211_hw *)data; | ||
259 | |||
260 | _rtl88ee_set_fw_ps_rf_off_low_power(hw); | ||
261 | } | ||
262 | |||
263 | static void _rtl88ee_fwlps_leave(struct ieee80211_hw *hw) | ||
264 | { | ||
265 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
266 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
267 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
268 | bool fw_current_inps = false; | ||
269 | u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; | ||
270 | |||
271 | if (ppsc->low_power_enable) { | ||
272 | rpwm_val = (FW_PS_STATE_ALL_ON_88E|FW_PS_ACK);/* RF on */ | ||
273 | _rtl88ee_set_fw_clock_on(hw, rpwm_val, false); | ||
274 | rtlhal->allow_sw_to_change_hwclc = false; | ||
275 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
276 | (u8 *)(&fw_pwrmode)); | ||
277 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
278 | (u8 *)(&fw_current_inps)); | ||
279 | } else { | ||
280 | rpwm_val = FW_PS_STATE_ALL_ON_88E; /* RF on */ | ||
281 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
282 | (u8 *)(&rpwm_val)); | ||
283 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
284 | (u8 *)(&fw_pwrmode)); | ||
285 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
286 | (u8 *)(&fw_current_inps)); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | static void _rtl88ee_fwlps_enter(struct ieee80211_hw *hw) | ||
291 | { | ||
292 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
293 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
294 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
295 | bool fw_current_inps = true; | ||
296 | u8 rpwm_val; | ||
297 | |||
298 | if (ppsc->low_power_enable) { | ||
299 | rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR_88E; /* RF off */ | ||
300 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
301 | (u8 *)(&fw_current_inps)); | ||
302 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
303 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
304 | rtlhal->allow_sw_to_change_hwclc = true; | ||
305 | _rtl88ee_set_fw_clock_off(hw, rpwm_val); | ||
306 | } else { | ||
307 | rpwm_val = FW_PS_STATE_RF_OFF_88E; /* RF off */ | ||
308 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
309 | (u8 *)(&fw_current_inps)); | ||
310 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
311 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
312 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
313 | (u8 *)(&rpwm_val)); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | ||
318 | { | ||
319 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
320 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
321 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
322 | |||
323 | switch (variable) { | ||
324 | case HW_VAR_RCR: | ||
325 | *((u32 *)(val)) = rtlpci->receive_config; | ||
326 | break; | ||
327 | case HW_VAR_RF_STATE: | ||
328 | *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; | ||
329 | break; | ||
330 | case HW_VAR_FWLPS_RF_ON:{ | ||
331 | enum rf_pwrstate rfstate; | ||
332 | u32 val_rcr; | ||
333 | |||
334 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, | ||
335 | (u8 *)(&rfstate)); | ||
336 | if (rfstate == ERFOFF) { | ||
337 | *((bool *)(val)) = true; | ||
338 | } else { | ||
339 | val_rcr = rtl_read_dword(rtlpriv, REG_RCR); | ||
340 | val_rcr &= 0x00070000; | ||
341 | if (val_rcr) | ||
342 | *((bool *)(val)) = false; | ||
343 | else | ||
344 | *((bool *)(val)) = true; | ||
345 | } | ||
346 | break; | ||
347 | } | ||
348 | case HW_VAR_FW_PSMODE_STATUS: | ||
349 | *((bool *)(val)) = ppsc->fw_current_inpsmode; | ||
350 | break; | ||
351 | case HW_VAR_CORRECT_TSF:{ | ||
352 | u64 tsf; | ||
353 | u32 *ptsf_low = (u32 *)&tsf; | ||
354 | u32 *ptsf_high = ((u32 *)&tsf) + 1; | ||
355 | |||
356 | *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); | ||
357 | *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); | ||
358 | |||
359 | *((u64 *)(val)) = tsf; | ||
360 | break; } | ||
361 | default: | ||
362 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
363 | "switch case not process %x\n", variable); | ||
364 | break; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | ||
369 | { | ||
370 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
371 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
372 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
373 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
374 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
375 | u8 idx; | ||
376 | |||
377 | switch (variable) { | ||
378 | case HW_VAR_ETHER_ADDR: | ||
379 | for (idx = 0; idx < ETH_ALEN; idx++) | ||
380 | rtl_write_byte(rtlpriv, (REG_MACID + idx), val[idx]); | ||
381 | break; | ||
382 | case HW_VAR_BASIC_RATE:{ | ||
383 | u16 rate_cfg = ((u16 *)val)[0]; | ||
384 | u8 rate_index = 0; | ||
385 | rate_cfg = rate_cfg & 0x15f; | ||
386 | rate_cfg |= 0x01; | ||
387 | rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); | ||
388 | rtl_write_byte(rtlpriv, REG_RRSR + 1, (rate_cfg >> 8) & 0xff); | ||
389 | while (rate_cfg > 0x1) { | ||
390 | rate_cfg = (rate_cfg >> 1); | ||
391 | rate_index++; | ||
392 | } | ||
393 | rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, rate_index); | ||
394 | break; } | ||
395 | case HW_VAR_BSSID: | ||
396 | for (idx = 0; idx < ETH_ALEN; idx++) | ||
397 | rtl_write_byte(rtlpriv, (REG_BSSID + idx), val[idx]); | ||
398 | break; | ||
399 | case HW_VAR_SIFS: | ||
400 | rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); | ||
401 | rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); | ||
402 | |||
403 | rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); | ||
404 | rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); | ||
405 | |||
406 | if (!mac->ht_enable) | ||
407 | rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, 0x0e0e); | ||
408 | else | ||
409 | rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, | ||
410 | *((u16 *)val)); | ||
411 | break; | ||
412 | case HW_VAR_SLOT_TIME:{ | ||
413 | u8 e_aci; | ||
414 | |||
415 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
416 | "HW_VAR_SLOT_TIME %x\n", val[0]); | ||
417 | |||
418 | rtl_write_byte(rtlpriv, REG_SLOT, val[0]); | ||
419 | |||
420 | for (e_aci = 0; e_aci < AC_MAX; e_aci++) { | ||
421 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, | ||
422 | (u8 *)(&e_aci)); | ||
423 | } | ||
424 | break; } | ||
425 | case HW_VAR_ACK_PREAMBLE:{ | ||
426 | u8 reg_tmp; | ||
427 | u8 short_preamble = (bool) (*(u8 *)val); | ||
428 | reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2); | ||
429 | if (short_preamble) { | ||
430 | reg_tmp |= 0x02; | ||
431 | rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp); | ||
432 | } else { | ||
433 | reg_tmp |= 0xFD; | ||
434 | rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp); | ||
435 | } | ||
436 | break; } | ||
437 | case HW_VAR_WPA_CONFIG: | ||
438 | rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); | ||
439 | break; | ||
440 | case HW_VAR_AMPDU_MIN_SPACE:{ | ||
441 | u8 min_spacing_to_set; | ||
442 | u8 sec_min_space; | ||
443 | |||
444 | min_spacing_to_set = *((u8 *)val); | ||
445 | if (min_spacing_to_set <= 7) { | ||
446 | sec_min_space = 0; | ||
447 | |||
448 | if (min_spacing_to_set < sec_min_space) | ||
449 | min_spacing_to_set = sec_min_space; | ||
450 | |||
451 | mac->min_space_cfg = ((mac->min_space_cfg & | ||
452 | 0xf8) | min_spacing_to_set); | ||
453 | |||
454 | *val = min_spacing_to_set; | ||
455 | |||
456 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
457 | "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", | ||
458 | mac->min_space_cfg); | ||
459 | |||
460 | rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, | ||
461 | mac->min_space_cfg); | ||
462 | } | ||
463 | break; } | ||
464 | case HW_VAR_SHORTGI_DENSITY:{ | ||
465 | u8 density_to_set; | ||
466 | |||
467 | density_to_set = *((u8 *)val); | ||
468 | mac->min_space_cfg |= (density_to_set << 3); | ||
469 | |||
470 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
471 | "Set HW_VAR_SHORTGI_DENSITY: %#x\n", | ||
472 | mac->min_space_cfg); | ||
473 | |||
474 | rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, | ||
475 | mac->min_space_cfg); | ||
476 | break; } | ||
477 | case HW_VAR_AMPDU_FACTOR:{ | ||
478 | u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; | ||
479 | u8 factor; | ||
480 | u8 *reg = NULL; | ||
481 | u8 id = 0; | ||
482 | |||
483 | reg = regtoset_normal; | ||
484 | |||
485 | factor = *((u8 *)val); | ||
486 | if (factor <= 3) { | ||
487 | factor = (1 << (factor + 2)); | ||
488 | if (factor > 0xf) | ||
489 | factor = 0xf; | ||
490 | |||
491 | for (id = 0; id < 4; id++) { | ||
492 | if ((reg[id] & 0xf0) > (factor << 4)) | ||
493 | reg[id] = (reg[id] & 0x0f) | | ||
494 | (factor << 4); | ||
495 | |||
496 | if ((reg[id] & 0x0f) > factor) | ||
497 | reg[id] = (reg[id] & 0xf0) | (factor); | ||
498 | |||
499 | rtl_write_byte(rtlpriv, (REG_AGGLEN_LMT + id), | ||
500 | reg[id]); | ||
501 | } | ||
502 | |||
503 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
504 | "Set HW_VAR_AMPDU_FACTOR: %#x\n", factor); | ||
505 | } | ||
506 | break; } | ||
507 | case HW_VAR_AC_PARAM:{ | ||
508 | u8 e_aci = *((u8 *)val); | ||
509 | rtl88e_dm_init_edca_turbo(hw); | ||
510 | |||
511 | if (rtlpci->acm_method != eAcmWay2_SW) | ||
512 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, | ||
513 | (u8 *)(&e_aci)); | ||
514 | break; } | ||
515 | case HW_VAR_ACM_CTRL:{ | ||
516 | u8 e_aci = *((u8 *)val); | ||
517 | union aci_aifsn *p_aci_aifsn = | ||
518 | (union aci_aifsn *)(&(mac->ac[0].aifs)); | ||
519 | u8 acm = p_aci_aifsn->f.acm; | ||
520 | u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); | ||
521 | |||
522 | acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); | ||
523 | |||
524 | if (acm) { | ||
525 | switch (e_aci) { | ||
526 | case AC0_BE: | ||
527 | acm_ctrl |= ACMHW_BEQEN; | ||
528 | break; | ||
529 | case AC2_VI: | ||
530 | acm_ctrl |= ACMHW_VIQEN; | ||
531 | break; | ||
532 | case AC3_VO: | ||
533 | acm_ctrl |= ACMHW_VOQEN; | ||
534 | break; | ||
535 | default: | ||
536 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
537 | "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", | ||
538 | acm); | ||
539 | break; | ||
540 | } | ||
541 | } else { | ||
542 | switch (e_aci) { | ||
543 | case AC0_BE: | ||
544 | acm_ctrl &= (~ACMHW_BEQEN); | ||
545 | break; | ||
546 | case AC2_VI: | ||
547 | acm_ctrl &= (~ACMHW_VIQEN); | ||
548 | break; | ||
549 | case AC3_VO: | ||
550 | acm_ctrl &= (~ACMHW_BEQEN); | ||
551 | break; | ||
552 | default: | ||
553 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
554 | "switch case not process\n"); | ||
555 | break; | ||
556 | } | ||
557 | } | ||
558 | |||
559 | RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, | ||
560 | "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", | ||
561 | acm_ctrl); | ||
562 | rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); | ||
563 | break; } | ||
564 | case HW_VAR_RCR: | ||
565 | rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); | ||
566 | rtlpci->receive_config = ((u32 *)(val))[0]; | ||
567 | break; | ||
568 | case HW_VAR_RETRY_LIMIT:{ | ||
569 | u8 retry_limit = ((u8 *)(val))[0]; | ||
570 | |||
571 | rtl_write_word(rtlpriv, REG_RL, | ||
572 | retry_limit << RETRY_LIMIT_SHORT_SHIFT | | ||
573 | retry_limit << RETRY_LIMIT_LONG_SHIFT); | ||
574 | break; } | ||
575 | case HW_VAR_DUAL_TSF_RST: | ||
576 | rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); | ||
577 | break; | ||
578 | case HW_VAR_EFUSE_BYTES: | ||
579 | rtlefuse->efuse_usedbytes = *((u16 *)val); | ||
580 | break; | ||
581 | case HW_VAR_EFUSE_USAGE: | ||
582 | rtlefuse->efuse_usedpercentage = *((u8 *)val); | ||
583 | break; | ||
584 | case HW_VAR_IO_CMD: | ||
585 | rtl88e_phy_set_io_cmd(hw, (*(enum io_type *)val)); | ||
586 | break; | ||
587 | case HW_VAR_SET_RPWM:{ | ||
588 | u8 rpwm_val; | ||
589 | |||
590 | rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); | ||
591 | udelay(1); | ||
592 | |||
593 | if (rpwm_val & BIT(7)) { | ||
594 | rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, | ||
595 | (*(u8 *)val)); | ||
596 | } else { | ||
597 | rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, | ||
598 | ((*(u8 *)val) | BIT(7))); | ||
599 | } | ||
600 | break; } | ||
601 | case HW_VAR_H2C_FW_PWRMODE: | ||
602 | rtl88e_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); | ||
603 | break; | ||
604 | case HW_VAR_FW_PSMODE_STATUS: | ||
605 | ppsc->fw_current_inpsmode = *((bool *)val); | ||
606 | break; | ||
607 | case HW_VAR_RESUME_CLK_ON: | ||
608 | _rtl88ee_set_fw_ps_rf_on(hw); | ||
609 | break; | ||
610 | case HW_VAR_FW_LPS_ACTION:{ | ||
611 | bool enter_fwlps = *((bool *)val); | ||
612 | |||
613 | if (enter_fwlps) | ||
614 | _rtl88ee_fwlps_enter(hw); | ||
615 | else | ||
616 | _rtl88ee_fwlps_leave(hw); | ||
617 | break; } | ||
618 | case HW_VAR_H2C_FW_JOINBSSRPT:{ | ||
619 | u8 mstatus = (*(u8 *)val); | ||
620 | u8 tmp, tmp_reg422, uval; | ||
621 | u8 count = 0, dlbcn_count = 0; | ||
622 | bool recover = false; | ||
623 | |||
624 | if (mstatus == RT_MEDIA_CONNECT) { | ||
625 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); | ||
626 | |||
627 | tmp = rtl_read_byte(rtlpriv, REG_CR + 1); | ||
628 | rtl_write_byte(rtlpriv, REG_CR + 1, (tmp | BIT(0))); | ||
629 | |||
630 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); | ||
631 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0); | ||
632 | |||
633 | tmp_reg422 = rtl_read_byte(rtlpriv, | ||
634 | REG_FWHW_TXQ_CTRL + 2); | ||
635 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, | ||
636 | tmp_reg422 & (~BIT(6))); | ||
637 | if (tmp_reg422 & BIT(6)) | ||
638 | recover = true; | ||
639 | |||
640 | do { | ||
641 | uval = rtl_read_byte(rtlpriv, REG_TDECTRL+2); | ||
642 | rtl_write_byte(rtlpriv, REG_TDECTRL+2, | ||
643 | (uval | BIT(0))); | ||
644 | _rtl88ee_return_beacon_queue_skb(hw); | ||
645 | |||
646 | rtl88e_set_fw_rsvdpagepkt(hw, 0); | ||
647 | uval = rtl_read_byte(rtlpriv, REG_TDECTRL+2); | ||
648 | count = 0; | ||
649 | while (!(uval & BIT(0)) && count < 20) { | ||
650 | count++; | ||
651 | udelay(10); | ||
652 | uval = rtl_read_byte(rtlpriv, | ||
653 | REG_TDECTRL+2); | ||
654 | } | ||
655 | dlbcn_count++; | ||
656 | } while (!(uval & BIT(0)) && dlbcn_count < 5); | ||
657 | |||
658 | if (uval & BIT(0)) | ||
659 | rtl_write_byte(rtlpriv, REG_TDECTRL+2, BIT(0)); | ||
660 | |||
661 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); | ||
662 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); | ||
663 | |||
664 | if (recover) { | ||
665 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, | ||
666 | tmp_reg422); | ||
667 | } | ||
668 | rtl_write_byte(rtlpriv, REG_CR + 1, (tmp & ~(BIT(0)))); | ||
669 | } | ||
670 | rtl88e_set_fw_joinbss_report_cmd(hw, (*(u8 *)val)); | ||
671 | break; } | ||
672 | case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: | ||
673 | rtl88e_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); | ||
674 | break; | ||
675 | case HW_VAR_AID:{ | ||
676 | u16 u2btmp; | ||
677 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); | ||
678 | u2btmp &= 0xC000; | ||
679 | rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | | ||
680 | mac->assoc_id)); | ||
681 | break; } | ||
682 | case HW_VAR_CORRECT_TSF:{ | ||
683 | u8 btype_ibss = ((u8 *)(val))[0]; | ||
684 | |||
685 | if (btype_ibss == true) | ||
686 | _rtl88ee_stop_tx_beacon(hw); | ||
687 | |||
688 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); | ||
689 | |||
690 | rtl_write_dword(rtlpriv, REG_TSFTR, | ||
691 | (u32) (mac->tsf & 0xffffffff)); | ||
692 | rtl_write_dword(rtlpriv, REG_TSFTR + 4, | ||
693 | (u32) ((mac->tsf >> 32) & 0xffffffff)); | ||
694 | |||
695 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); | ||
696 | |||
697 | if (btype_ibss == true) | ||
698 | _rtl88ee_resume_tx_beacon(hw); | ||
699 | break; } | ||
700 | default: | ||
701 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
702 | "switch case not process %x\n", variable); | ||
703 | break; | ||
704 | } | ||
705 | } | ||
706 | |||
707 | static bool _rtl88ee_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) | ||
708 | { | ||
709 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
710 | bool status = true; | ||
711 | long count = 0; | ||
712 | u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | | ||
713 | _LLT_OP(_LLT_WRITE_ACCESS); | ||
714 | |||
715 | rtl_write_dword(rtlpriv, REG_LLT_INIT, value); | ||
716 | |||
717 | do { | ||
718 | value = rtl_read_dword(rtlpriv, REG_LLT_INIT); | ||
719 | if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) | ||
720 | break; | ||
721 | |||
722 | if (count > POLLING_LLT_THRESHOLD) { | ||
723 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
724 | "Failed to polling write LLT done at address %d!\n", | ||
725 | address); | ||
726 | status = false; | ||
727 | break; | ||
728 | } | ||
729 | } while (++count); | ||
730 | |||
731 | return status; | ||
732 | } | ||
733 | |||
734 | static bool _rtl88ee_llt_table_init(struct ieee80211_hw *hw) | ||
735 | { | ||
736 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
737 | unsigned short i; | ||
738 | u8 txpktbuf_bndy; | ||
739 | u8 maxpage; | ||
740 | bool status; | ||
741 | |||
742 | maxpage = 0xAF; | ||
743 | txpktbuf_bndy = 0xAB; | ||
744 | |||
745 | rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x01); | ||
746 | rtl_write_dword(rtlpriv, REG_RQPN, 0x80730d29); | ||
747 | |||
748 | |||
749 | rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x25FF0000 | txpktbuf_bndy)); | ||
750 | rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); | ||
751 | |||
752 | rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); | ||
753 | rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); | ||
754 | |||
755 | rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); | ||
756 | rtl_write_byte(rtlpriv, REG_PBP, 0x11); | ||
757 | rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); | ||
758 | |||
759 | for (i = 0; i < (txpktbuf_bndy - 1); i++) { | ||
760 | status = _rtl88ee_llt_write(hw, i, i + 1); | ||
761 | if (true != status) | ||
762 | return status; | ||
763 | } | ||
764 | |||
765 | status = _rtl88ee_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); | ||
766 | if (true != status) | ||
767 | return status; | ||
768 | |||
769 | for (i = txpktbuf_bndy; i < maxpage; i++) { | ||
770 | status = _rtl88ee_llt_write(hw, i, (i + 1)); | ||
771 | if (true != status) | ||
772 | return status; | ||
773 | } | ||
774 | |||
775 | status = _rtl88ee_llt_write(hw, maxpage, txpktbuf_bndy); | ||
776 | if (true != status) | ||
777 | return status; | ||
778 | |||
779 | return true; | ||
780 | } | ||
781 | |||
782 | static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw) | ||
783 | { | ||
784 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
785 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
786 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
787 | struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); | ||
788 | |||
789 | if (rtlpriv->rtlhal.up_first_time) | ||
790 | return; | ||
791 | |||
792 | if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) | ||
793 | rtl88ee_sw_led_on(hw, pLed0); | ||
794 | else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) | ||
795 | rtl88ee_sw_led_on(hw, pLed0); | ||
796 | else | ||
797 | rtl88ee_sw_led_off(hw, pLed0); | ||
798 | } | ||
799 | |||
800 | static bool _rtl88ee_init_mac(struct ieee80211_hw *hw) | ||
801 | { | ||
802 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
803 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
804 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
805 | u8 bytetmp; | ||
806 | u16 wordtmp; | ||
807 | |||
808 | /*Disable XTAL OUTPUT for power saving. YJ, add, 111206. */ | ||
809 | bytetmp = rtl_read_byte(rtlpriv, REG_XCK_OUT_CTRL) & (~BIT(0)); | ||
810 | rtl_write_byte(rtlpriv, REG_XCK_OUT_CTRL, bytetmp); | ||
811 | /*Auto Power Down to CHIP-off State*/ | ||
812 | bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7)); | ||
813 | rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); | ||
814 | |||
815 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); | ||
816 | /* HW Power on sequence */ | ||
817 | if (!rtl88_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, | ||
818 | PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, | ||
819 | Rtl8188E_NIC_ENABLE_FLOW)) { | ||
820 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
821 | "init MAC Fail as rtl88_hal_pwrseqcmdparsing\n"); | ||
822 | return false; | ||
823 | } | ||
824 | |||
825 | bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4); | ||
826 | rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp); | ||
827 | |||
828 | bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2); | ||
829 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp|BIT(2)); | ||
830 | |||
831 | bytetmp = rtl_read_byte(rtlpriv, REG_WATCH_DOG+1); | ||
832 | rtl_write_byte(rtlpriv, REG_WATCH_DOG+1, bytetmp|BIT(7)); | ||
833 | |||
834 | bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1); | ||
835 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1, bytetmp|BIT(1)); | ||
836 | |||
837 | bytetmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL); | ||
838 | rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, bytetmp|BIT(1)|BIT(0)); | ||
839 | rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL+1, 2); | ||
840 | rtl_write_word(rtlpriv, REG_TX_RPT_TIME, 0xcdf0); | ||
841 | |||
842 | /*Add for wake up online*/ | ||
843 | bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); | ||
844 | |||
845 | rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp|BIT(3)); | ||
846 | bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG+1); | ||
847 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+1, (bytetmp & (~BIT(4)))); | ||
848 | rtl_write_byte(rtlpriv, 0x367, 0x80); | ||
849 | |||
850 | rtl_write_word(rtlpriv, REG_CR, 0x2ff); | ||
851 | rtl_write_byte(rtlpriv, REG_CR+1, 0x06); | ||
852 | rtl_write_byte(rtlpriv, REG_CR+2, 0x00); | ||
853 | |||
854 | if (!rtlhal->mac_func_enable) { | ||
855 | if (_rtl88ee_llt_table_init(hw) == false) { | ||
856 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
857 | "LLT table init fail\n"); | ||
858 | return false; | ||
859 | } | ||
860 | } | ||
861 | |||
862 | |||
863 | rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); | ||
864 | rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); | ||
865 | |||
866 | wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); | ||
867 | wordtmp &= 0xf; | ||
868 | wordtmp |= 0xE771; | ||
869 | rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); | ||
870 | |||
871 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
872 | rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xffff); | ||
873 | rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); | ||
874 | |||
875 | rtl_write_dword(rtlpriv, REG_BCNQ_DESA, | ||
876 | ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & | ||
877 | DMA_BIT_MASK(32)); | ||
878 | rtl_write_dword(rtlpriv, REG_MGQ_DESA, | ||
879 | (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & | ||
880 | DMA_BIT_MASK(32)); | ||
881 | rtl_write_dword(rtlpriv, REG_VOQ_DESA, | ||
882 | (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); | ||
883 | rtl_write_dword(rtlpriv, REG_VIQ_DESA, | ||
884 | (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); | ||
885 | rtl_write_dword(rtlpriv, REG_BEQ_DESA, | ||
886 | (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); | ||
887 | rtl_write_dword(rtlpriv, REG_BKQ_DESA, | ||
888 | (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); | ||
889 | rtl_write_dword(rtlpriv, REG_HQ_DESA, | ||
890 | (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & | ||
891 | DMA_BIT_MASK(32)); | ||
892 | rtl_write_dword(rtlpriv, REG_RX_DESA, | ||
893 | (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & | ||
894 | DMA_BIT_MASK(32)); | ||
895 | |||
896 | /* if we want to support 64 bit DMA, we should set it here, | ||
897 | * but at the moment we do not support 64 bit DMA | ||
898 | */ | ||
899 | |||
900 | rtl_write_dword(rtlpriv, REG_INT_MIG, 0); | ||
901 | |||
902 | rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); | ||
903 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0);/*Enable RX DMA */ | ||
904 | |||
905 | if (rtlhal->earlymode_enable) {/*Early mode enable*/ | ||
906 | bytetmp = rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL); | ||
907 | bytetmp |= 0x1f; | ||
908 | rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, bytetmp); | ||
909 | rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL+3, 0x81); | ||
910 | } | ||
911 | _rtl88ee_gen_refresh_led_state(hw); | ||
912 | return true; | ||
913 | } | ||
914 | |||
915 | static void _rtl88ee_hw_configure(struct ieee80211_hw *hw) | ||
916 | { | ||
917 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
918 | u32 reg_prsr; | ||
919 | |||
920 | reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; | ||
921 | |||
922 | rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr); | ||
923 | rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); | ||
924 | } | ||
925 | |||
926 | static void _rtl88ee_enable_aspm_back_door(struct ieee80211_hw *hw) | ||
927 | { | ||
928 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
929 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
930 | u8 tmp1byte = 0; | ||
931 | u32 tmp4Byte = 0, count; | ||
932 | |||
933 | rtl_write_word(rtlpriv, 0x354, 0x8104); | ||
934 | rtl_write_word(rtlpriv, 0x358, 0x24); | ||
935 | |||
936 | rtl_write_word(rtlpriv, 0x350, 0x70c); | ||
937 | rtl_write_byte(rtlpriv, 0x352, 0x2); | ||
938 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
939 | count = 0; | ||
940 | while (tmp1byte && count < 20) { | ||
941 | udelay(10); | ||
942 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
943 | count++; | ||
944 | } | ||
945 | if (0 == tmp1byte) { | ||
946 | tmp4Byte = rtl_read_dword(rtlpriv, 0x34c); | ||
947 | rtl_write_dword(rtlpriv, 0x348, tmp4Byte|BIT(31)); | ||
948 | rtl_write_word(rtlpriv, 0x350, 0xf70c); | ||
949 | rtl_write_byte(rtlpriv, 0x352, 0x1); | ||
950 | } | ||
951 | |||
952 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
953 | count = 0; | ||
954 | while (tmp1byte && count < 20) { | ||
955 | udelay(10); | ||
956 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
957 | count++; | ||
958 | } | ||
959 | |||
960 | rtl_write_word(rtlpriv, 0x350, 0x718); | ||
961 | rtl_write_byte(rtlpriv, 0x352, 0x2); | ||
962 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
963 | count = 0; | ||
964 | while (tmp1byte && count < 20) { | ||
965 | udelay(10); | ||
966 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
967 | count++; | ||
968 | } | ||
969 | if (ppsc->support_backdoor || (0 == tmp1byte)) { | ||
970 | tmp4Byte = rtl_read_dword(rtlpriv, 0x34c); | ||
971 | rtl_write_dword(rtlpriv, 0x348, tmp4Byte|BIT(11)|BIT(12)); | ||
972 | rtl_write_word(rtlpriv, 0x350, 0xf718); | ||
973 | rtl_write_byte(rtlpriv, 0x352, 0x1); | ||
974 | } | ||
975 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
976 | count = 0; | ||
977 | while (tmp1byte && count < 20) { | ||
978 | udelay(10); | ||
979 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
980 | count++; | ||
981 | } | ||
982 | } | ||
983 | |||
984 | void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw) | ||
985 | { | ||
986 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
987 | u8 sec_reg_value; | ||
988 | |||
989 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
990 | "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", | ||
991 | rtlpriv->sec.pairwise_enc_algorithm, | ||
992 | rtlpriv->sec.group_enc_algorithm); | ||
993 | |||
994 | if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { | ||
995 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
996 | "not open hw encryption\n"); | ||
997 | return; | ||
998 | } | ||
999 | sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; | ||
1000 | |||
1001 | if (rtlpriv->sec.use_defaultkey) { | ||
1002 | sec_reg_value |= SCR_TXUSEDK; | ||
1003 | sec_reg_value |= SCR_RXUSEDK; | ||
1004 | } | ||
1005 | |||
1006 | sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); | ||
1007 | |||
1008 | rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); | ||
1009 | |||
1010 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
1011 | "The SECR-value %x\n", sec_reg_value); | ||
1012 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); | ||
1013 | } | ||
1014 | |||
1015 | int rtl88ee_hw_init(struct ieee80211_hw *hw) | ||
1016 | { | ||
1017 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1018 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1019 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1020 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1021 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1022 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1023 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1024 | bool rtstatus = true; | ||
1025 | int err = 0; | ||
1026 | u8 tmp_u1b, u1byte; | ||
1027 | |||
1028 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Rtl8188EE hw init\n"); | ||
1029 | rtlpriv->rtlhal.being_init_adapter = true; | ||
1030 | rtlpriv->intf_ops->disable_aspm(hw); | ||
1031 | |||
1032 | tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1); | ||
1033 | u1byte = rtl_read_byte(rtlpriv, REG_CR); | ||
1034 | if ((tmp_u1b & BIT(3)) && (u1byte != 0 && u1byte != 0xEA)) { | ||
1035 | rtlhal->mac_func_enable = true; | ||
1036 | } else { | ||
1037 | rtlhal->mac_func_enable = false; | ||
1038 | rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E; | ||
1039 | } | ||
1040 | |||
1041 | rtstatus = _rtl88ee_init_mac(hw); | ||
1042 | if (rtstatus != true) { | ||
1043 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); | ||
1044 | err = 1; | ||
1045 | return err; | ||
1046 | } | ||
1047 | |||
1048 | err = rtl88e_download_fw(hw, false); | ||
1049 | if (err) { | ||
1050 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1051 | "Failed to download FW. Init HW without FW now..\n"); | ||
1052 | err = 1; | ||
1053 | rtlhal->fw_ready = false; | ||
1054 | return err; | ||
1055 | } else { | ||
1056 | rtlhal->fw_ready = true; | ||
1057 | } | ||
1058 | /*fw related variable initialize */ | ||
1059 | rtlhal->last_hmeboxnum = 0; | ||
1060 | rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E; | ||
1061 | rtlhal->fw_clk_change_in_progress = false; | ||
1062 | rtlhal->allow_sw_to_change_hwclc = false; | ||
1063 | ppsc->fw_current_inpsmode = false; | ||
1064 | |||
1065 | rtl88e_phy_mac_config(hw); | ||
1066 | /* because last function modifies RCR, we update | ||
1067 | * rcr var here, or TP will be unstable for receive_config | ||
1068 | * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx | ||
1069 | * RCR_APP_ICV will cause mac80211 disassoc for cisco 1252 | ||
1070 | */ | ||
1071 | rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); | ||
1072 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
1073 | |||
1074 | rtl88e_phy_bb_config(hw); | ||
1075 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); | ||
1076 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); | ||
1077 | |||
1078 | rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; | ||
1079 | rtl88e_phy_rf_config(hw); | ||
1080 | |||
1081 | rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, | ||
1082 | RF_CHNLBW, RFREG_OFFSET_MASK); | ||
1083 | rtlphy->rfreg_chnlval[0] = rtlphy->rfreg_chnlval[0] & 0xfff00fff; | ||
1084 | |||
1085 | _rtl88ee_hw_configure(hw); | ||
1086 | rtl_cam_reset_all_entry(hw); | ||
1087 | rtl88ee_enable_hw_security_config(hw); | ||
1088 | |||
1089 | rtlhal->mac_func_enable = true; | ||
1090 | ppsc->rfpwr_state = ERFON; | ||
1091 | |||
1092 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); | ||
1093 | _rtl88ee_enable_aspm_back_door(hw); | ||
1094 | rtlpriv->intf_ops->enable_aspm(hw); | ||
1095 | |||
1096 | if (ppsc->rfpwr_state == ERFON) { | ||
1097 | if ((rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) || | ||
1098 | ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) && | ||
1099 | (rtlhal->oem_id == RT_CID_819x_HP))) { | ||
1100 | rtl88e_phy_set_rfpath_switch(hw, true); | ||
1101 | rtlpriv->dm.fat_table.rx_idle_ant = MAIN_ANT; | ||
1102 | } else { | ||
1103 | rtl88e_phy_set_rfpath_switch(hw, false); | ||
1104 | rtlpriv->dm.fat_table.rx_idle_ant = AUX_ANT; | ||
1105 | } | ||
1106 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1107 | "rx idle ant %s\n", | ||
1108 | (rtlpriv->dm.fat_table.rx_idle_ant == MAIN_ANT) ? | ||
1109 | ("MAIN_ANT") : ("AUX_ANT")); | ||
1110 | |||
1111 | if (rtlphy->iqk_initialized) { | ||
1112 | rtl88e_phy_iq_calibrate(hw, true); | ||
1113 | } else { | ||
1114 | rtl88e_phy_iq_calibrate(hw, false); | ||
1115 | rtlphy->iqk_initialized = true; | ||
1116 | } | ||
1117 | rtl88e_dm_check_txpower_tracking(hw); | ||
1118 | rtl88e_phy_lc_calibrate(hw); | ||
1119 | } | ||
1120 | |||
1121 | tmp_u1b = efuse_read_1byte(hw, 0x1FA); | ||
1122 | if (!(tmp_u1b & BIT(0))) { | ||
1123 | rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); | ||
1124 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path A\n"); | ||
1125 | } | ||
1126 | |||
1127 | if (!(tmp_u1b & BIT(4))) { | ||
1128 | tmp_u1b = rtl_read_byte(rtlpriv, 0x16); | ||
1129 | tmp_u1b &= 0x0F; | ||
1130 | rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80); | ||
1131 | udelay(10); | ||
1132 | rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90); | ||
1133 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "under 1.5V\n"); | ||
1134 | } | ||
1135 | rtl_write_byte(rtlpriv, REG_NAV_CTRL+2, ((30000+127)/128)); | ||
1136 | rtl88e_dm_init(hw); | ||
1137 | rtlpriv->rtlhal.being_init_adapter = false; | ||
1138 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "end of Rtl8188EE hw init %x\n", | ||
1139 | err); | ||
1140 | return 0; | ||
1141 | } | ||
1142 | |||
1143 | static enum version_8188e _rtl88ee_read_chip_version(struct ieee80211_hw *hw) | ||
1144 | { | ||
1145 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1146 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1147 | enum version_8188e version = VERSION_UNKNOWN; | ||
1148 | u32 value32; | ||
1149 | |||
1150 | value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); | ||
1151 | if (value32 & TRP_VAUX_EN) { | ||
1152 | version = (enum version_8188e) VERSION_TEST_CHIP_88E; | ||
1153 | } else { | ||
1154 | version = NORMAL_CHIP; | ||
1155 | version = version | ((value32 & TYPE_ID) ? RF_TYPE_2T2R : 0); | ||
1156 | version = version | ((value32 & VENDOR_ID) ? | ||
1157 | CHIP_VENDOR_UMC : 0); | ||
1158 | } | ||
1159 | |||
1160 | rtlphy->rf_type = RF_1T1R; | ||
1161 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1162 | "Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? | ||
1163 | "RF_2T2R" : "RF_1T1R"); | ||
1164 | |||
1165 | return version; | ||
1166 | } | ||
1167 | |||
1168 | static int _rtl88ee_set_media_status(struct ieee80211_hw *hw, | ||
1169 | enum nl80211_iftype type) | ||
1170 | { | ||
1171 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1172 | u8 bt_msr = rtl_read_byte(rtlpriv, MSR); | ||
1173 | enum led_ctl_mode ledaction = LED_CTL_NO_LINK; | ||
1174 | bt_msr &= 0xfc; | ||
1175 | |||
1176 | if (type == NL80211_IFTYPE_UNSPECIFIED || | ||
1177 | type == NL80211_IFTYPE_STATION) { | ||
1178 | _rtl88ee_stop_tx_beacon(hw); | ||
1179 | _rtl88ee_enable_bcn_sub_func(hw); | ||
1180 | } else if (type == NL80211_IFTYPE_ADHOC || | ||
1181 | type == NL80211_IFTYPE_AP || | ||
1182 | type == NL80211_IFTYPE_MESH_POINT) { | ||
1183 | _rtl88ee_resume_tx_beacon(hw); | ||
1184 | _rtl88ee_disable_bcn_sub_func(hw); | ||
1185 | } else { | ||
1186 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1187 | "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", | ||
1188 | type); | ||
1189 | } | ||
1190 | |||
1191 | switch (type) { | ||
1192 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1193 | bt_msr |= MSR_NOLINK; | ||
1194 | ledaction = LED_CTL_LINK; | ||
1195 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1196 | "Set Network type to NO LINK!\n"); | ||
1197 | break; | ||
1198 | case NL80211_IFTYPE_ADHOC: | ||
1199 | bt_msr |= MSR_ADHOC; | ||
1200 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1201 | "Set Network type to Ad Hoc!\n"); | ||
1202 | break; | ||
1203 | case NL80211_IFTYPE_STATION: | ||
1204 | bt_msr |= MSR_INFRA; | ||
1205 | ledaction = LED_CTL_LINK; | ||
1206 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1207 | "Set Network type to STA!\n"); | ||
1208 | break; | ||
1209 | case NL80211_IFTYPE_AP: | ||
1210 | bt_msr |= MSR_AP; | ||
1211 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1212 | "Set Network type to AP!\n"); | ||
1213 | break; | ||
1214 | case NL80211_IFTYPE_MESH_POINT: | ||
1215 | bt_msr |= MSR_ADHOC; | ||
1216 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1217 | "Set Network type to Mesh Point!\n"); | ||
1218 | break; | ||
1219 | default: | ||
1220 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1221 | "Network type %d not support!\n", type); | ||
1222 | return 1; | ||
1223 | } | ||
1224 | |||
1225 | rtl_write_byte(rtlpriv, (MSR), bt_msr); | ||
1226 | rtlpriv->cfg->ops->led_control(hw, ledaction); | ||
1227 | if ((bt_msr & 0xfc) == MSR_AP) | ||
1228 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); | ||
1229 | else | ||
1230 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); | ||
1231 | return 0; | ||
1232 | } | ||
1233 | |||
1234 | void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) | ||
1235 | { | ||
1236 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1237 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1238 | u32 reg_rcr = rtlpci->receive_config; | ||
1239 | |||
1240 | if (rtlpriv->psc.rfpwr_state != ERFON) | ||
1241 | return; | ||
1242 | |||
1243 | if (check_bssid == true) { | ||
1244 | reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); | ||
1245 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, | ||
1246 | (u8 *)(®_rcr)); | ||
1247 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); | ||
1248 | } else if (check_bssid == false) { | ||
1249 | reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); | ||
1250 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0); | ||
1251 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1252 | HW_VAR_RCR, (u8 *)(®_rcr)); | ||
1253 | } | ||
1254 | } | ||
1255 | |||
1256 | int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | ||
1257 | { | ||
1258 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1259 | |||
1260 | if (_rtl88ee_set_media_status(hw, type)) | ||
1261 | return -EOPNOTSUPP; | ||
1262 | |||
1263 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { | ||
1264 | if (type != NL80211_IFTYPE_AP && | ||
1265 | type != NL80211_IFTYPE_MESH_POINT) | ||
1266 | rtl88ee_set_check_bssid(hw, true); | ||
1267 | } else { | ||
1268 | rtl88ee_set_check_bssid(hw, false); | ||
1269 | } | ||
1270 | |||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1274 | /* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ | ||
1275 | void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci) | ||
1276 | { | ||
1277 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1278 | rtl88e_dm_init_edca_turbo(hw); | ||
1279 | switch (aci) { | ||
1280 | case AC1_BK: | ||
1281 | rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); | ||
1282 | break; | ||
1283 | case AC0_BE: | ||
1284 | break; | ||
1285 | case AC2_VI: | ||
1286 | rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); | ||
1287 | break; | ||
1288 | case AC3_VO: | ||
1289 | rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); | ||
1290 | break; | ||
1291 | default: | ||
1292 | RT_ASSERT(false, "invalid aci: %d !\n", aci); | ||
1293 | break; | ||
1294 | } | ||
1295 | } | ||
1296 | |||
1297 | void rtl88ee_enable_interrupt(struct ieee80211_hw *hw) | ||
1298 | { | ||
1299 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1300 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1301 | |||
1302 | rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); | ||
1303 | rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); | ||
1304 | rtlpci->irq_enabled = true; | ||
1305 | /* there are some C2H CMDs have been sent before system interrupt | ||
1306 | * is enabled, e.g., C2H, CPWM. | ||
1307 | * So we need to clear all C2H events that FW has notified, otherwise | ||
1308 | * FW won't schedule any commands anymore. | ||
1309 | */ | ||
1310 | rtl_write_byte(rtlpriv, REG_C2HEVT_CLEAR, 0); | ||
1311 | /*enable system interrupt*/ | ||
1312 | rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF); | ||
1313 | } | ||
1314 | |||
1315 | void rtl88ee_disable_interrupt(struct ieee80211_hw *hw) | ||
1316 | { | ||
1317 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1318 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1319 | |||
1320 | rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); | ||
1321 | rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); | ||
1322 | rtlpci->irq_enabled = false; | ||
1323 | synchronize_irq(rtlpci->pdev->irq); | ||
1324 | } | ||
1325 | |||
1326 | static void _rtl88ee_poweroff_adapter(struct ieee80211_hw *hw) | ||
1327 | { | ||
1328 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1329 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1330 | u8 u1b_tmp; | ||
1331 | u32 count = 0; | ||
1332 | rtlhal->mac_func_enable = false; | ||
1333 | rtlpriv->intf_ops->enable_aspm(hw); | ||
1334 | |||
1335 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "POWER OFF adapter\n"); | ||
1336 | u1b_tmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL); | ||
1337 | rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, u1b_tmp & (~BIT(1))); | ||
1338 | |||
1339 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); | ||
1340 | while (!(u1b_tmp & BIT(1)) && (count++ < 100)) { | ||
1341 | udelay(10); | ||
1342 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); | ||
1343 | count++; | ||
1344 | } | ||
1345 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0xFF); | ||
1346 | |||
1347 | rtl88_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, | ||
1348 | PWR_INTF_PCI_MSK, | ||
1349 | Rtl8188E_NIC_LPS_ENTER_FLOW); | ||
1350 | |||
1351 | rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); | ||
1352 | |||
1353 | if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready) | ||
1354 | rtl88e_firmware_selfreset(hw); | ||
1355 | |||
1356 | u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); | ||
1357 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); | ||
1358 | rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); | ||
1359 | |||
1360 | u1b_tmp = rtl_read_byte(rtlpriv, REG_32K_CTRL); | ||
1361 | rtl_write_byte(rtlpriv, REG_32K_CTRL, (u1b_tmp & (~BIT(0)))); | ||
1362 | |||
1363 | rtl88_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, | ||
1364 | PWR_INTF_PCI_MSK, Rtl8188E_NIC_DISABLE_FLOW); | ||
1365 | |||
1366 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); | ||
1367 | rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(3)))); | ||
1368 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); | ||
1369 | rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(3))); | ||
1370 | |||
1371 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E); | ||
1372 | |||
1373 | u1b_tmp = rtl_read_byte(rtlpriv, GPIO_IN); | ||
1374 | rtl_write_byte(rtlpriv, GPIO_OUT, u1b_tmp); | ||
1375 | rtl_write_byte(rtlpriv, GPIO_IO_SEL, 0x7F); | ||
1376 | |||
1377 | u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); | ||
1378 | rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL, (u1b_tmp << 4) | u1b_tmp); | ||
1379 | u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL+1); | ||
1380 | rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL+1, u1b_tmp | 0x0F); | ||
1381 | |||
1382 | rtl_write_dword(rtlpriv, REG_GPIO_IO_SEL_2+2, 0x00080808); | ||
1383 | } | ||
1384 | |||
1385 | void rtl88ee_card_disable(struct ieee80211_hw *hw) | ||
1386 | { | ||
1387 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1388 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1389 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1390 | enum nl80211_iftype opmode; | ||
1391 | |||
1392 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RTL8188ee card disable\n"); | ||
1393 | |||
1394 | mac->link_state = MAC80211_NOLINK; | ||
1395 | opmode = NL80211_IFTYPE_UNSPECIFIED; | ||
1396 | |||
1397 | _rtl88ee_set_media_status(hw, opmode); | ||
1398 | |||
1399 | if (rtlpriv->rtlhal.driver_is_goingto_unload || | ||
1400 | ppsc->rfoff_reason > RF_CHANGE_BY_PS) | ||
1401 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); | ||
1402 | |||
1403 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
1404 | _rtl88ee_poweroff_adapter(hw); | ||
1405 | |||
1406 | /* after power off we should do iqk again */ | ||
1407 | rtlpriv->phy.iqk_initialized = false; | ||
1408 | } | ||
1409 | |||
1410 | void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw, | ||
1411 | u32 *p_inta, u32 *p_intb) | ||
1412 | { | ||
1413 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1414 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1415 | |||
1416 | *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; | ||
1417 | rtl_write_dword(rtlpriv, ISR, *p_inta); | ||
1418 | |||
1419 | *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; | ||
1420 | rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); | ||
1421 | } | ||
1422 | |||
1423 | void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw) | ||
1424 | { | ||
1425 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1426 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1427 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1428 | u16 bcn_interval, atim_window; | ||
1429 | |||
1430 | bcn_interval = mac->beacon_interval; | ||
1431 | atim_window = 2; /*FIX MERGE */ | ||
1432 | rtl88ee_disable_interrupt(hw); | ||
1433 | rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); | ||
1434 | rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); | ||
1435 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); | ||
1436 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); | ||
1437 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); | ||
1438 | rtl_write_byte(rtlpriv, 0x606, 0x30); | ||
1439 | rtlpci->reg_bcn_ctrl_val |= BIT(3); | ||
1440 | rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); | ||
1441 | /*rtl88ee_enable_interrupt(hw);*/ | ||
1442 | } | ||
1443 | |||
1444 | void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw) | ||
1445 | { | ||
1446 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1447 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1448 | u16 bcn_interval = mac->beacon_interval; | ||
1449 | |||
1450 | RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, | ||
1451 | "beacon_interval:%d\n", bcn_interval); | ||
1452 | /*rtl88ee_disable_interrupt(hw);*/ | ||
1453 | rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); | ||
1454 | /*rtl88ee_enable_interrupt(hw);*/ | ||
1455 | } | ||
1456 | |||
1457 | void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw, | ||
1458 | u32 add_msr, u32 rm_msr) | ||
1459 | { | ||
1460 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1461 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1462 | |||
1463 | RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, | ||
1464 | "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); | ||
1465 | |||
1466 | rtl88ee_disable_interrupt(hw); | ||
1467 | if (add_msr) | ||
1468 | rtlpci->irq_mask[0] |= add_msr; | ||
1469 | if (rm_msr) | ||
1470 | rtlpci->irq_mask[0] &= (~rm_msr); | ||
1471 | rtl88ee_enable_interrupt(hw); | ||
1472 | } | ||
1473 | |||
1474 | static inline u8 get_chnl_group(u8 chnl) | ||
1475 | { | ||
1476 | u8 group; | ||
1477 | |||
1478 | group = chnl / 3; | ||
1479 | if (chnl == 14) | ||
1480 | group = 5; | ||
1481 | |||
1482 | return group; | ||
1483 | } | ||
1484 | |||
1485 | static void set_diff0_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path, | ||
1486 | u32 i, u32 eadr) | ||
1487 | { | ||
1488 | pwr2g->bw40_diff[path][i] = 0; | ||
1489 | if (hwinfo[eadr] == 0xFF) { | ||
1490 | pwr2g->bw20_diff[path][i] = 0x02; | ||
1491 | } else { | ||
1492 | pwr2g->bw20_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1493 | /*bit sign number to 8 bit sign number*/ | ||
1494 | if (pwr2g->bw20_diff[path][i] & BIT(3)) | ||
1495 | pwr2g->bw20_diff[path][i] |= 0xF0; | ||
1496 | } | ||
1497 | |||
1498 | if (hwinfo[eadr] == 0xFF) { | ||
1499 | pwr2g->ofdm_diff[path][i] = 0x04; | ||
1500 | } else { | ||
1501 | pwr2g->ofdm_diff[path][i] = (hwinfo[eadr] & 0x0f); | ||
1502 | /*bit sign number to 8 bit sign number*/ | ||
1503 | if (pwr2g->ofdm_diff[path][i] & BIT(3)) | ||
1504 | pwr2g->ofdm_diff[path][i] |= 0xF0; | ||
1505 | } | ||
1506 | pwr2g->cck_diff[path][i] = 0; | ||
1507 | } | ||
1508 | |||
1509 | static void set_diff0_5g(struct txpower_info_5g *pwr5g, u8 *hwinfo, u32 path, | ||
1510 | u32 i, u32 eadr) | ||
1511 | { | ||
1512 | pwr5g->bw40_diff[path][i] = 0; | ||
1513 | if (hwinfo[eadr] == 0xFF) { | ||
1514 | pwr5g->bw20_diff[path][i] = 0; | ||
1515 | } else { | ||
1516 | pwr5g->bw20_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1517 | /*bit sign number to 8 bit sign number*/ | ||
1518 | if (pwr5g->bw20_diff[path][i] & BIT(3)) | ||
1519 | pwr5g->bw20_diff[path][i] |= 0xF0; | ||
1520 | } | ||
1521 | |||
1522 | if (hwinfo[eadr] == 0xFF) { | ||
1523 | pwr5g->ofdm_diff[path][i] = 0x04; | ||
1524 | } else { | ||
1525 | pwr5g->ofdm_diff[path][i] = (hwinfo[eadr] & 0x0f); | ||
1526 | /*bit sign number to 8 bit sign number*/ | ||
1527 | if (pwr5g->ofdm_diff[path][i] & BIT(3)) | ||
1528 | pwr5g->ofdm_diff[path][i] |= 0xF0; | ||
1529 | } | ||
1530 | } | ||
1531 | |||
1532 | static void set_diff1_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path, | ||
1533 | u32 i, u32 eadr) | ||
1534 | { | ||
1535 | if (hwinfo[eadr] == 0xFF) { | ||
1536 | pwr2g->bw40_diff[path][i] = 0xFE; | ||
1537 | } else { | ||
1538 | pwr2g->bw40_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1539 | if (pwr2g->bw40_diff[path][i] & BIT(3)) | ||
1540 | pwr2g->bw40_diff[path][i] |= 0xF0; | ||
1541 | } | ||
1542 | |||
1543 | if (hwinfo[eadr] == 0xFF) { | ||
1544 | pwr2g->bw20_diff[path][i] = 0xFE; | ||
1545 | } else { | ||
1546 | pwr2g->bw20_diff[path][i] = (hwinfo[eadr]&0x0f); | ||
1547 | if (pwr2g->bw20_diff[path][i] & BIT(3)) | ||
1548 | pwr2g->bw20_diff[path][i] |= 0xF0; | ||
1549 | } | ||
1550 | } | ||
1551 | |||
1552 | static void set_diff1_5g(struct txpower_info_5g *pwr5g, u8 *hwinfo, u32 path, | ||
1553 | u32 i, u32 eadr) | ||
1554 | { | ||
1555 | if (hwinfo[eadr] == 0xFF) { | ||
1556 | pwr5g->bw40_diff[path][i] = 0xFE; | ||
1557 | } else { | ||
1558 | pwr5g->bw40_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1559 | if (pwr5g->bw40_diff[path][i] & BIT(3)) | ||
1560 | pwr5g->bw40_diff[path][i] |= 0xF0; | ||
1561 | } | ||
1562 | |||
1563 | if (hwinfo[eadr] == 0xFF) { | ||
1564 | pwr5g->bw20_diff[path][i] = 0xFE; | ||
1565 | } else { | ||
1566 | pwr5g->bw20_diff[path][i] = (hwinfo[eadr] & 0x0f); | ||
1567 | if (pwr5g->bw20_diff[path][i] & BIT(3)) | ||
1568 | pwr5g->bw20_diff[path][i] |= 0xF0; | ||
1569 | } | ||
1570 | } | ||
1571 | |||
1572 | static void set_diff2_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path, | ||
1573 | u32 i, u32 eadr) | ||
1574 | { | ||
1575 | if (hwinfo[eadr] == 0xFF) { | ||
1576 | pwr2g->ofdm_diff[path][i] = 0xFE; | ||
1577 | } else { | ||
1578 | pwr2g->ofdm_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1579 | if (pwr2g->ofdm_diff[path][i] & BIT(3)) | ||
1580 | pwr2g->ofdm_diff[path][i] |= 0xF0; | ||
1581 | } | ||
1582 | |||
1583 | if (hwinfo[eadr] == 0xFF) { | ||
1584 | pwr2g->cck_diff[path][i] = 0xFE; | ||
1585 | } else { | ||
1586 | pwr2g->cck_diff[path][i] = (hwinfo[eadr]&0x0f); | ||
1587 | if (pwr2g->cck_diff[path][i] & BIT(3)) | ||
1588 | pwr2g->cck_diff[path][i] |= 0xF0; | ||
1589 | } | ||
1590 | } | ||
1591 | |||
1592 | static void _rtl8188e_read_power_value_fromprom(struct ieee80211_hw *hw, | ||
1593 | struct txpower_info_2g *pwr2g, | ||
1594 | struct txpower_info_5g *pwr5g, | ||
1595 | bool autoload_fail, | ||
1596 | u8 *hwinfo) | ||
1597 | { | ||
1598 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1599 | u32 path, eadr = EEPROM_TX_PWR_INX, i; | ||
1600 | |||
1601 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1602 | "hal_ReadPowerValueFromPROM88E(): PROMContent[0x%x]= 0x%x\n", | ||
1603 | (eadr+1), hwinfo[eadr+1]); | ||
1604 | if (0xFF == hwinfo[eadr+1]) | ||
1605 | autoload_fail = true; | ||
1606 | |||
1607 | if (autoload_fail) { | ||
1608 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1609 | "auto load fail : Use Default value!\n"); | ||
1610 | for (path = 0; path < MAX_RF_PATH; path++) { | ||
1611 | /* 2.4G default value */ | ||
1612 | for (i = 0; i < MAX_CHNL_GROUP_24G; i++) { | ||
1613 | pwr2g->index_cck_base[path][i] = 0x2D; | ||
1614 | pwr2g->index_bw40_base[path][i] = 0x2D; | ||
1615 | } | ||
1616 | for (i = 0; i < MAX_TX_COUNT; i++) { | ||
1617 | if (i == 0) { | ||
1618 | pwr2g->bw20_diff[path][0] = 0x02; | ||
1619 | pwr2g->ofdm_diff[path][0] = 0x04; | ||
1620 | } else { | ||
1621 | pwr2g->bw20_diff[path][i] = 0xFE; | ||
1622 | pwr2g->bw40_diff[path][i] = 0xFE; | ||
1623 | pwr2g->cck_diff[path][i] = 0xFE; | ||
1624 | pwr2g->ofdm_diff[path][i] = 0xFE; | ||
1625 | } | ||
1626 | } | ||
1627 | } | ||
1628 | return; | ||
1629 | } | ||
1630 | |||
1631 | for (path = 0; path < MAX_RF_PATH; path++) { | ||
1632 | /*2.4G default value*/ | ||
1633 | for (i = 0; i < MAX_CHNL_GROUP_24G; i++) { | ||
1634 | pwr2g->index_cck_base[path][i] = hwinfo[eadr++]; | ||
1635 | if (pwr2g->index_cck_base[path][i] == 0xFF) | ||
1636 | pwr2g->index_cck_base[path][i] = 0x2D; | ||
1637 | } | ||
1638 | for (i = 0; i < MAX_CHNL_GROUP_24G; i++) { | ||
1639 | pwr2g->index_bw40_base[path][i] = hwinfo[eadr++]; | ||
1640 | if (pwr2g->index_bw40_base[path][i] == 0xFF) | ||
1641 | pwr2g->index_bw40_base[path][i] = 0x2D; | ||
1642 | } | ||
1643 | for (i = 0; i < MAX_TX_COUNT; i++) { | ||
1644 | if (i == 0) { | ||
1645 | set_diff0_2g(pwr2g, hwinfo, path, i, eadr); | ||
1646 | eadr++; | ||
1647 | } else { | ||
1648 | set_diff1_2g(pwr2g, hwinfo, path, i, eadr); | ||
1649 | eadr++; | ||
1650 | |||
1651 | set_diff2_2g(pwr2g, hwinfo, path, i, eadr); | ||
1652 | eadr++; | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1656 | /*5G default value*/ | ||
1657 | for (i = 0; i < MAX_CHNL_GROUP_5G; i++) { | ||
1658 | pwr5g->index_bw40_base[path][i] = hwinfo[eadr++]; | ||
1659 | if (pwr5g->index_bw40_base[path][i] == 0xFF) | ||
1660 | pwr5g->index_bw40_base[path][i] = 0xFE; | ||
1661 | } | ||
1662 | |||
1663 | for (i = 0; i < MAX_TX_COUNT; i++) { | ||
1664 | if (i == 0) { | ||
1665 | set_diff0_5g(pwr5g, hwinfo, path, i, eadr); | ||
1666 | eadr++; | ||
1667 | } else { | ||
1668 | set_diff1_5g(pwr5g, hwinfo, path, i, eadr); | ||
1669 | eadr++; | ||
1670 | } | ||
1671 | } | ||
1672 | |||
1673 | if (hwinfo[eadr] == 0xFF) { | ||
1674 | pwr5g->ofdm_diff[path][1] = 0xFE; | ||
1675 | pwr5g->ofdm_diff[path][2] = 0xFE; | ||
1676 | } else { | ||
1677 | pwr5g->ofdm_diff[path][1] = (hwinfo[eadr] & 0xf0) >> 4; | ||
1678 | pwr5g->ofdm_diff[path][2] = (hwinfo[eadr] & 0x0f); | ||
1679 | } | ||
1680 | eadr++; | ||
1681 | |||
1682 | if (hwinfo[eadr] == 0xFF) | ||
1683 | pwr5g->ofdm_diff[path][3] = 0xFE; | ||
1684 | else | ||
1685 | pwr5g->ofdm_diff[path][3] = (hwinfo[eadr]&0x0f); | ||
1686 | eadr++; | ||
1687 | |||
1688 | for (i = 1; i < MAX_TX_COUNT; i++) { | ||
1689 | if (pwr5g->ofdm_diff[path][i] == 0xFF) | ||
1690 | pwr5g->ofdm_diff[path][i] = 0xFE; | ||
1691 | else if (pwr5g->ofdm_diff[path][i] & BIT(3)) | ||
1692 | pwr5g->ofdm_diff[path][i] |= 0xF0; | ||
1693 | } | ||
1694 | } | ||
1695 | } | ||
1696 | |||
1697 | static void _rtl88ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | ||
1698 | bool autoload_fail, | ||
1699 | u8 *hwinfo) | ||
1700 | { | ||
1701 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1702 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1703 | struct txpower_info_2g pwrinfo24g; | ||
1704 | struct txpower_info_5g pwrinfo5g; | ||
1705 | u8 rf_path, index; | ||
1706 | u8 i; | ||
1707 | int jj = EEPROM_RF_BOARD_OPTION_88E; | ||
1708 | int kk = EEPROM_THERMAL_METER_88E; | ||
1709 | |||
1710 | _rtl8188e_read_power_value_fromprom(hw, &pwrinfo24g, &pwrinfo5g, | ||
1711 | autoload_fail, hwinfo); | ||
1712 | |||
1713 | for (rf_path = 0; rf_path < 2; rf_path++) { | ||
1714 | for (i = 0; i < 14; i++) { | ||
1715 | index = get_chnl_group(i+1); | ||
1716 | |||
1717 | rtlefuse->txpwrlevel_cck[rf_path][i] = | ||
1718 | pwrinfo24g.index_cck_base[rf_path][index]; | ||
1719 | if (i == 13) | ||
1720 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = | ||
1721 | pwrinfo24g.index_bw40_base[rf_path][4]; | ||
1722 | else | ||
1723 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = | ||
1724 | pwrinfo24g.index_bw40_base[rf_path][index]; | ||
1725 | rtlefuse->txpwr_ht20diff[rf_path][i] = | ||
1726 | pwrinfo24g.bw20_diff[rf_path][0]; | ||
1727 | rtlefuse->txpwr_legacyhtdiff[rf_path][i] = | ||
1728 | pwrinfo24g.ofdm_diff[rf_path][0]; | ||
1729 | } | ||
1730 | |||
1731 | for (i = 0; i < 14; i++) { | ||
1732 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, | ||
1733 | "RF(%d)-Ch(%d) [CCK / HT40_1S ] = " | ||
1734 | "[0x%x / 0x%x ]\n", rf_path, i, | ||
1735 | rtlefuse->txpwrlevel_cck[rf_path][i], | ||
1736 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i]); | ||
1737 | } | ||
1738 | } | ||
1739 | |||
1740 | if (!autoload_fail) | ||
1741 | rtlefuse->eeprom_thermalmeter = hwinfo[kk]; | ||
1742 | else | ||
1743 | rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; | ||
1744 | |||
1745 | if (rtlefuse->eeprom_thermalmeter == 0xff || autoload_fail) { | ||
1746 | rtlefuse->apk_thermalmeterignore = true; | ||
1747 | rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; | ||
1748 | } | ||
1749 | |||
1750 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; | ||
1751 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, | ||
1752 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | ||
1753 | |||
1754 | if (!autoload_fail) { | ||
1755 | rtlefuse->eeprom_regulatory = hwinfo[jj] & 0x07;/*bit0~2*/ | ||
1756 | if (hwinfo[jj] == 0xFF) | ||
1757 | rtlefuse->eeprom_regulatory = 0; | ||
1758 | } else { | ||
1759 | rtlefuse->eeprom_regulatory = 0; | ||
1760 | } | ||
1761 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, | ||
1762 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | ||
1763 | } | ||
1764 | |||
1765 | static void _rtl88ee_read_adapter_info(struct ieee80211_hw *hw) | ||
1766 | { | ||
1767 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1768 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1769 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1770 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
1771 | u16 i, usvalue; | ||
1772 | u8 hwinfo[HWSET_MAX_SIZE]; | ||
1773 | u16 eeprom_id; | ||
1774 | int jj = EEPROM_RF_BOARD_OPTION_88E; | ||
1775 | int kk = EEPROM_RF_FEATURE_OPTION_88E; | ||
1776 | |||
1777 | if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { | ||
1778 | rtl_efuse_shadow_map_update(hw); | ||
1779 | |||
1780 | memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], | ||
1781 | HWSET_MAX_SIZE); | ||
1782 | } else if (rtlefuse->epromtype == EEPROM_93C46) { | ||
1783 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1784 | "RTL819X Not boot from eeprom, check it !!"); | ||
1785 | } | ||
1786 | |||
1787 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), | ||
1788 | hwinfo, HWSET_MAX_SIZE); | ||
1789 | |||
1790 | eeprom_id = *((u16 *)&hwinfo[0]); | ||
1791 | if (eeprom_id != RTL8188E_EEPROM_ID) { | ||
1792 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1793 | "EEPROM ID(%#x) is invalid!!\n", eeprom_id); | ||
1794 | rtlefuse->autoload_failflag = true; | ||
1795 | } else { | ||
1796 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); | ||
1797 | rtlefuse->autoload_failflag = false; | ||
1798 | } | ||
1799 | |||
1800 | if (rtlefuse->autoload_failflag == true) | ||
1801 | return; | ||
1802 | /*VID DID SVID SDID*/ | ||
1803 | rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; | ||
1804 | rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; | ||
1805 | rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; | ||
1806 | rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; | ||
1807 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1808 | "EEPROMId = 0x%4x\n", eeprom_id); | ||
1809 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1810 | "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); | ||
1811 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1812 | "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); | ||
1813 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1814 | "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); | ||
1815 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1816 | "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); | ||
1817 | /*customer ID*/ | ||
1818 | rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; | ||
1819 | if (rtlefuse->eeprom_oemid == 0xFF) | ||
1820 | rtlefuse->eeprom_oemid = 0; | ||
1821 | |||
1822 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1823 | "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); | ||
1824 | /*EEPROM version*/ | ||
1825 | rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; | ||
1826 | /*mac address*/ | ||
1827 | for (i = 0; i < 6; i += 2) { | ||
1828 | usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; | ||
1829 | *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; | ||
1830 | } | ||
1831 | |||
1832 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
1833 | "dev_addr: %pM\n", rtlefuse->dev_addr); | ||
1834 | /*channel plan */ | ||
1835 | rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; | ||
1836 | /* set channel paln to world wide 13 */ | ||
1837 | rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; | ||
1838 | /*tx power*/ | ||
1839 | _rtl88ee_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, | ||
1840 | hwinfo); | ||
1841 | rtlefuse->txpwr_fromeprom = true; | ||
1842 | |||
1843 | rtl8188ee_read_bt_coexist_info_from_hwpg(hw, | ||
1844 | rtlefuse->autoload_failflag, | ||
1845 | hwinfo); | ||
1846 | /*board type*/ | ||
1847 | rtlefuse->board_type = (((*(u8 *)&hwinfo[jj]) & 0xE0) >> 5); | ||
1848 | /*Wake on wlan*/ | ||
1849 | rtlefuse->wowlan_enable = ((hwinfo[kk] & 0x40) >> 6); | ||
1850 | /*parse xtal*/ | ||
1851 | rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_88E]; | ||
1852 | if (hwinfo[EEPROM_XTAL_88E]) | ||
1853 | rtlefuse->crystalcap = 0x20; | ||
1854 | /*antenna diversity*/ | ||
1855 | rtlefuse->antenna_div_cfg = (hwinfo[jj] & 0x18) >> 3; | ||
1856 | if (hwinfo[jj] == 0xFF) | ||
1857 | rtlefuse->antenna_div_cfg = 0; | ||
1858 | if (rppriv->bt_coexist.eeprom_bt_coexist != 0 && | ||
1859 | rppriv->bt_coexist.eeprom_bt_ant_num == ANT_X1) | ||
1860 | rtlefuse->antenna_div_cfg = 0; | ||
1861 | |||
1862 | rtlefuse->antenna_div_type = hwinfo[EEPROM_RF_ANTENNA_OPT_88E]; | ||
1863 | if (rtlefuse->antenna_div_type == 0xFF) | ||
1864 | rtlefuse->antenna_div_type = 0x01; | ||
1865 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV || | ||
1866 | rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1867 | rtlefuse->antenna_div_cfg = 1; | ||
1868 | |||
1869 | if (rtlhal->oem_id == RT_CID_DEFAULT) { | ||
1870 | switch (rtlefuse->eeprom_oemid) { | ||
1871 | case EEPROM_CID_DEFAULT: | ||
1872 | if (rtlefuse->eeprom_did == 0x8179) { | ||
1873 | if (rtlefuse->eeprom_svid == 0x1025) { | ||
1874 | rtlhal->oem_id = RT_CID_819x_Acer; | ||
1875 | } else if ((rtlefuse->eeprom_svid == 0x10EC && | ||
1876 | rtlefuse->eeprom_smid == 0x0179) || | ||
1877 | (rtlefuse->eeprom_svid == 0x17AA && | ||
1878 | rtlefuse->eeprom_smid == 0x0179)) { | ||
1879 | rtlhal->oem_id = RT_CID_819x_Lenovo; | ||
1880 | } else if (rtlefuse->eeprom_svid == 0x103c && | ||
1881 | rtlefuse->eeprom_smid == 0x197d) { | ||
1882 | rtlhal->oem_id = RT_CID_819x_HP; | ||
1883 | } else { | ||
1884 | rtlhal->oem_id = RT_CID_DEFAULT; | ||
1885 | } | ||
1886 | } else { | ||
1887 | rtlhal->oem_id = RT_CID_DEFAULT; | ||
1888 | } | ||
1889 | break; | ||
1890 | case EEPROM_CID_TOSHIBA: | ||
1891 | rtlhal->oem_id = RT_CID_TOSHIBA; | ||
1892 | break; | ||
1893 | case EEPROM_CID_QMI: | ||
1894 | rtlhal->oem_id = RT_CID_819x_QMI; | ||
1895 | break; | ||
1896 | case EEPROM_CID_WHQL: | ||
1897 | default: | ||
1898 | rtlhal->oem_id = RT_CID_DEFAULT; | ||
1899 | break; | ||
1900 | } | ||
1901 | } | ||
1902 | } | ||
1903 | |||
1904 | static void _rtl88ee_hal_customized_behavior(struct ieee80211_hw *hw) | ||
1905 | { | ||
1906 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1907 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
1908 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1909 | |||
1910 | pcipriv->ledctl.led_opendrain = true; | ||
1911 | |||
1912 | switch (rtlhal->oem_id) { | ||
1913 | case RT_CID_819x_HP: | ||
1914 | pcipriv->ledctl.led_opendrain = true; | ||
1915 | break; | ||
1916 | case RT_CID_819x_Lenovo: | ||
1917 | case RT_CID_DEFAULT: | ||
1918 | case RT_CID_TOSHIBA: | ||
1919 | case RT_CID_CCX: | ||
1920 | case RT_CID_819x_Acer: | ||
1921 | case RT_CID_WHQL: | ||
1922 | default: | ||
1923 | break; | ||
1924 | } | ||
1925 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
1926 | "RT Customized ID: 0x%02X\n", rtlhal->oem_id); | ||
1927 | } | ||
1928 | |||
1929 | void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw) | ||
1930 | { | ||
1931 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1932 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1933 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1934 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1935 | u8 tmp_u1b; | ||
1936 | |||
1937 | rtlhal->version = _rtl88ee_read_chip_version(hw); | ||
1938 | if (get_rf_type(rtlphy) == RF_1T1R) { | ||
1939 | rtlpriv->dm.rfpath_rxenable[0] = true; | ||
1940 | } else { | ||
1941 | rtlpriv->dm.rfpath_rxenable[0] = true; | ||
1942 | rtlpriv->dm.rfpath_rxenable[1] = true; | ||
1943 | } | ||
1944 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", | ||
1945 | rtlhal->version); | ||
1946 | tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); | ||
1947 | if (tmp_u1b & BIT(4)) { | ||
1948 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); | ||
1949 | rtlefuse->epromtype = EEPROM_93C46; | ||
1950 | } else { | ||
1951 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); | ||
1952 | rtlefuse->epromtype = EEPROM_BOOT_EFUSE; | ||
1953 | } | ||
1954 | if (tmp_u1b & BIT(5)) { | ||
1955 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); | ||
1956 | rtlefuse->autoload_failflag = false; | ||
1957 | _rtl88ee_read_adapter_info(hw); | ||
1958 | } else { | ||
1959 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); | ||
1960 | } | ||
1961 | _rtl88ee_hal_customized_behavior(hw); | ||
1962 | } | ||
1963 | |||
1964 | static void rtl88ee_update_hal_rate_table(struct ieee80211_hw *hw, | ||
1965 | struct ieee80211_sta *sta) | ||
1966 | { | ||
1967 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1968 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
1969 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1970 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1971 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1972 | u32 ratr_value; | ||
1973 | u8 ratr_index = 0; | ||
1974 | u8 nmode = mac->ht_enable; | ||
1975 | u8 mimo_ps = IEEE80211_SMPS_OFF; | ||
1976 | u16 shortgi_rate; | ||
1977 | u32 tmp_ratr_value; | ||
1978 | u8 ctx40 = mac->bw_40; | ||
1979 | u16 cap = sta->ht_cap.cap; | ||
1980 | u8 short40 = (cap & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; | ||
1981 | u8 short20 = (cap & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; | ||
1982 | enum wireless_mode wirelessmode = mac->mode; | ||
1983 | |||
1984 | if (rtlhal->current_bandtype == BAND_ON_5G) | ||
1985 | ratr_value = sta->supp_rates[1] << 4; | ||
1986 | else | ||
1987 | ratr_value = sta->supp_rates[0]; | ||
1988 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
1989 | ratr_value = 0xfff; | ||
1990 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | ||
1991 | sta->ht_cap.mcs.rx_mask[0] << 12); | ||
1992 | switch (wirelessmode) { | ||
1993 | case WIRELESS_MODE_B: | ||
1994 | if (ratr_value & 0x0000000c) | ||
1995 | ratr_value &= 0x0000000d; | ||
1996 | else | ||
1997 | ratr_value &= 0x0000000f; | ||
1998 | break; | ||
1999 | case WIRELESS_MODE_G: | ||
2000 | ratr_value &= 0x00000FF5; | ||
2001 | break; | ||
2002 | case WIRELESS_MODE_N_24G: | ||
2003 | case WIRELESS_MODE_N_5G: | ||
2004 | nmode = 1; | ||
2005 | if (mimo_ps == IEEE80211_SMPS_STATIC) { | ||
2006 | ratr_value &= 0x0007F005; | ||
2007 | } else { | ||
2008 | u32 ratr_mask; | ||
2009 | |||
2010 | if (get_rf_type(rtlphy) == RF_1T2R || | ||
2011 | get_rf_type(rtlphy) == RF_1T1R) | ||
2012 | ratr_mask = 0x000ff005; | ||
2013 | else | ||
2014 | ratr_mask = 0x0f0ff005; | ||
2015 | |||
2016 | ratr_value &= ratr_mask; | ||
2017 | } | ||
2018 | break; | ||
2019 | default: | ||
2020 | if (rtlphy->rf_type == RF_1T2R) | ||
2021 | ratr_value &= 0x000ff0ff; | ||
2022 | else | ||
2023 | ratr_value &= 0x0f0ff0ff; | ||
2024 | |||
2025 | break; | ||
2026 | } | ||
2027 | |||
2028 | if ((rppriv->bt_coexist.bt_coexistence) && | ||
2029 | (rppriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) && | ||
2030 | (rppriv->bt_coexist.bt_cur_state) && | ||
2031 | (rppriv->bt_coexist.bt_ant_isolation) && | ||
2032 | ((rppriv->bt_coexist.bt_service == BT_SCO) || | ||
2033 | (rppriv->bt_coexist.bt_service == BT_BUSY))) | ||
2034 | ratr_value &= 0x0fffcfc0; | ||
2035 | else | ||
2036 | ratr_value &= 0x0FFFFFFF; | ||
2037 | |||
2038 | if (nmode && ((ctx40 && short40) || | ||
2039 | (!ctx40 && short20))) { | ||
2040 | ratr_value |= 0x10000000; | ||
2041 | tmp_ratr_value = (ratr_value >> 12); | ||
2042 | |||
2043 | for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { | ||
2044 | if ((1 << shortgi_rate) & tmp_ratr_value) | ||
2045 | break; | ||
2046 | } | ||
2047 | |||
2048 | shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | | ||
2049 | (shortgi_rate << 4) | (shortgi_rate); | ||
2050 | } | ||
2051 | |||
2052 | rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); | ||
2053 | |||
2054 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | ||
2055 | "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); | ||
2056 | } | ||
2057 | |||
2058 | static void rtl88ee_update_hal_rate_mask(struct ieee80211_hw *hw, | ||
2059 | struct ieee80211_sta *sta, u8 rssi) | ||
2060 | { | ||
2061 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2062 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
2063 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2064 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
2065 | struct rtl_sta_info *sta_entry = NULL; | ||
2066 | u32 ratr_bitmap; | ||
2067 | u8 ratr_index; | ||
2068 | u16 cap = sta->ht_cap.cap; | ||
2069 | u8 ctx40 = (cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0; | ||
2070 | u8 short40 = (cap & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; | ||
2071 | u8 short20 = (cap & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; | ||
2072 | enum wireless_mode wirelessmode = 0; | ||
2073 | bool shortgi = false; | ||
2074 | u8 rate_mask[5]; | ||
2075 | u8 macid = 0; | ||
2076 | u8 mimo_ps = IEEE80211_SMPS_OFF; | ||
2077 | |||
2078 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
2079 | wirelessmode = sta_entry->wireless_mode; | ||
2080 | if (mac->opmode == NL80211_IFTYPE_STATION || | ||
2081 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
2082 | ctx40 = mac->bw_40; | ||
2083 | else if (mac->opmode == NL80211_IFTYPE_AP || | ||
2084 | mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2085 | macid = sta->aid + 1; | ||
2086 | |||
2087 | if (rtlhal->current_bandtype == BAND_ON_5G) | ||
2088 | ratr_bitmap = sta->supp_rates[1] << 4; | ||
2089 | else | ||
2090 | ratr_bitmap = sta->supp_rates[0]; | ||
2091 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2092 | ratr_bitmap = 0xfff; | ||
2093 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | ||
2094 | sta->ht_cap.mcs.rx_mask[0] << 12); | ||
2095 | switch (wirelessmode) { | ||
2096 | case WIRELESS_MODE_B: | ||
2097 | ratr_index = RATR_INX_WIRELESS_B; | ||
2098 | if (ratr_bitmap & 0x0000000c) | ||
2099 | ratr_bitmap &= 0x0000000d; | ||
2100 | else | ||
2101 | ratr_bitmap &= 0x0000000f; | ||
2102 | break; | ||
2103 | case WIRELESS_MODE_G: | ||
2104 | ratr_index = RATR_INX_WIRELESS_GB; | ||
2105 | |||
2106 | if (rssi == 1) | ||
2107 | ratr_bitmap &= 0x00000f00; | ||
2108 | else if (rssi == 2) | ||
2109 | ratr_bitmap &= 0x00000ff0; | ||
2110 | else | ||
2111 | ratr_bitmap &= 0x00000ff5; | ||
2112 | break; | ||
2113 | case WIRELESS_MODE_A: | ||
2114 | ratr_index = RATR_INX_WIRELESS_A; | ||
2115 | ratr_bitmap &= 0x00000ff0; | ||
2116 | break; | ||
2117 | case WIRELESS_MODE_N_24G: | ||
2118 | case WIRELESS_MODE_N_5G: | ||
2119 | ratr_index = RATR_INX_WIRELESS_NGB; | ||
2120 | |||
2121 | if (mimo_ps == IEEE80211_SMPS_STATIC) { | ||
2122 | if (rssi == 1) | ||
2123 | ratr_bitmap &= 0x00070000; | ||
2124 | else if (rssi == 2) | ||
2125 | ratr_bitmap &= 0x0007f000; | ||
2126 | else | ||
2127 | ratr_bitmap &= 0x0007f005; | ||
2128 | } else { | ||
2129 | if (rtlphy->rf_type == RF_1T2R || | ||
2130 | rtlphy->rf_type == RF_1T1R) { | ||
2131 | if (ctx40) { | ||
2132 | if (rssi == 1) | ||
2133 | ratr_bitmap &= 0x000f0000; | ||
2134 | else if (rssi == 2) | ||
2135 | ratr_bitmap &= 0x000ff000; | ||
2136 | else | ||
2137 | ratr_bitmap &= 0x000ff015; | ||
2138 | } else { | ||
2139 | if (rssi == 1) | ||
2140 | ratr_bitmap &= 0x000f0000; | ||
2141 | else if (rssi == 2) | ||
2142 | ratr_bitmap &= 0x000ff000; | ||
2143 | else | ||
2144 | ratr_bitmap &= 0x000ff005; | ||
2145 | } | ||
2146 | } else { | ||
2147 | if (ctx40) { | ||
2148 | if (rssi == 1) | ||
2149 | ratr_bitmap &= 0x0f8f0000; | ||
2150 | else if (rssi == 2) | ||
2151 | ratr_bitmap &= 0x0f8ff000; | ||
2152 | else | ||
2153 | ratr_bitmap &= 0x0f8ff015; | ||
2154 | } else { | ||
2155 | if (rssi == 1) | ||
2156 | ratr_bitmap &= 0x0f8f0000; | ||
2157 | else if (rssi == 2) | ||
2158 | ratr_bitmap &= 0x0f8ff000; | ||
2159 | else | ||
2160 | ratr_bitmap &= 0x0f8ff005; | ||
2161 | } | ||
2162 | } | ||
2163 | } | ||
2164 | |||
2165 | if ((ctx40 && short40) || (!ctx40 && short20)) { | ||
2166 | if (macid == 0) | ||
2167 | shortgi = true; | ||
2168 | else if (macid == 1) | ||
2169 | shortgi = false; | ||
2170 | } | ||
2171 | break; | ||
2172 | default: | ||
2173 | ratr_index = RATR_INX_WIRELESS_NGB; | ||
2174 | |||
2175 | if (rtlphy->rf_type == RF_1T2R) | ||
2176 | ratr_bitmap &= 0x000ff0ff; | ||
2177 | else | ||
2178 | ratr_bitmap &= 0x0f0ff0ff; | ||
2179 | break; | ||
2180 | } | ||
2181 | sta_entry->ratr_index = ratr_index; | ||
2182 | |||
2183 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | ||
2184 | "ratr_bitmap :%x\n", ratr_bitmap); | ||
2185 | *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | | ||
2186 | (ratr_index << 28); | ||
2187 | rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; | ||
2188 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | ||
2189 | "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", | ||
2190 | ratr_index, ratr_bitmap, rate_mask[0], rate_mask[1], | ||
2191 | rate_mask[2], rate_mask[3], rate_mask[4]); | ||
2192 | rtl88e_fill_h2c_cmd(hw, H2C_88E_RA_MASK, 5, rate_mask); | ||
2193 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); | ||
2194 | } | ||
2195 | |||
2196 | void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw, | ||
2197 | struct ieee80211_sta *sta, u8 rssi) | ||
2198 | { | ||
2199 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2200 | |||
2201 | if (rtlpriv->dm.useramask) | ||
2202 | rtl88ee_update_hal_rate_mask(hw, sta, rssi); | ||
2203 | else | ||
2204 | rtl88ee_update_hal_rate_table(hw, sta); | ||
2205 | } | ||
2206 | |||
2207 | void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw) | ||
2208 | { | ||
2209 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2210 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2211 | u16 sifs_timer; | ||
2212 | |||
2213 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, | ||
2214 | (u8 *)&mac->slot_time); | ||
2215 | if (!mac->ht_enable) | ||
2216 | sifs_timer = 0x0a0a; | ||
2217 | else | ||
2218 | sifs_timer = 0x0e0e; | ||
2219 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); | ||
2220 | } | ||
2221 | |||
2222 | bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) | ||
2223 | { | ||
2224 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2225 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
2226 | enum rf_pwrstate state_toset; | ||
2227 | u32 u4tmp; | ||
2228 | bool actuallyset = false; | ||
2229 | |||
2230 | if (rtlpriv->rtlhal.being_init_adapter) | ||
2231 | return false; | ||
2232 | |||
2233 | if (ppsc->swrf_processing) | ||
2234 | return false; | ||
2235 | |||
2236 | spin_lock(&rtlpriv->locks.rf_ps_lock); | ||
2237 | if (ppsc->rfchange_inprogress) { | ||
2238 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2239 | return false; | ||
2240 | } else { | ||
2241 | ppsc->rfchange_inprogress = true; | ||
2242 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2243 | } | ||
2244 | |||
2245 | u4tmp = rtl_read_dword(rtlpriv, REG_GPIO_OUTPUT); | ||
2246 | state_toset = (u4tmp & BIT(31)) ? ERFON : ERFOFF; | ||
2247 | |||
2248 | |||
2249 | if ((ppsc->hwradiooff == true) && (state_toset == ERFON)) { | ||
2250 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2251 | "GPIOChangeRF - HW Radio ON, RF ON\n"); | ||
2252 | |||
2253 | state_toset = ERFON; | ||
2254 | ppsc->hwradiooff = false; | ||
2255 | actuallyset = true; | ||
2256 | } else if ((ppsc->hwradiooff == false) && (state_toset == ERFOFF)) { | ||
2257 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2258 | "GPIOChangeRF - HW Radio OFF, RF OFF\n"); | ||
2259 | |||
2260 | state_toset = ERFOFF; | ||
2261 | ppsc->hwradiooff = true; | ||
2262 | actuallyset = true; | ||
2263 | } | ||
2264 | |||
2265 | if (actuallyset) { | ||
2266 | spin_lock(&rtlpriv->locks.rf_ps_lock); | ||
2267 | ppsc->rfchange_inprogress = false; | ||
2268 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2269 | } else { | ||
2270 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) | ||
2271 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
2272 | |||
2273 | spin_lock(&rtlpriv->locks.rf_ps_lock); | ||
2274 | ppsc->rfchange_inprogress = false; | ||
2275 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2276 | } | ||
2277 | |||
2278 | *valid = 1; | ||
2279 | return !ppsc->hwradiooff; | ||
2280 | } | ||
2281 | |||
2282 | static void add_one_key(struct ieee80211_hw *hw, u8 *macaddr, | ||
2283 | struct rtl_mac *mac, u32 key, u32 id, | ||
2284 | u8 enc_algo, bool is_pairwise) | ||
2285 | { | ||
2286 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2287 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
2288 | |||
2289 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "add one entry\n"); | ||
2290 | if (is_pairwise) { | ||
2291 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set Pairwise key\n"); | ||
2292 | |||
2293 | rtl_cam_add_one_entry(hw, macaddr, key, id, enc_algo, | ||
2294 | CAM_CONFIG_NO_USEDK, | ||
2295 | rtlpriv->sec.key_buf[key]); | ||
2296 | } else { | ||
2297 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set group key\n"); | ||
2298 | |||
2299 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
2300 | rtl_cam_add_one_entry(hw, rtlefuse->dev_addr, | ||
2301 | PAIRWISE_KEYIDX, | ||
2302 | CAM_PAIRWISE_KEY_POSITION, | ||
2303 | enc_algo, | ||
2304 | CAM_CONFIG_NO_USEDK, | ||
2305 | rtlpriv->sec.key_buf[id]); | ||
2306 | } | ||
2307 | |||
2308 | rtl_cam_add_one_entry(hw, macaddr, key, id, enc_algo, | ||
2309 | CAM_CONFIG_NO_USEDK, | ||
2310 | rtlpriv->sec.key_buf[id]); | ||
2311 | } | ||
2312 | } | ||
2313 | |||
2314 | void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key, | ||
2315 | u8 *mac_ad, bool is_group, u8 enc_algo, | ||
2316 | bool is_wepkey, bool clear_all) | ||
2317 | { | ||
2318 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2319 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2320 | u8 *macaddr = mac_ad; | ||
2321 | u32 id = 0; | ||
2322 | bool is_pairwise = false; | ||
2323 | |||
2324 | static u8 cam_const_addr[4][6] = { | ||
2325 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
2326 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, | ||
2327 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, | ||
2328 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} | ||
2329 | }; | ||
2330 | static u8 cam_const_broad[] = { | ||
2331 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
2332 | }; | ||
2333 | |||
2334 | if (clear_all) { | ||
2335 | u8 idx = 0; | ||
2336 | u8 cam_offset = 0; | ||
2337 | u8 clear_number = 5; | ||
2338 | |||
2339 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); | ||
2340 | |||
2341 | for (idx = 0; idx < clear_number; idx++) { | ||
2342 | rtl_cam_mark_invalid(hw, cam_offset + idx); | ||
2343 | rtl_cam_empty_entry(hw, cam_offset + idx); | ||
2344 | |||
2345 | if (idx < 5) { | ||
2346 | memset(rtlpriv->sec.key_buf[idx], 0, | ||
2347 | MAX_KEY_LEN); | ||
2348 | rtlpriv->sec.key_len[idx] = 0; | ||
2349 | } | ||
2350 | } | ||
2351 | |||
2352 | } else { | ||
2353 | switch (enc_algo) { | ||
2354 | case WEP40_ENCRYPTION: | ||
2355 | enc_algo = CAM_WEP40; | ||
2356 | break; | ||
2357 | case WEP104_ENCRYPTION: | ||
2358 | enc_algo = CAM_WEP104; | ||
2359 | break; | ||
2360 | case TKIP_ENCRYPTION: | ||
2361 | enc_algo = CAM_TKIP; | ||
2362 | break; | ||
2363 | case AESCCMP_ENCRYPTION: | ||
2364 | enc_algo = CAM_AES; | ||
2365 | break; | ||
2366 | default: | ||
2367 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
2368 | "switch case not processed\n"); | ||
2369 | enc_algo = CAM_TKIP; | ||
2370 | break; | ||
2371 | } | ||
2372 | |||
2373 | if (is_wepkey || rtlpriv->sec.use_defaultkey) { | ||
2374 | macaddr = cam_const_addr[key]; | ||
2375 | id = key; | ||
2376 | } else { | ||
2377 | if (is_group) { | ||
2378 | macaddr = cam_const_broad; | ||
2379 | id = key; | ||
2380 | } else { | ||
2381 | if (mac->opmode == NL80211_IFTYPE_AP || | ||
2382 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
2383 | id = rtl_cam_get_free_entry(hw, mac_ad); | ||
2384 | if (id >= TOTAL_CAM_ENTRY) { | ||
2385 | RT_TRACE(rtlpriv, COMP_SEC, | ||
2386 | DBG_EMERG, | ||
2387 | "Can not find free hw security cam entry\n"); | ||
2388 | return; | ||
2389 | } | ||
2390 | } else { | ||
2391 | id = CAM_PAIRWISE_KEY_POSITION; | ||
2392 | } | ||
2393 | |||
2394 | key = PAIRWISE_KEYIDX; | ||
2395 | is_pairwise = true; | ||
2396 | } | ||
2397 | } | ||
2398 | |||
2399 | if (rtlpriv->sec.key_len[key] == 0) { | ||
2400 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
2401 | "delete one entry, id is %d\n", id); | ||
2402 | if (mac->opmode == NL80211_IFTYPE_AP || | ||
2403 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
2404 | rtl_cam_del_entry(hw, mac_ad); | ||
2405 | rtl_cam_delete_one_entry(hw, mac_ad, id); | ||
2406 | } else { | ||
2407 | add_one_key(hw, macaddr, mac, key, id, enc_algo, | ||
2408 | is_pairwise); | ||
2409 | } | ||
2410 | } | ||
2411 | } | ||
2412 | |||
2413 | static void rtl8188ee_bt_var_init(struct ieee80211_hw *hw) | ||
2414 | { | ||
2415 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
2416 | struct bt_coexist_info coexist = rppriv->bt_coexist; | ||
2417 | |||
2418 | coexist.bt_coexistence = rppriv->bt_coexist.eeprom_bt_coexist; | ||
2419 | coexist.bt_ant_num = coexist.eeprom_bt_ant_num; | ||
2420 | coexist.bt_coexist_type = coexist.eeprom_bt_type; | ||
2421 | |||
2422 | if (coexist.reg_bt_iso == 2) | ||
2423 | coexist.bt_ant_isolation = coexist.eeprom_bt_ant_isol; | ||
2424 | else | ||
2425 | coexist.bt_ant_isolation = coexist.reg_bt_iso; | ||
2426 | |||
2427 | coexist.bt_radio_shared_type = coexist.eeprom_bt_radio_shared; | ||
2428 | |||
2429 | if (coexist.bt_coexistence) { | ||
2430 | if (coexist.reg_bt_sco == 1) | ||
2431 | coexist.bt_service = BT_OTHER_ACTION; | ||
2432 | else if (coexist.reg_bt_sco == 2) | ||
2433 | coexist.bt_service = BT_SCO; | ||
2434 | else if (coexist.reg_bt_sco == 4) | ||
2435 | coexist.bt_service = BT_BUSY; | ||
2436 | else if (coexist.reg_bt_sco == 5) | ||
2437 | coexist.bt_service = BT_OTHERBUSY; | ||
2438 | else | ||
2439 | coexist.bt_service = BT_IDLE; | ||
2440 | |||
2441 | coexist.bt_edca_ul = 0; | ||
2442 | coexist.bt_edca_dl = 0; | ||
2443 | coexist.bt_rssi_state = 0xff; | ||
2444 | } | ||
2445 | } | ||
2446 | |||
2447 | void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, | ||
2448 | bool auto_load_fail, u8 *hwinfo) | ||
2449 | { | ||
2450 | rtl8188ee_bt_var_init(hw); | ||
2451 | } | ||
2452 | |||
2453 | void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw) | ||
2454 | { | ||
2455 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
2456 | |||
2457 | /* 0:Low, 1:High, 2:From Efuse. */ | ||
2458 | rppriv->bt_coexist.reg_bt_iso = 2; | ||
2459 | /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ | ||
2460 | rppriv->bt_coexist.reg_bt_sco = 3; | ||
2461 | /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ | ||
2462 | rppriv->bt_coexist.reg_bt_sco = 0; | ||
2463 | } | ||
2464 | |||
2465 | void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw) | ||
2466 | { | ||
2467 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2468 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
2469 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
2470 | struct bt_coexist_info coexist = rppriv->bt_coexist; | ||
2471 | u8 u1_tmp; | ||
2472 | |||
2473 | if (coexist.bt_coexistence && | ||
2474 | ((coexist.bt_coexist_type == BT_CSR_BC4) || | ||
2475 | coexist.bt_coexist_type == BT_CSR_BC8)) { | ||
2476 | if (coexist.bt_ant_isolation) | ||
2477 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); | ||
2478 | |||
2479 | u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & | ||
2480 | BIT_OFFSET_LEN_MASK_32(0, 1); | ||
2481 | u1_tmp = u1_tmp | ((coexist.bt_ant_isolation == 1) ? | ||
2482 | 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | | ||
2483 | ((coexist.bt_service == BT_SCO) ? | ||
2484 | 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); | ||
2485 | rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); | ||
2486 | |||
2487 | rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); | ||
2488 | rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); | ||
2489 | rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); | ||
2490 | |||
2491 | /* Config to 1T1R. */ | ||
2492 | if (rtlphy->rf_type == RF_1T1R) { | ||
2493 | u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); | ||
2494 | u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); | ||
2495 | rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); | ||
2496 | |||
2497 | u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); | ||
2498 | u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); | ||
2499 | rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); | ||
2500 | } | ||
2501 | } | ||
2502 | } | ||
2503 | |||
2504 | void rtl88ee_suspend(struct ieee80211_hw *hw) | ||
2505 | { | ||
2506 | } | ||
2507 | |||
2508 | void rtl88ee_resume(struct ieee80211_hw *hw) | ||
2509 | { | ||
2510 | } | ||
2511 | |||
2512 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
2513 | void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw, | ||
2514 | bool allow_all_da, bool write_into_reg) | ||
2515 | { | ||
2516 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2517 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
2518 | |||
2519 | if (allow_all_da) /* Set BIT0 */ | ||
2520 | rtlpci->receive_config |= RCR_AAP; | ||
2521 | else /* Clear BIT0 */ | ||
2522 | rtlpci->receive_config &= ~RCR_AAP; | ||
2523 | |||
2524 | if (write_into_reg) | ||
2525 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
2526 | |||
2527 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
2528 | "receive_config = 0x%08X, write_into_reg =%d\n", | ||
2529 | rtlpci->receive_config, write_into_reg); | ||
2530 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h new file mode 100644 index 000000000000..b4460a41bd01 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92CE_HW_H__ | ||
31 | #define __RTL92CE_HW_H__ | ||
32 | |||
33 | void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); | ||
34 | void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw); | ||
35 | void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw, | ||
36 | u32 *p_inta, u32 *p_intb); | ||
37 | int rtl88ee_hw_init(struct ieee80211_hw *hw); | ||
38 | void rtl88ee_card_disable(struct ieee80211_hw *hw); | ||
39 | void rtl88ee_enable_interrupt(struct ieee80211_hw *hw); | ||
40 | void rtl88ee_disable_interrupt(struct ieee80211_hw *hw); | ||
41 | int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); | ||
42 | void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); | ||
43 | void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci); | ||
44 | void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw); | ||
45 | void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw); | ||
46 | void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw, | ||
47 | u32 add_msr, u32 rm_msr); | ||
48 | void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); | ||
49 | void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw, | ||
50 | struct ieee80211_sta *sta, u8 rssi_level); | ||
51 | void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw); | ||
52 | bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); | ||
53 | void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw); | ||
54 | void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key_index, | ||
55 | u8 *p_macaddr, bool is_group, u8 enc_algo, | ||
56 | bool is_wepkey, bool clear_all); | ||
57 | |||
58 | void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, | ||
59 | bool autoload_fail, u8 *hwinfo); | ||
60 | void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw); | ||
61 | void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw); | ||
62 | void rtl88ee_suspend(struct ieee80211_hw *hw); | ||
63 | void rtl88ee_resume(struct ieee80211_hw *hw); | ||
64 | void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw, | ||
65 | bool allow_all_da, bool write_into_reg); | ||
66 | void rtl88ee_fw_clk_off_timer_callback(unsigned long data); | ||
67 | |||
68 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/rtlwifi/rtl8188ee/led.c new file mode 100644 index 000000000000..c81a9cb6894c --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/led.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "reg.h" | ||
33 | #include "led.h" | ||
34 | |||
35 | static void rtl88ee_init_led(struct ieee80211_hw *hw, | ||
36 | struct rtl_led *pled, enum rtl_led_pin ledpin) | ||
37 | { | ||
38 | pled->hw = hw; | ||
39 | pled->ledpin = ledpin; | ||
40 | pled->ledon = false; | ||
41 | } | ||
42 | |||
43 | void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) | ||
44 | { | ||
45 | u8 ledcfg; | ||
46 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
47 | |||
48 | RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, | ||
49 | "LedAddr:%X ledpin =%d\n", REG_LEDCFG2, pled->ledpin); | ||
50 | |||
51 | switch (pled->ledpin) { | ||
52 | case LED_PIN_GPIO0: | ||
53 | break; | ||
54 | case LED_PIN_LED0: | ||
55 | ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); | ||
56 | rtl_write_byte(rtlpriv, REG_LEDCFG2, | ||
57 | (ledcfg & 0xf0) | BIT(5) | BIT(6)); | ||
58 | break; | ||
59 | case LED_PIN_LED1: | ||
60 | ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); | ||
61 | rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); | ||
62 | break; | ||
63 | default: | ||
64 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
65 | "switch case not processed\n"); | ||
66 | break; | ||
67 | } | ||
68 | pled->ledon = true; | ||
69 | } | ||
70 | |||
71 | void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) | ||
72 | { | ||
73 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
74 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
75 | u8 ledcfg; | ||
76 | u8 val; | ||
77 | |||
78 | RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, | ||
79 | "LedAddr:%X ledpin =%d\n", REG_LEDCFG2, pled->ledpin); | ||
80 | |||
81 | switch (pled->ledpin) { | ||
82 | case LED_PIN_GPIO0: | ||
83 | break; | ||
84 | case LED_PIN_LED0: | ||
85 | ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); | ||
86 | ledcfg &= 0xf0; | ||
87 | val = ledcfg | BIT(3) | BIT(5) | BIT(6); | ||
88 | if (pcipriv->ledctl.led_opendrain == true) { | ||
89 | rtl_write_byte(rtlpriv, REG_LEDCFG2, val); | ||
90 | ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); | ||
91 | val = ledcfg & 0xFE; | ||
92 | rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, val); | ||
93 | } else { | ||
94 | rtl_write_byte(rtlpriv, REG_LEDCFG2, val); | ||
95 | } | ||
96 | break; | ||
97 | case LED_PIN_LED1: | ||
98 | ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); | ||
99 | ledcfg &= 0x10; | ||
100 | rtl_write_byte(rtlpriv, REG_LEDCFG1, (ledcfg | BIT(3))); | ||
101 | break; | ||
102 | default: | ||
103 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
104 | "switch case not processed\n"); | ||
105 | break; | ||
106 | } | ||
107 | pled->ledon = false; | ||
108 | } | ||
109 | |||
110 | void rtl88ee_init_sw_leds(struct ieee80211_hw *hw) | ||
111 | { | ||
112 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
113 | |||
114 | rtl88ee_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); | ||
115 | rtl88ee_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); | ||
116 | } | ||
117 | |||
118 | static void rtl88ee_sw_led_control(struct ieee80211_hw *hw, | ||
119 | enum led_ctl_mode ledaction) | ||
120 | { | ||
121 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
122 | struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); | ||
123 | |||
124 | switch (ledaction) { | ||
125 | case LED_CTL_POWER_ON: | ||
126 | case LED_CTL_LINK: | ||
127 | case LED_CTL_NO_LINK: | ||
128 | rtl88ee_sw_led_on(hw, pLed0); | ||
129 | break; | ||
130 | case LED_CTL_POWER_OFF: | ||
131 | rtl88ee_sw_led_off(hw, pLed0); | ||
132 | break; | ||
133 | default: | ||
134 | break; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | void rtl88ee_led_control(struct ieee80211_hw *hw, | ||
139 | enum led_ctl_mode ledaction) | ||
140 | { | ||
141 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
142 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
143 | |||
144 | if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && | ||
145 | (ledaction == LED_CTL_TX || | ||
146 | ledaction == LED_CTL_RX || | ||
147 | ledaction == LED_CTL_SITE_SURVEY || | ||
148 | ledaction == LED_CTL_LINK || | ||
149 | ledaction == LED_CTL_NO_LINK || | ||
150 | ledaction == LED_CTL_START_TO_LINK || | ||
151 | ledaction == LED_CTL_POWER_ON)) { | ||
152 | return; | ||
153 | } | ||
154 | RT_TRACE(rtlpriv, COMP_LED, DBG_TRACE, "ledaction %d,\n", | ||
155 | ledaction); | ||
156 | rtl88ee_sw_led_control(hw, ledaction); | ||
157 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/rtlwifi/rtl8188ee/led.h new file mode 100644 index 000000000000..4073f6f847b2 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/led.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92CE_LED_H__ | ||
31 | #define __RTL92CE_LED_H__ | ||
32 | |||
33 | void rtl88ee_init_sw_leds(struct ieee80211_hw *hw); | ||
34 | void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); | ||
35 | void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); | ||
36 | void rtl88ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); | ||
37 | |||
38 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c new file mode 100644 index 000000000000..e655c0473225 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c | |||
@@ -0,0 +1,2202 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "../ps.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "phy.h" | ||
36 | #include "rf.h" | ||
37 | #include "dm.h" | ||
38 | #include "table.h" | ||
39 | |||
40 | static void set_baseband_phy_config(struct ieee80211_hw *hw); | ||
41 | static void set_baseband_agc_config(struct ieee80211_hw *hw); | ||
42 | static void store_pwrindex_offset(struct ieee80211_hw *hw, | ||
43 | u32 regaddr, u32 bitmask, | ||
44 | u32 data); | ||
45 | static bool check_cond(struct ieee80211_hw *hw, const u32 condition); | ||
46 | |||
47 | static u32 rf_serial_read(struct ieee80211_hw *hw, | ||
48 | enum radio_path rfpath, u32 offset) | ||
49 | { | ||
50 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
51 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
52 | struct bb_reg_def *phreg = &rtlphy->phyreg_def[rfpath]; | ||
53 | u32 newoffset; | ||
54 | u32 tmplong, tmplong2; | ||
55 | u8 rfpi_enable = 0; | ||
56 | u32 ret; | ||
57 | int jj = RF90_PATH_A; | ||
58 | int kk = RF90_PATH_B; | ||
59 | |||
60 | offset &= 0xff; | ||
61 | newoffset = offset; | ||
62 | if (RT_CANNOT_IO(hw)) { | ||
63 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); | ||
64 | return 0xFFFFFFFF; | ||
65 | } | ||
66 | tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); | ||
67 | if (rfpath == jj) | ||
68 | tmplong2 = tmplong; | ||
69 | else | ||
70 | tmplong2 = rtl_get_bbreg(hw, phreg->rfhssi_para2, MASKDWORD); | ||
71 | tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | | ||
72 | (newoffset << 23) | BLSSIREADEDGE; | ||
73 | rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, | ||
74 | tmplong & (~BLSSIREADEDGE)); | ||
75 | mdelay(1); | ||
76 | rtl_set_bbreg(hw, phreg->rfhssi_para2, MASKDWORD, tmplong2); | ||
77 | mdelay(2); | ||
78 | if (rfpath == jj) | ||
79 | rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, | ||
80 | BIT(8)); | ||
81 | else if (rfpath == kk) | ||
82 | rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, | ||
83 | BIT(8)); | ||
84 | if (rfpi_enable) | ||
85 | ret = rtl_get_bbreg(hw, phreg->rf_rbpi, BLSSIREADBACKDATA); | ||
86 | else | ||
87 | ret = rtl_get_bbreg(hw, phreg->rf_rb, BLSSIREADBACKDATA); | ||
88 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]= 0x%x\n", | ||
89 | rfpath, phreg->rf_rb, ret); | ||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | static void rf_serial_write(struct ieee80211_hw *hw, | ||
94 | enum radio_path rfpath, u32 offset, | ||
95 | u32 data) | ||
96 | { | ||
97 | u32 data_and_addr; | ||
98 | u32 newoffset; | ||
99 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
100 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
101 | struct bb_reg_def *phreg = &rtlphy->phyreg_def[rfpath]; | ||
102 | |||
103 | if (RT_CANNOT_IO(hw)) { | ||
104 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); | ||
105 | return; | ||
106 | } | ||
107 | offset &= 0xff; | ||
108 | newoffset = offset; | ||
109 | data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; | ||
110 | rtl_set_bbreg(hw, phreg->rf3wire_offset, MASKDWORD, data_and_addr); | ||
111 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]= 0x%x\n", | ||
112 | rfpath, phreg->rf3wire_offset, data_and_addr); | ||
113 | } | ||
114 | |||
115 | static u32 cal_bit_shift(u32 bitmask) | ||
116 | { | ||
117 | u32 i; | ||
118 | |||
119 | for (i = 0; i <= 31; i++) { | ||
120 | if (((bitmask >> i) & 0x1) == 1) | ||
121 | break; | ||
122 | } | ||
123 | return i; | ||
124 | } | ||
125 | |||
126 | static bool config_bb_with_header(struct ieee80211_hw *hw, | ||
127 | u8 configtype) | ||
128 | { | ||
129 | if (configtype == BASEBAND_CONFIG_PHY_REG) | ||
130 | set_baseband_phy_config(hw); | ||
131 | else if (configtype == BASEBAND_CONFIG_AGC_TAB) | ||
132 | set_baseband_agc_config(hw); | ||
133 | return true; | ||
134 | } | ||
135 | |||
136 | static bool config_bb_with_pgheader(struct ieee80211_hw *hw, | ||
137 | u8 configtype) | ||
138 | { | ||
139 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
140 | int i; | ||
141 | u32 *table_pg; | ||
142 | u16 tbl_page_len; | ||
143 | u32 v1 = 0, v2 = 0; | ||
144 | |||
145 | tbl_page_len = RTL8188EEPHY_REG_ARRAY_PGLEN; | ||
146 | table_pg = RTL8188EEPHY_REG_ARRAY_PG; | ||
147 | |||
148 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | ||
149 | for (i = 0; i < tbl_page_len; i = i + 3) { | ||
150 | v1 = table_pg[i]; | ||
151 | v2 = table_pg[i + 1]; | ||
152 | |||
153 | if (v1 < 0xcdcdcdcd) { | ||
154 | if (table_pg[i] == 0xfe) | ||
155 | mdelay(50); | ||
156 | else if (table_pg[i] == 0xfd) | ||
157 | mdelay(5); | ||
158 | else if (table_pg[i] == 0xfc) | ||
159 | mdelay(1); | ||
160 | else if (table_pg[i] == 0xfb) | ||
161 | udelay(50); | ||
162 | else if (table_pg[i] == 0xfa) | ||
163 | udelay(5); | ||
164 | else if (table_pg[i] == 0xf9) | ||
165 | udelay(1); | ||
166 | |||
167 | store_pwrindex_offset(hw, table_pg[i], | ||
168 | table_pg[i + 1], | ||
169 | table_pg[i + 2]); | ||
170 | continue; | ||
171 | } else { | ||
172 | if (!check_cond(hw, table_pg[i])) { | ||
173 | /*don't need the hw_body*/ | ||
174 | i += 2; /* skip the pair of expression*/ | ||
175 | v1 = table_pg[i]; | ||
176 | v2 = table_pg[i + 1]; | ||
177 | while (v2 != 0xDEAD) { | ||
178 | i += 3; | ||
179 | v1 = table_pg[i]; | ||
180 | v2 = table_pg[i + 1]; | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | } else { | ||
186 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
187 | "configtype != BaseBand_Config_PHY_REG\n"); | ||
188 | } | ||
189 | return true; | ||
190 | } | ||
191 | |||
192 | static bool config_parafile(struct ieee80211_hw *hw) | ||
193 | { | ||
194 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
195 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
196 | struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw)); | ||
197 | bool rtstatus; | ||
198 | |||
199 | rtstatus = config_bb_with_header(hw, BASEBAND_CONFIG_PHY_REG); | ||
200 | if (rtstatus != true) { | ||
201 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); | ||
202 | return false; | ||
203 | } | ||
204 | |||
205 | if (fuse->autoload_failflag == false) { | ||
206 | rtlphy->pwrgroup_cnt = 0; | ||
207 | rtstatus = config_bb_with_pgheader(hw, BASEBAND_CONFIG_PHY_REG); | ||
208 | } | ||
209 | if (rtstatus != true) { | ||
210 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); | ||
211 | return false; | ||
212 | } | ||
213 | rtstatus = config_bb_with_header(hw, BASEBAND_CONFIG_AGC_TAB); | ||
214 | if (rtstatus != true) { | ||
215 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); | ||
216 | return false; | ||
217 | } | ||
218 | rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, | ||
219 | RFPGA0_XA_HSSIPARAMETER2, 0x200)); | ||
220 | |||
221 | return true; | ||
222 | } | ||
223 | |||
224 | static void rtl88e_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) | ||
225 | { | ||
226 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
227 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
228 | int jj = RF90_PATH_A; | ||
229 | int kk = RF90_PATH_B; | ||
230 | |||
231 | rtlphy->phyreg_def[jj].rfintfs = RFPGA0_XAB_RFINTERFACESW; | ||
232 | rtlphy->phyreg_def[kk].rfintfs = RFPGA0_XAB_RFINTERFACESW; | ||
233 | rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; | ||
234 | rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; | ||
235 | |||
236 | rtlphy->phyreg_def[jj].rfintfi = RFPGA0_XAB_RFINTERFACERB; | ||
237 | rtlphy->phyreg_def[kk].rfintfi = RFPGA0_XAB_RFINTERFACERB; | ||
238 | rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; | ||
239 | rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; | ||
240 | |||
241 | rtlphy->phyreg_def[jj].rfintfo = RFPGA0_XA_RFINTERFACEOE; | ||
242 | rtlphy->phyreg_def[kk].rfintfo = RFPGA0_XB_RFINTERFACEOE; | ||
243 | |||
244 | rtlphy->phyreg_def[jj].rfintfe = RFPGA0_XA_RFINTERFACEOE; | ||
245 | rtlphy->phyreg_def[kk].rfintfe = RFPGA0_XB_RFINTERFACEOE; | ||
246 | |||
247 | rtlphy->phyreg_def[jj].rf3wire_offset = RFPGA0_XA_LSSIPARAMETER; | ||
248 | rtlphy->phyreg_def[kk].rf3wire_offset = RFPGA0_XB_LSSIPARAMETER; | ||
249 | |||
250 | rtlphy->phyreg_def[jj].rflssi_select = rFPGA0_XAB_RFPARAMETER; | ||
251 | rtlphy->phyreg_def[kk].rflssi_select = rFPGA0_XAB_RFPARAMETER; | ||
252 | rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER; | ||
253 | rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER; | ||
254 | |||
255 | rtlphy->phyreg_def[jj].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
256 | rtlphy->phyreg_def[kk].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
257 | rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
258 | rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
259 | |||
260 | rtlphy->phyreg_def[jj].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; | ||
261 | rtlphy->phyreg_def[kk].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; | ||
262 | |||
263 | rtlphy->phyreg_def[jj].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; | ||
264 | rtlphy->phyreg_def[kk].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; | ||
265 | |||
266 | rtlphy->phyreg_def[jj].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; | ||
267 | rtlphy->phyreg_def[kk].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; | ||
268 | rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; | ||
269 | rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; | ||
270 | |||
271 | rtlphy->phyreg_def[jj].rfagc_control1 = ROFDM0_XAAGCCORE1; | ||
272 | rtlphy->phyreg_def[kk].rfagc_control1 = ROFDM0_XBAGCCORE1; | ||
273 | rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; | ||
274 | rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; | ||
275 | |||
276 | rtlphy->phyreg_def[jj].rfagc_control2 = ROFDM0_XAAGCCORE2; | ||
277 | rtlphy->phyreg_def[kk].rfagc_control2 = ROFDM0_XBAGCCORE2; | ||
278 | rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; | ||
279 | rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; | ||
280 | |||
281 | rtlphy->phyreg_def[jj].rfrxiq_imbal = ROFDM0_XARXIQIMBAL; | ||
282 | rtlphy->phyreg_def[kk].rfrxiq_imbal = ROFDM0_XBRXIQIMBAL; | ||
283 | rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBAL; | ||
284 | rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBAL; | ||
285 | |||
286 | rtlphy->phyreg_def[jj].rfrx_afe = ROFDM0_XARXAFE; | ||
287 | rtlphy->phyreg_def[kk].rfrx_afe = ROFDM0_XBRXAFE; | ||
288 | rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; | ||
289 | rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; | ||
290 | |||
291 | rtlphy->phyreg_def[jj].rftxiq_imbal = ROFDM0_XATXIQIMBAL; | ||
292 | rtlphy->phyreg_def[kk].rftxiq_imbal = ROFDM0_XBTXIQIMBAL; | ||
293 | rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBAL; | ||
294 | rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBAL; | ||
295 | |||
296 | rtlphy->phyreg_def[jj].rftx_afe = ROFDM0_XATXAFE; | ||
297 | rtlphy->phyreg_def[kk].rftx_afe = ROFDM0_XBTXAFE; | ||
298 | |||
299 | rtlphy->phyreg_def[jj].rf_rb = RFPGA0_XA_LSSIREADBACK; | ||
300 | rtlphy->phyreg_def[kk].rf_rb = RFPGA0_XB_LSSIREADBACK; | ||
301 | |||
302 | rtlphy->phyreg_def[jj].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; | ||
303 | rtlphy->phyreg_def[kk].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; | ||
304 | } | ||
305 | |||
306 | static bool rtl88e_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, | ||
307 | u32 cmdtableidx, u32 cmdtablesz, | ||
308 | enum swchnlcmd_id cmdid, | ||
309 | u32 para1, u32 para2, u32 msdelay) | ||
310 | { | ||
311 | struct swchnlcmd *pcmd; | ||
312 | |||
313 | if (cmdtable == NULL) { | ||
314 | RT_ASSERT(false, "cmdtable cannot be NULL.\n"); | ||
315 | return false; | ||
316 | } | ||
317 | |||
318 | if (cmdtableidx >= cmdtablesz) | ||
319 | return false; | ||
320 | |||
321 | pcmd = cmdtable + cmdtableidx; | ||
322 | pcmd->cmdid = cmdid; | ||
323 | pcmd->para1 = para1; | ||
324 | pcmd->para2 = para2; | ||
325 | pcmd->msdelay = msdelay; | ||
326 | return true; | ||
327 | } | ||
328 | |||
329 | static bool chnl_step_by_step(struct ieee80211_hw *hw, | ||
330 | u8 channel, u8 *stage, u8 *step, | ||
331 | u32 *delay) | ||
332 | { | ||
333 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
334 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
335 | struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; | ||
336 | u32 precommoncmdcnt; | ||
337 | struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; | ||
338 | u32 postcommoncmdcnt; | ||
339 | struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; | ||
340 | u32 rfdependcmdcnt; | ||
341 | struct swchnlcmd *currentcmd = NULL; | ||
342 | u8 rfpath; | ||
343 | u8 num_total_rfpath = rtlphy->num_total_rfpath; | ||
344 | |||
345 | precommoncmdcnt = 0; | ||
346 | rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, | ||
347 | MAX_PRECMD_CNT, | ||
348 | CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); | ||
349 | rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, | ||
350 | MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); | ||
351 | |||
352 | postcommoncmdcnt = 0; | ||
353 | |||
354 | rtl88e_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, | ||
355 | MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); | ||
356 | |||
357 | rfdependcmdcnt = 0; | ||
358 | |||
359 | RT_ASSERT((channel >= 1 && channel <= 14), | ||
360 | "illegal channel for Zebra: %d\n", channel); | ||
361 | |||
362 | rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, | ||
363 | MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, | ||
364 | RF_CHNLBW, channel, 10); | ||
365 | |||
366 | rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, | ||
367 | MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, | ||
368 | 0); | ||
369 | |||
370 | do { | ||
371 | switch (*stage) { | ||
372 | case 0: | ||
373 | currentcmd = &precommoncmd[*step]; | ||
374 | break; | ||
375 | case 1: | ||
376 | currentcmd = &rfdependcmd[*step]; | ||
377 | break; | ||
378 | case 2: | ||
379 | currentcmd = &postcommoncmd[*step]; | ||
380 | break; | ||
381 | } | ||
382 | |||
383 | if (currentcmd->cmdid == CMDID_END) { | ||
384 | if ((*stage) == 2) { | ||
385 | return true; | ||
386 | } else { | ||
387 | (*stage)++; | ||
388 | (*step) = 0; | ||
389 | continue; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | switch (currentcmd->cmdid) { | ||
394 | case CMDID_SET_TXPOWEROWER_LEVEL: | ||
395 | rtl88e_phy_set_txpower_level(hw, channel); | ||
396 | break; | ||
397 | case CMDID_WRITEPORT_ULONG: | ||
398 | rtl_write_dword(rtlpriv, currentcmd->para1, | ||
399 | currentcmd->para2); | ||
400 | break; | ||
401 | case CMDID_WRITEPORT_USHORT: | ||
402 | rtl_write_word(rtlpriv, currentcmd->para1, | ||
403 | (u16) currentcmd->para2); | ||
404 | break; | ||
405 | case CMDID_WRITEPORT_UCHAR: | ||
406 | rtl_write_byte(rtlpriv, currentcmd->para1, | ||
407 | (u8) currentcmd->para2); | ||
408 | break; | ||
409 | case CMDID_RF_WRITEREG: | ||
410 | for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { | ||
411 | rtlphy->rfreg_chnlval[rfpath] = | ||
412 | ((rtlphy->rfreg_chnlval[rfpath] & | ||
413 | 0xfffffc00) | currentcmd->para2); | ||
414 | |||
415 | rtl_set_rfreg(hw, (enum radio_path)rfpath, | ||
416 | currentcmd->para1, | ||
417 | RFREG_OFFSET_MASK, | ||
418 | rtlphy->rfreg_chnlval[rfpath]); | ||
419 | } | ||
420 | break; | ||
421 | default: | ||
422 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
423 | "switch case not processed\n"); | ||
424 | break; | ||
425 | } | ||
426 | |||
427 | break; | ||
428 | } while (true); | ||
429 | |||
430 | (*delay) = currentcmd->msdelay; | ||
431 | (*step)++; | ||
432 | return false; | ||
433 | } | ||
434 | |||
435 | static long rtl88e_pwr_idx_dbm(struct ieee80211_hw *hw, | ||
436 | enum wireless_mode wirelessmode, | ||
437 | u8 txpwridx) | ||
438 | { | ||
439 | long offset; | ||
440 | long pwrout_dbm; | ||
441 | |||
442 | switch (wirelessmode) { | ||
443 | case WIRELESS_MODE_B: | ||
444 | offset = -7; | ||
445 | break; | ||
446 | case WIRELESS_MODE_G: | ||
447 | case WIRELESS_MODE_N_24G: | ||
448 | offset = -8; | ||
449 | break; | ||
450 | default: | ||
451 | offset = -8; | ||
452 | break; | ||
453 | } | ||
454 | pwrout_dbm = txpwridx / 2 + offset; | ||
455 | return pwrout_dbm; | ||
456 | } | ||
457 | |||
458 | static void rtl88e_phy_set_io(struct ieee80211_hw *hw) | ||
459 | { | ||
460 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
461 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
462 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; | ||
463 | |||
464 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
465 | "--->Cmd(%#x), set_io_inprogress(%d)\n", | ||
466 | rtlphy->current_io_type, rtlphy->set_io_inprogress); | ||
467 | switch (rtlphy->current_io_type) { | ||
468 | case IO_CMD_RESUME_DM_BY_SCAN: | ||
469 | dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; | ||
470 | /*rtl92c_dm_write_dig(hw);*/ | ||
471 | rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel); | ||
472 | rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x83); | ||
473 | break; | ||
474 | case IO_CMD_PAUSE_DM_BY_SCAN: | ||
475 | rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; | ||
476 | dm_digtable->cur_igvalue = 0x17; | ||
477 | rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x40); | ||
478 | break; | ||
479 | default: | ||
480 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
481 | "switch case not processed\n"); | ||
482 | break; | ||
483 | } | ||
484 | rtlphy->set_io_inprogress = false; | ||
485 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
486 | "(%#x)\n", rtlphy->current_io_type); | ||
487 | } | ||
488 | |||
489 | u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) | ||
490 | { | ||
491 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
492 | u32 returnvalue, originalvalue, bitshift; | ||
493 | |||
494 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
495 | "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask); | ||
496 | originalvalue = rtl_read_dword(rtlpriv, regaddr); | ||
497 | bitshift = cal_bit_shift(bitmask); | ||
498 | returnvalue = (originalvalue & bitmask) >> bitshift; | ||
499 | |||
500 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
501 | "BBR MASK = 0x%x Addr[0x%x]= 0x%x\n", bitmask, | ||
502 | regaddr, originalvalue); | ||
503 | |||
504 | return returnvalue; | ||
505 | } | ||
506 | |||
507 | void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, | ||
508 | u32 regaddr, u32 bitmask, u32 data) | ||
509 | { | ||
510 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
511 | u32 originalvalue, bitshift; | ||
512 | |||
513 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
514 | "regaddr(%#x), bitmask(%#x),data(%#x)\n", | ||
515 | regaddr, bitmask, data); | ||
516 | |||
517 | if (bitmask != MASKDWORD) { | ||
518 | originalvalue = rtl_read_dword(rtlpriv, regaddr); | ||
519 | bitshift = cal_bit_shift(bitmask); | ||
520 | data = ((originalvalue & (~bitmask)) | (data << bitshift)); | ||
521 | } | ||
522 | |||
523 | rtl_write_dword(rtlpriv, regaddr, data); | ||
524 | |||
525 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
526 | "regaddr(%#x), bitmask(%#x), data(%#x)\n", | ||
527 | regaddr, bitmask, data); | ||
528 | } | ||
529 | |||
530 | u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, | ||
531 | enum radio_path rfpath, u32 regaddr, u32 bitmask) | ||
532 | { | ||
533 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
534 | u32 original_value, readback_value, bitshift; | ||
535 | unsigned long flags; | ||
536 | |||
537 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
538 | "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", | ||
539 | regaddr, rfpath, bitmask); | ||
540 | |||
541 | spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); | ||
542 | |||
543 | |||
544 | original_value = rf_serial_read(hw, rfpath, regaddr); | ||
545 | bitshift = cal_bit_shift(bitmask); | ||
546 | readback_value = (original_value & bitmask) >> bitshift; | ||
547 | |||
548 | spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); | ||
549 | |||
550 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
551 | "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", | ||
552 | regaddr, rfpath, bitmask, original_value); | ||
553 | |||
554 | return readback_value; | ||
555 | } | ||
556 | |||
557 | void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, | ||
558 | enum radio_path rfpath, | ||
559 | u32 regaddr, u32 bitmask, u32 data) | ||
560 | { | ||
561 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
562 | u32 original_value, bitshift; | ||
563 | unsigned long flags; | ||
564 | |||
565 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
566 | "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", | ||
567 | regaddr, bitmask, data, rfpath); | ||
568 | |||
569 | spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); | ||
570 | |||
571 | if (bitmask != RFREG_OFFSET_MASK) { | ||
572 | original_value = rf_serial_read(hw, rfpath, regaddr); | ||
573 | bitshift = cal_bit_shift(bitmask); | ||
574 | data = ((original_value & (~bitmask)) | | ||
575 | (data << bitshift)); | ||
576 | } | ||
577 | |||
578 | rf_serial_write(hw, rfpath, regaddr, data); | ||
579 | |||
580 | |||
581 | spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); | ||
582 | |||
583 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
584 | "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", | ||
585 | regaddr, bitmask, data, rfpath); | ||
586 | } | ||
587 | |||
588 | static bool config_mac_with_header(struct ieee80211_hw *hw) | ||
589 | { | ||
590 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
591 | u32 i; | ||
592 | u32 arraylength; | ||
593 | u32 *ptrarray; | ||
594 | |||
595 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl8188EMACPHY_Array\n"); | ||
596 | arraylength = RTL8188EEMAC_1T_ARRAYLEN; | ||
597 | ptrarray = RTL8188EEMAC_1T_ARRAY; | ||
598 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
599 | "Img:RTL8188EEMAC_1T_ARRAY LEN %d\n", arraylength); | ||
600 | for (i = 0; i < arraylength; i = i + 2) | ||
601 | rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); | ||
602 | return true; | ||
603 | } | ||
604 | |||
605 | bool rtl88e_phy_mac_config(struct ieee80211_hw *hw) | ||
606 | { | ||
607 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
608 | bool rtstatus = config_mac_with_header(hw); | ||
609 | |||
610 | rtl_write_byte(rtlpriv, 0x04CA, 0x0B); | ||
611 | return rtstatus; | ||
612 | } | ||
613 | |||
614 | bool rtl88e_phy_bb_config(struct ieee80211_hw *hw) | ||
615 | { | ||
616 | bool rtstatus = true; | ||
617 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
618 | u16 regval; | ||
619 | u8 reg_hwparafile = 1; | ||
620 | u32 tmp; | ||
621 | rtl88e_phy_init_bb_rf_register_definition(hw); | ||
622 | regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); | ||
623 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, | ||
624 | regval | BIT(13) | BIT(0) | BIT(1)); | ||
625 | |||
626 | rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); | ||
627 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, | ||
628 | FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | | ||
629 | FEN_BB_GLB_RSTN | FEN_BBRSTB); | ||
630 | tmp = rtl_read_dword(rtlpriv, 0x4c); | ||
631 | rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23)); | ||
632 | if (reg_hwparafile == 1) | ||
633 | rtstatus = config_parafile(hw); | ||
634 | return rtstatus; | ||
635 | } | ||
636 | |||
637 | bool rtl88e_phy_rf_config(struct ieee80211_hw *hw) | ||
638 | { | ||
639 | return rtl88e_phy_rf6052_config(hw); | ||
640 | } | ||
641 | |||
642 | static bool check_cond(struct ieee80211_hw *hw, | ||
643 | const u32 condition) | ||
644 | { | ||
645 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
646 | struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw)); | ||
647 | u32 _board = fuse->board_type; /*need efuse define*/ | ||
648 | u32 _interface = rtlhal->interface; | ||
649 | u32 _platform = 0x08;/*SupportPlatform */ | ||
650 | u32 cond = condition; | ||
651 | |||
652 | if (condition == 0xCDCDCDCD) | ||
653 | return true; | ||
654 | |||
655 | cond = condition & 0xFF; | ||
656 | if ((_board & cond) == 0 && cond != 0x1F) | ||
657 | return false; | ||
658 | |||
659 | cond = condition & 0xFF00; | ||
660 | cond = cond >> 8; | ||
661 | if ((_interface & cond) == 0 && cond != 0x07) | ||
662 | return false; | ||
663 | |||
664 | cond = condition & 0xFF0000; | ||
665 | cond = cond >> 16; | ||
666 | if ((_platform & cond) == 0 && cond != 0x0F) | ||
667 | return false; | ||
668 | return true; | ||
669 | } | ||
670 | |||
671 | static void _rtl8188e_config_rf_reg(struct ieee80211_hw *hw, | ||
672 | u32 addr, u32 data, enum radio_path rfpath, | ||
673 | u32 regaddr) | ||
674 | { | ||
675 | if (addr == 0xffe) { | ||
676 | mdelay(50); | ||
677 | } else if (addr == 0xfd) { | ||
678 | mdelay(5); | ||
679 | } else if (addr == 0xfc) { | ||
680 | mdelay(1); | ||
681 | } else if (addr == 0xfb) { | ||
682 | udelay(50); | ||
683 | } else if (addr == 0xfa) { | ||
684 | udelay(5); | ||
685 | } else if (addr == 0xf9) { | ||
686 | udelay(1); | ||
687 | } else { | ||
688 | rtl_set_rfreg(hw, rfpath, regaddr, | ||
689 | RFREG_OFFSET_MASK, | ||
690 | data); | ||
691 | udelay(1); | ||
692 | } | ||
693 | } | ||
694 | |||
695 | static void rtl88_config_s(struct ieee80211_hw *hw, | ||
696 | u32 addr, u32 data) | ||
697 | { | ||
698 | u32 content = 0x1000; /*RF Content: radio_a_txt*/ | ||
699 | u32 maskforphyset = (u32)(content & 0xE000); | ||
700 | |||
701 | _rtl8188e_config_rf_reg(hw, addr, data, RF90_PATH_A, | ||
702 | addr | maskforphyset); | ||
703 | } | ||
704 | |||
705 | static void _rtl8188e_config_bb_reg(struct ieee80211_hw *hw, | ||
706 | u32 addr, u32 data) | ||
707 | { | ||
708 | if (addr == 0xfe) { | ||
709 | mdelay(50); | ||
710 | } else if (addr == 0xfd) { | ||
711 | mdelay(5); | ||
712 | } else if (addr == 0xfc) { | ||
713 | mdelay(1); | ||
714 | } else if (addr == 0xfb) { | ||
715 | udelay(50); | ||
716 | } else if (addr == 0xfa) { | ||
717 | udelay(5); | ||
718 | } else if (addr == 0xf9) { | ||
719 | udelay(1); | ||
720 | } else { | ||
721 | rtl_set_bbreg(hw, addr, MASKDWORD, data); | ||
722 | udelay(1); | ||
723 | } | ||
724 | } | ||
725 | |||
726 | |||
727 | #define NEXT_PAIR(v1, v2, i) \ | ||
728 | do { \ | ||
729 | i += 2; v1 = array_table[i]; \ | ||
730 | v2 = array_table[i + 1]; \ | ||
731 | } while (0) | ||
732 | |||
733 | static void set_baseband_agc_config(struct ieee80211_hw *hw) | ||
734 | { | ||
735 | int i; | ||
736 | u32 *array_table; | ||
737 | u16 arraylen; | ||
738 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
739 | u32 v1 = 0, v2 = 0; | ||
740 | |||
741 | arraylen = RTL8188EEAGCTAB_1TARRAYLEN; | ||
742 | array_table = RTL8188EEAGCTAB_1TARRAY; | ||
743 | |||
744 | for (i = 0; i < arraylen; i += 2) { | ||
745 | v1 = array_table[i]; | ||
746 | v2 = array_table[i + 1]; | ||
747 | if (v1 < 0xCDCDCDCD) { | ||
748 | rtl_set_bbreg(hw, array_table[i], MASKDWORD, | ||
749 | array_table[i + 1]); | ||
750 | udelay(1); | ||
751 | continue; | ||
752 | } else {/*This line is the start line of branch.*/ | ||
753 | if (!check_cond(hw, array_table[i])) { | ||
754 | /*Discard the following (offset, data) pairs*/ | ||
755 | NEXT_PAIR(v1, v2, i); | ||
756 | while (v2 != 0xDEAD && v2 != 0xCDEF && | ||
757 | v2 != 0xCDCD && i < arraylen - 2) { | ||
758 | NEXT_PAIR(v1, v2, i); | ||
759 | } | ||
760 | i -= 2; /* compensate for loop's += 2*/ | ||
761 | } else { | ||
762 | /* Configure matched pairs and skip to end */ | ||
763 | NEXT_PAIR(v1, v2, i); | ||
764 | while (v2 != 0xDEAD && v2 != 0xCDEF && | ||
765 | v2 != 0xCDCD && i < arraylen - 2) { | ||
766 | rtl_set_bbreg(hw, array_table[i], | ||
767 | MASKDWORD, | ||
768 | array_table[i + 1]); | ||
769 | udelay(1); | ||
770 | NEXT_PAIR(v1, v2, i); | ||
771 | } | ||
772 | |||
773 | while (v2 != 0xDEAD && i < arraylen - 2) | ||
774 | NEXT_PAIR(v1, v2, i); | ||
775 | } | ||
776 | } | ||
777 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
778 | "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n", | ||
779 | array_table[i], | ||
780 | array_table[i + 1]); | ||
781 | } | ||
782 | } | ||
783 | |||
784 | static void set_baseband_phy_config(struct ieee80211_hw *hw) | ||
785 | { | ||
786 | int i; | ||
787 | u32 *array_table; | ||
788 | u16 arraylen; | ||
789 | u32 v1 = 0, v2 = 0; | ||
790 | |||
791 | arraylen = RTL8188EEPHY_REG_1TARRAYLEN; | ||
792 | array_table = RTL8188EEPHY_REG_1TARRAY; | ||
793 | |||
794 | for (i = 0; i < arraylen; i += 2) { | ||
795 | v1 = array_table[i]; | ||
796 | v2 = array_table[i + 1]; | ||
797 | if (v1 < 0xcdcdcdcd) { | ||
798 | _rtl8188e_config_bb_reg(hw, v1, v2); | ||
799 | } else {/*This line is the start line of branch.*/ | ||
800 | if (!check_cond(hw, array_table[i])) { | ||
801 | /*Discard the following (offset, data) pairs*/ | ||
802 | NEXT_PAIR(v1, v2, i); | ||
803 | while (v2 != 0xDEAD && | ||
804 | v2 != 0xCDEF && | ||
805 | v2 != 0xCDCD && i < arraylen - 2) | ||
806 | NEXT_PAIR(v1, v2, i); | ||
807 | i -= 2; /* prevent from for-loop += 2*/ | ||
808 | } else { | ||
809 | /* Configure matched pairs and skip to end */ | ||
810 | NEXT_PAIR(v1, v2, i); | ||
811 | while (v2 != 0xDEAD && | ||
812 | v2 != 0xCDEF && | ||
813 | v2 != 0xCDCD && i < arraylen - 2) { | ||
814 | _rtl8188e_config_bb_reg(hw, v1, v2); | ||
815 | NEXT_PAIR(v1, v2, i); | ||
816 | } | ||
817 | |||
818 | while (v2 != 0xDEAD && i < arraylen - 2) | ||
819 | NEXT_PAIR(v1, v2, i); | ||
820 | } | ||
821 | } | ||
822 | } | ||
823 | } | ||
824 | |||
825 | static void store_pwrindex_offset(struct ieee80211_hw *hw, | ||
826 | u32 regaddr, u32 bitmask, | ||
827 | u32 data) | ||
828 | { | ||
829 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
830 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
831 | |||
832 | if (regaddr == RTXAGC_A_RATE18_06) { | ||
833 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0] = data; | ||
834 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
835 | "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", | ||
836 | rtlphy->pwrgroup_cnt, | ||
837 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0]); | ||
838 | } | ||
839 | if (regaddr == RTXAGC_A_RATE54_24) { | ||
840 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1] = data; | ||
841 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
842 | "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", | ||
843 | rtlphy->pwrgroup_cnt, | ||
844 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1]); | ||
845 | } | ||
846 | if (regaddr == RTXAGC_A_CCK1_MCS32) { | ||
847 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6] = data; | ||
848 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
849 | "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", | ||
850 | rtlphy->pwrgroup_cnt, | ||
851 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6]); | ||
852 | } | ||
853 | if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { | ||
854 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7] = data; | ||
855 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
856 | "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", | ||
857 | rtlphy->pwrgroup_cnt, | ||
858 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7]); | ||
859 | } | ||
860 | if (regaddr == RTXAGC_A_MCS03_MCS00) { | ||
861 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2] = data; | ||
862 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
863 | "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", | ||
864 | rtlphy->pwrgroup_cnt, | ||
865 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2]); | ||
866 | } | ||
867 | if (regaddr == RTXAGC_A_MCS07_MCS04) { | ||
868 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3] = data; | ||
869 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
870 | "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", | ||
871 | rtlphy->pwrgroup_cnt, | ||
872 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3]); | ||
873 | } | ||
874 | if (regaddr == RTXAGC_A_MCS11_MCS08) { | ||
875 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4] = data; | ||
876 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
877 | "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", | ||
878 | rtlphy->pwrgroup_cnt, | ||
879 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4]); | ||
880 | } | ||
881 | if (regaddr == RTXAGC_A_MCS15_MCS12) { | ||
882 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5] = data; | ||
883 | if (get_rf_type(rtlphy) == RF_1T1R) | ||
884 | rtlphy->pwrgroup_cnt++; | ||
885 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
886 | "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", | ||
887 | rtlphy->pwrgroup_cnt, | ||
888 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5]); | ||
889 | } | ||
890 | if (regaddr == RTXAGC_B_RATE18_06) { | ||
891 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8] = data; | ||
892 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
893 | "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", | ||
894 | rtlphy->pwrgroup_cnt, | ||
895 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8]); | ||
896 | } | ||
897 | if (regaddr == RTXAGC_B_RATE54_24) { | ||
898 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9] = data; | ||
899 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
900 | "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", | ||
901 | rtlphy->pwrgroup_cnt, | ||
902 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9]); | ||
903 | } | ||
904 | if (regaddr == RTXAGC_B_CCK1_55_MCS32) { | ||
905 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14] = data; | ||
906 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
907 | "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", | ||
908 | rtlphy->pwrgroup_cnt, | ||
909 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14]); | ||
910 | } | ||
911 | if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { | ||
912 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15] = data; | ||
913 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
914 | "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", | ||
915 | rtlphy->pwrgroup_cnt, | ||
916 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15]); | ||
917 | } | ||
918 | if (regaddr == RTXAGC_B_MCS03_MCS00) { | ||
919 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10] = data; | ||
920 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
921 | "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", | ||
922 | rtlphy->pwrgroup_cnt, | ||
923 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10]); | ||
924 | } | ||
925 | if (regaddr == RTXAGC_B_MCS07_MCS04) { | ||
926 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11] = data; | ||
927 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
928 | "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", | ||
929 | rtlphy->pwrgroup_cnt, | ||
930 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11]); | ||
931 | } | ||
932 | if (regaddr == RTXAGC_B_MCS11_MCS08) { | ||
933 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12] = data; | ||
934 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
935 | "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", | ||
936 | rtlphy->pwrgroup_cnt, | ||
937 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12]); | ||
938 | } | ||
939 | if (regaddr == RTXAGC_B_MCS15_MCS12) { | ||
940 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13] = data; | ||
941 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
942 | "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", | ||
943 | rtlphy->pwrgroup_cnt, | ||
944 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13]); | ||
945 | if (get_rf_type(rtlphy) != RF_1T1R) | ||
946 | rtlphy->pwrgroup_cnt++; | ||
947 | } | ||
948 | } | ||
949 | |||
950 | #define READ_NEXT_RF_PAIR(v1, v2, i) \ | ||
951 | do { \ | ||
952 | i += 2; v1 = a_table[i]; \ | ||
953 | v2 = a_table[i + 1]; \ | ||
954 | } while (0) | ||
955 | |||
956 | bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | ||
957 | enum radio_path rfpath) | ||
958 | { | ||
959 | int i; | ||
960 | u32 *a_table; | ||
961 | u16 a_len; | ||
962 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
963 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
964 | u32 v1 = 0, v2 = 0; | ||
965 | |||
966 | a_len = RTL8188EE_RADIOA_1TARRAYLEN; | ||
967 | a_table = RTL8188EE_RADIOA_1TARRAY; | ||
968 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
969 | "Radio_A:RTL8188EE_RADIOA_1TARRAY %d\n", a_len); | ||
970 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); | ||
971 | switch (rfpath) { | ||
972 | case RF90_PATH_A: | ||
973 | for (i = 0; i < a_len; i = i + 2) { | ||
974 | v1 = a_table[i]; | ||
975 | v2 = a_table[i + 1]; | ||
976 | if (v1 < 0xcdcdcdcd) { | ||
977 | rtl88_config_s(hw, v1, v2); | ||
978 | } else {/*This line is the start line of branch.*/ | ||
979 | if (!check_cond(hw, a_table[i])) { | ||
980 | /* Discard the following (offset, data) | ||
981 | * pairs | ||
982 | */ | ||
983 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
984 | while (v2 != 0xDEAD && v2 != 0xCDEF && | ||
985 | v2 != 0xCDCD && i < a_len - 2) | ||
986 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
987 | i -= 2; /* prevent from for-loop += 2*/ | ||
988 | } else { | ||
989 | /* Configure matched pairs and skip to | ||
990 | * end of if-else. | ||
991 | */ | ||
992 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
993 | while (v2 != 0xDEAD && v2 != 0xCDEF && | ||
994 | v2 != 0xCDCD && i < a_len - 2) { | ||
995 | rtl88_config_s(hw, v1, v2); | ||
996 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
997 | } | ||
998 | |||
999 | while (v2 != 0xDEAD && i < a_len - 2) | ||
1000 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
1001 | } | ||
1002 | } | ||
1003 | } | ||
1004 | |||
1005 | if (rtlhal->oem_id == RT_CID_819x_HP) | ||
1006 | rtl88_config_s(hw, 0x52, 0x7E4BD); | ||
1007 | |||
1008 | break; | ||
1009 | |||
1010 | case RF90_PATH_B: | ||
1011 | case RF90_PATH_C: | ||
1012 | case RF90_PATH_D: | ||
1013 | default: | ||
1014 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1015 | "switch case not processed\n"); | ||
1016 | break; | ||
1017 | } | ||
1018 | return true; | ||
1019 | } | ||
1020 | |||
1021 | void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) | ||
1022 | { | ||
1023 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1024 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1025 | |||
1026 | rtlphy->default_initialgain[0] = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, | ||
1027 | MASKBYTE0); | ||
1028 | rtlphy->default_initialgain[1] = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, | ||
1029 | MASKBYTE0); | ||
1030 | rtlphy->default_initialgain[2] = rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, | ||
1031 | MASKBYTE0); | ||
1032 | rtlphy->default_initialgain[3] = rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, | ||
1033 | MASKBYTE0); | ||
1034 | |||
1035 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1036 | "Default initial gain (c50 = 0x%x, c58 = 0x%x, c60 = 0x%x, c68 = 0x%x\n", | ||
1037 | rtlphy->default_initialgain[0], | ||
1038 | rtlphy->default_initialgain[1], | ||
1039 | rtlphy->default_initialgain[2], | ||
1040 | rtlphy->default_initialgain[3]); | ||
1041 | |||
1042 | rtlphy->framesync = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, | ||
1043 | MASKBYTE0); | ||
1044 | rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, | ||
1045 | MASKDWORD); | ||
1046 | |||
1047 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1048 | "Default framesync (0x%x) = 0x%x\n", | ||
1049 | ROFDM0_RXDETECTOR3, rtlphy->framesync); | ||
1050 | } | ||
1051 | |||
1052 | void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) | ||
1053 | { | ||
1054 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1055 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1056 | u8 level; | ||
1057 | long dbm; | ||
1058 | |||
1059 | level = rtlphy->cur_cck_txpwridx; | ||
1060 | dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_B, level); | ||
1061 | level = rtlphy->cur_ofdm24g_txpwridx; | ||
1062 | if (rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_G, level) > dbm) | ||
1063 | dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_G, level); | ||
1064 | level = rtlphy->cur_ofdm24g_txpwridx; | ||
1065 | if (rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_N_24G, level) > dbm) | ||
1066 | dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_N_24G, level); | ||
1067 | *powerlevel = dbm; | ||
1068 | } | ||
1069 | |||
1070 | static void _rtl88e_get_txpower_index(struct ieee80211_hw *hw, u8 channel, | ||
1071 | u8 *cckpower, u8 *ofdm, u8 *bw20_pwr, | ||
1072 | u8 *bw40_pwr) | ||
1073 | { | ||
1074 | struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw)); | ||
1075 | u8 i = (channel - 1); | ||
1076 | u8 rf_path = 0; | ||
1077 | int jj = RF90_PATH_A; | ||
1078 | int kk = RF90_PATH_B; | ||
1079 | |||
1080 | for (rf_path = 0; rf_path < 2; rf_path++) { | ||
1081 | if (rf_path == jj) { | ||
1082 | cckpower[jj] = fuse->txpwrlevel_cck[jj][i]; | ||
1083 | if (fuse->txpwr_ht20diff[jj][i] > 0x0f) /*-8~7 */ | ||
1084 | bw20_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i] - | ||
1085 | (~(fuse->txpwr_ht20diff[jj][i]) + 1); | ||
1086 | else | ||
1087 | bw20_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i] + | ||
1088 | fuse->txpwr_ht20diff[jj][i]; | ||
1089 | if (fuse->txpwr_legacyhtdiff[jj][i] > 0xf) | ||
1090 | ofdm[jj] = fuse->txpwrlevel_ht40_1s[jj][i] - | ||
1091 | (~(fuse->txpwr_legacyhtdiff[jj][i])+1); | ||
1092 | else | ||
1093 | ofdm[jj] = fuse->txpwrlevel_ht40_1s[jj][i] + | ||
1094 | fuse->txpwr_legacyhtdiff[jj][i]; | ||
1095 | bw40_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i]; | ||
1096 | |||
1097 | } else if (rf_path == kk) { | ||
1098 | cckpower[kk] = fuse->txpwrlevel_cck[kk][i]; | ||
1099 | bw20_pwr[kk] = fuse->txpwrlevel_ht40_1s[kk][i] + | ||
1100 | fuse->txpwr_ht20diff[kk][i]; | ||
1101 | ofdm[kk] = fuse->txpwrlevel_ht40_1s[kk][i] + | ||
1102 | fuse->txpwr_legacyhtdiff[kk][i]; | ||
1103 | bw40_pwr[kk] = fuse->txpwrlevel_ht40_1s[kk][i]; | ||
1104 | } | ||
1105 | } | ||
1106 | } | ||
1107 | |||
1108 | static void _rtl88e_ccxpower_index_check(struct ieee80211_hw *hw, | ||
1109 | u8 channel, u8 *cckpower, | ||
1110 | u8 *ofdm, u8 *bw20_pwr, | ||
1111 | u8 *bw40_pwr) | ||
1112 | { | ||
1113 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1114 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1115 | |||
1116 | rtlphy->cur_cck_txpwridx = cckpower[0]; | ||
1117 | rtlphy->cur_ofdm24g_txpwridx = ofdm[0]; | ||
1118 | rtlphy->cur_bw20_txpwridx = bw20_pwr[0]; | ||
1119 | rtlphy->cur_bw40_txpwridx = bw40_pwr[0]; | ||
1120 | } | ||
1121 | |||
1122 | void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) | ||
1123 | { | ||
1124 | struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw)); | ||
1125 | u8 cckpower[MAX_TX_COUNT] = {0}, ofdm[MAX_TX_COUNT] = {0}; | ||
1126 | u8 bw20_pwr[MAX_TX_COUNT] = {0}, bw40_pwr[MAX_TX_COUNT] = {0}; | ||
1127 | |||
1128 | if (fuse->txpwr_fromeprom == false) | ||
1129 | return; | ||
1130 | _rtl88e_get_txpower_index(hw, channel, &cckpower[0], &ofdm[0], | ||
1131 | &bw20_pwr[0], &bw40_pwr[0]); | ||
1132 | _rtl88e_ccxpower_index_check(hw, channel, &cckpower[0], &ofdm[0], | ||
1133 | &bw20_pwr[0], &bw40_pwr[0]); | ||
1134 | rtl88e_phy_rf6052_set_cck_txpower(hw, &cckpower[0]); | ||
1135 | rtl88e_phy_rf6052_set_ofdm_txpower(hw, &ofdm[0], &bw20_pwr[0], | ||
1136 | &bw40_pwr[0], channel); | ||
1137 | } | ||
1138 | |||
1139 | void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) | ||
1140 | { | ||
1141 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1142 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1143 | enum io_type iotype; | ||
1144 | |||
1145 | if (!is_hal_stop(rtlhal)) { | ||
1146 | switch (operation) { | ||
1147 | case SCAN_OPT_BACKUP: | ||
1148 | iotype = IO_CMD_PAUSE_DM_BY_SCAN; | ||
1149 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1150 | HW_VAR_IO_CMD, | ||
1151 | (u8 *)&iotype); | ||
1152 | break; | ||
1153 | case SCAN_OPT_RESTORE: | ||
1154 | iotype = IO_CMD_RESUME_DM_BY_SCAN; | ||
1155 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1156 | HW_VAR_IO_CMD, | ||
1157 | (u8 *)&iotype); | ||
1158 | break; | ||
1159 | default: | ||
1160 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1161 | "Unknown Scan Backup operation.\n"); | ||
1162 | break; | ||
1163 | } | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw) | ||
1168 | { | ||
1169 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1170 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1171 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1172 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1173 | u8 reg_bw_opmode; | ||
1174 | u8 reg_prsr_rsc; | ||
1175 | |||
1176 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, | ||
1177 | "Switch to %s bandwidth\n", | ||
1178 | rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? | ||
1179 | "20MHz" : "40MHz"); | ||
1180 | |||
1181 | if (is_hal_stop(rtlhal)) { | ||
1182 | rtlphy->set_bwmode_inprogress = false; | ||
1183 | return; | ||
1184 | } | ||
1185 | |||
1186 | reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); | ||
1187 | reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); | ||
1188 | |||
1189 | switch (rtlphy->current_chan_bw) { | ||
1190 | case HT_CHANNEL_WIDTH_20: | ||
1191 | reg_bw_opmode |= BW_OPMODE_20MHZ; | ||
1192 | rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); | ||
1193 | break; | ||
1194 | case HT_CHANNEL_WIDTH_20_40: | ||
1195 | reg_bw_opmode &= ~BW_OPMODE_20MHZ; | ||
1196 | rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); | ||
1197 | reg_prsr_rsc = | ||
1198 | (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); | ||
1199 | rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); | ||
1200 | break; | ||
1201 | default: | ||
1202 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1203 | "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); | ||
1204 | break; | ||
1205 | } | ||
1206 | |||
1207 | switch (rtlphy->current_chan_bw) { | ||
1208 | case HT_CHANNEL_WIDTH_20: | ||
1209 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); | ||
1210 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); | ||
1211 | /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);*/ | ||
1212 | break; | ||
1213 | case HT_CHANNEL_WIDTH_20_40: | ||
1214 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); | ||
1215 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); | ||
1216 | |||
1217 | rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, | ||
1218 | (mac->cur_40_prime_sc >> 1)); | ||
1219 | rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); | ||
1220 | /*rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);*/ | ||
1221 | |||
1222 | rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), | ||
1223 | (mac->cur_40_prime_sc == | ||
1224 | HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); | ||
1225 | break; | ||
1226 | default: | ||
1227 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1228 | "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); | ||
1229 | break; | ||
1230 | } | ||
1231 | rtl88e_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); | ||
1232 | rtlphy->set_bwmode_inprogress = false; | ||
1233 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); | ||
1234 | } | ||
1235 | |||
1236 | void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw, | ||
1237 | enum nl80211_channel_type ch_type) | ||
1238 | { | ||
1239 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1240 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1241 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1242 | u8 tmp_bw = rtlphy->current_chan_bw; | ||
1243 | |||
1244 | if (rtlphy->set_bwmode_inprogress) | ||
1245 | return; | ||
1246 | rtlphy->set_bwmode_inprogress = true; | ||
1247 | if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | ||
1248 | rtl88e_phy_set_bw_mode_callback(hw); | ||
1249 | } else { | ||
1250 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1251 | "FALSE driver sleep or unload\n"); | ||
1252 | rtlphy->set_bwmode_inprogress = false; | ||
1253 | rtlphy->current_chan_bw = tmp_bw; | ||
1254 | } | ||
1255 | } | ||
1256 | |||
1257 | void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw) | ||
1258 | { | ||
1259 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1260 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1261 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1262 | u32 delay; | ||
1263 | |||
1264 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, | ||
1265 | "switch to channel%d\n", rtlphy->current_channel); | ||
1266 | if (is_hal_stop(rtlhal)) | ||
1267 | return; | ||
1268 | do { | ||
1269 | if (!rtlphy->sw_chnl_inprogress) | ||
1270 | break; | ||
1271 | if (!chnl_step_by_step(hw, rtlphy->current_channel, | ||
1272 | &rtlphy->sw_chnl_stage, | ||
1273 | &rtlphy->sw_chnl_step, &delay)) { | ||
1274 | if (delay > 0) | ||
1275 | mdelay(delay); | ||
1276 | else | ||
1277 | continue; | ||
1278 | } else { | ||
1279 | rtlphy->sw_chnl_inprogress = false; | ||
1280 | } | ||
1281 | break; | ||
1282 | } while (true); | ||
1283 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); | ||
1284 | } | ||
1285 | |||
1286 | u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw) | ||
1287 | { | ||
1288 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1289 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1290 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1291 | |||
1292 | if (rtlphy->sw_chnl_inprogress) | ||
1293 | return 0; | ||
1294 | if (rtlphy->set_bwmode_inprogress) | ||
1295 | return 0; | ||
1296 | RT_ASSERT((rtlphy->current_channel <= 14), | ||
1297 | "WIRELESS_MODE_G but channel>14"); | ||
1298 | rtlphy->sw_chnl_inprogress = true; | ||
1299 | rtlphy->sw_chnl_stage = 0; | ||
1300 | rtlphy->sw_chnl_step = 0; | ||
1301 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | ||
1302 | rtl88e_phy_sw_chnl_callback(hw); | ||
1303 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | ||
1304 | "sw_chnl_inprogress false schdule workitem current channel %d\n", | ||
1305 | rtlphy->current_channel); | ||
1306 | rtlphy->sw_chnl_inprogress = false; | ||
1307 | } else { | ||
1308 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | ||
1309 | "sw_chnl_inprogress false driver sleep or unload\n"); | ||
1310 | rtlphy->sw_chnl_inprogress = false; | ||
1311 | } | ||
1312 | return 1; | ||
1313 | } | ||
1314 | |||
1315 | static u8 _rtl88e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) | ||
1316 | { | ||
1317 | u32 reg_eac, reg_e94, reg_e9c; | ||
1318 | u8 result = 0x00; | ||
1319 | |||
1320 | rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1c); | ||
1321 | rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x30008c1c); | ||
1322 | rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x8214032a); | ||
1323 | rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x28160000); | ||
1324 | |||
1325 | rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); | ||
1326 | rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); | ||
1327 | rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); | ||
1328 | |||
1329 | mdelay(IQK_DELAY_TIME); | ||
1330 | |||
1331 | reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); | ||
1332 | reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); | ||
1333 | reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); | ||
1334 | |||
1335 | if (!(reg_eac & BIT(28)) && | ||
1336 | (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && | ||
1337 | (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) | ||
1338 | result |= 0x01; | ||
1339 | return result; | ||
1340 | } | ||
1341 | |||
1342 | static u8 _rtl88e_phy_path_b_iqk(struct ieee80211_hw *hw) | ||
1343 | { | ||
1344 | u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; | ||
1345 | u8 result = 0x00; | ||
1346 | |||
1347 | rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); | ||
1348 | rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); | ||
1349 | mdelay(IQK_DELAY_TIME); | ||
1350 | reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); | ||
1351 | reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); | ||
1352 | reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); | ||
1353 | reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); | ||
1354 | reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); | ||
1355 | |||
1356 | if (!(reg_eac & BIT(31)) && | ||
1357 | (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && | ||
1358 | (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) | ||
1359 | result |= 0x01; | ||
1360 | else | ||
1361 | return result; | ||
1362 | if (!(reg_eac & BIT(30)) && | ||
1363 | (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && | ||
1364 | (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) | ||
1365 | result |= 0x02; | ||
1366 | return result; | ||
1367 | } | ||
1368 | |||
1369 | static u8 _rtl88e_phy_path_a_rx_iqk(struct ieee80211_hw *hw, bool config_pathb) | ||
1370 | { | ||
1371 | u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u32temp; | ||
1372 | u8 result = 0x00; | ||
1373 | int jj = RF90_PATH_A; | ||
1374 | |||
1375 | /*Get TXIMR Setting*/ | ||
1376 | /*Modify RX IQK mode table*/ | ||
1377 | rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); | ||
1378 | rtl_set_rfreg(hw, jj, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); | ||
1379 | rtl_set_rfreg(hw, jj, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); | ||
1380 | rtl_set_rfreg(hw, jj, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); | ||
1381 | rtl_set_rfreg(hw, jj, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf117b); | ||
1382 | rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); | ||
1383 | |||
1384 | /*IQK Setting*/ | ||
1385 | rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); | ||
1386 | rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x81004800); | ||
1387 | |||
1388 | /*path a IQK setting*/ | ||
1389 | rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x10008c1c); | ||
1390 | rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x30008c1c); | ||
1391 | rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160804); | ||
1392 | rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160000); | ||
1393 | |||
1394 | /*LO calibration Setting*/ | ||
1395 | rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); | ||
1396 | /*one shot, path A LOK & iqk*/ | ||
1397 | rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); | ||
1398 | rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); | ||
1399 | |||
1400 | mdelay(IQK_DELAY_TIME); | ||
1401 | |||
1402 | reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); | ||
1403 | reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); | ||
1404 | reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); | ||
1405 | |||
1406 | |||
1407 | if (!(reg_eac & BIT(28)) && | ||
1408 | (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && | ||
1409 | (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) | ||
1410 | result |= 0x01; | ||
1411 | else | ||
1412 | return result; | ||
1413 | |||
1414 | u32temp = 0x80007C00 | (reg_e94&0x3FF0000) | | ||
1415 | ((reg_e9c&0x3FF0000) >> 16); | ||
1416 | rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32temp); | ||
1417 | /*RX IQK*/ | ||
1418 | /*Modify RX IQK mode table*/ | ||
1419 | rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); | ||
1420 | rtl_set_rfreg(hw, jj, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); | ||
1421 | rtl_set_rfreg(hw, jj, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); | ||
1422 | rtl_set_rfreg(hw, jj, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); | ||
1423 | rtl_set_rfreg(hw, jj, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ffa); | ||
1424 | rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); | ||
1425 | |||
1426 | /*IQK Setting*/ | ||
1427 | rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); | ||
1428 | |||
1429 | /*path a IQK setting*/ | ||
1430 | rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x30008c1c); | ||
1431 | rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x10008c1c); | ||
1432 | rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160c05); | ||
1433 | rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160c05); | ||
1434 | |||
1435 | /*LO calibration Setting*/ | ||
1436 | rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); | ||
1437 | /*one shot, path A LOK & iqk*/ | ||
1438 | rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); | ||
1439 | rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); | ||
1440 | |||
1441 | mdelay(IQK_DELAY_TIME); | ||
1442 | |||
1443 | reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); | ||
1444 | reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); | ||
1445 | reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); | ||
1446 | reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD); | ||
1447 | |||
1448 | if (!(reg_eac & BIT(27)) && | ||
1449 | (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && | ||
1450 | (((reg_eac & 0x03FF0000) >> 16) != 0x36)) | ||
1451 | result |= 0x02; | ||
1452 | return result; | ||
1453 | } | ||
1454 | |||
1455 | static void fill_iqk(struct ieee80211_hw *hw, bool iqk_ok, long result[][8], | ||
1456 | u8 final, bool btxonly) | ||
1457 | { | ||
1458 | u32 oldval_0, x, tx0_a, reg; | ||
1459 | long y, tx0_c; | ||
1460 | |||
1461 | if (final == 0xFF) { | ||
1462 | return; | ||
1463 | } else if (iqk_ok) { | ||
1464 | oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBAL, | ||
1465 | MASKDWORD) >> 22) & 0x3FF; | ||
1466 | x = result[final][0]; | ||
1467 | if ((x & 0x00000200) != 0) | ||
1468 | x = x | 0xFFFFFC00; | ||
1469 | tx0_a = (x * oldval_0) >> 8; | ||
1470 | rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, 0x3FF, tx0_a); | ||
1471 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(31), | ||
1472 | ((x * oldval_0 >> 7) & 0x1)); | ||
1473 | y = result[final][1]; | ||
1474 | if ((y & 0x00000200) != 0) | ||
1475 | y |= 0xFFFFFC00; | ||
1476 | tx0_c = (y * oldval_0) >> 8; | ||
1477 | rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, | ||
1478 | ((tx0_c & 0x3C0) >> 6)); | ||
1479 | rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, 0x003F0000, | ||
1480 | (tx0_c & 0x3F)); | ||
1481 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(29), | ||
1482 | ((y * oldval_0 >> 7) & 0x1)); | ||
1483 | if (btxonly) | ||
1484 | return; | ||
1485 | reg = result[final][2]; | ||
1486 | rtl_set_bbreg(hw, ROFDM0_XARXIQIMBAL, 0x3FF, reg); | ||
1487 | reg = result[final][3] & 0x3F; | ||
1488 | rtl_set_bbreg(hw, ROFDM0_XARXIQIMBAL, 0xFC00, reg); | ||
1489 | reg = (result[final][3] >> 6) & 0xF; | ||
1490 | rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); | ||
1491 | } | ||
1492 | } | ||
1493 | |||
1494 | static void save_adda_reg(struct ieee80211_hw *hw, | ||
1495 | const u32 *addareg, u32 *backup, | ||
1496 | u32 registernum) | ||
1497 | { | ||
1498 | u32 i; | ||
1499 | |||
1500 | for (i = 0; i < registernum; i++) | ||
1501 | backup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); | ||
1502 | } | ||
1503 | |||
1504 | static void save_mac_reg(struct ieee80211_hw *hw, const u32 *macreg, | ||
1505 | u32 *macbackup) | ||
1506 | { | ||
1507 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1508 | u32 i; | ||
1509 | |||
1510 | for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) | ||
1511 | macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); | ||
1512 | macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); | ||
1513 | } | ||
1514 | |||
1515 | static void reload_adda(struct ieee80211_hw *hw, const u32 *addareg, | ||
1516 | u32 *backup, u32 reg_num) | ||
1517 | { | ||
1518 | u32 i; | ||
1519 | |||
1520 | for (i = 0; i < reg_num; i++) | ||
1521 | rtl_set_bbreg(hw, addareg[i], MASKDWORD, backup[i]); | ||
1522 | } | ||
1523 | |||
1524 | static void reload_mac(struct ieee80211_hw *hw, const u32 *macreg, | ||
1525 | u32 *macbackup) | ||
1526 | { | ||
1527 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1528 | u32 i; | ||
1529 | |||
1530 | for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) | ||
1531 | rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]); | ||
1532 | rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); | ||
1533 | } | ||
1534 | |||
1535 | static void _rtl88e_phy_path_adda_on(struct ieee80211_hw *hw, | ||
1536 | const u32 *addareg, bool is_patha_on, | ||
1537 | bool is2t) | ||
1538 | { | ||
1539 | u32 pathon; | ||
1540 | u32 i; | ||
1541 | |||
1542 | pathon = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; | ||
1543 | if (false == is2t) { | ||
1544 | pathon = 0x0bdb25a0; | ||
1545 | rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0); | ||
1546 | } else { | ||
1547 | rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); | ||
1548 | } | ||
1549 | |||
1550 | for (i = 1; i < IQK_ADDA_REG_NUM; i++) | ||
1551 | rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon); | ||
1552 | } | ||
1553 | |||
1554 | static void _rtl88e_phy_mac_setting_calibration(struct ieee80211_hw *hw, | ||
1555 | const u32 *macreg, | ||
1556 | u32 *macbackup) | ||
1557 | { | ||
1558 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1559 | u32 i = 0; | ||
1560 | |||
1561 | rtl_write_byte(rtlpriv, macreg[i], 0x3F); | ||
1562 | |||
1563 | for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) | ||
1564 | rtl_write_byte(rtlpriv, macreg[i], | ||
1565 | (u8) (macbackup[i] & (~BIT(3)))); | ||
1566 | rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5)))); | ||
1567 | } | ||
1568 | |||
1569 | static void _rtl88e_phy_path_a_standby(struct ieee80211_hw *hw) | ||
1570 | { | ||
1571 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); | ||
1572 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); | ||
1573 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); | ||
1574 | } | ||
1575 | |||
1576 | static void _rtl88e_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode) | ||
1577 | { | ||
1578 | u32 mode; | ||
1579 | |||
1580 | mode = pi_mode ? 0x01000100 : 0x01000000; | ||
1581 | rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); | ||
1582 | rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); | ||
1583 | } | ||
1584 | |||
1585 | static bool sim_comp(struct ieee80211_hw *hw, long result[][8], u8 c1, u8 c2) | ||
1586 | { | ||
1587 | u32 i, j, diff, bitmap, bound; | ||
1588 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1589 | |||
1590 | u8 final[2] = {0xFF, 0xFF}; | ||
1591 | bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version); | ||
1592 | |||
1593 | if (is2t) | ||
1594 | bound = 8; | ||
1595 | else | ||
1596 | bound = 4; | ||
1597 | |||
1598 | bitmap = 0; | ||
1599 | |||
1600 | for (i = 0; i < bound; i++) { | ||
1601 | diff = (result[c1][i] > result[c2][i]) ? | ||
1602 | (result[c1][i] - result[c2][i]) : | ||
1603 | (result[c2][i] - result[c1][i]); | ||
1604 | |||
1605 | if (diff > MAX_TOLERANCE) { | ||
1606 | if ((i == 2 || i == 6) && !bitmap) { | ||
1607 | if (result[c1][i] + result[c1][i + 1] == 0) | ||
1608 | final[(i / 4)] = c2; | ||
1609 | else if (result[c2][i] + result[c2][i + 1] == 0) | ||
1610 | final[(i / 4)] = c1; | ||
1611 | else | ||
1612 | bitmap = bitmap | (1 << i); | ||
1613 | } else { | ||
1614 | bitmap = bitmap | (1 << i); | ||
1615 | } | ||
1616 | } | ||
1617 | } | ||
1618 | |||
1619 | if (bitmap == 0) { | ||
1620 | for (i = 0; i < (bound / 4); i++) { | ||
1621 | if (final[i] != 0xFF) { | ||
1622 | for (j = i * 4; j < (i + 1) * 4 - 2; j++) | ||
1623 | result[3][j] = result[final[i]][j]; | ||
1624 | bresult = false; | ||
1625 | } | ||
1626 | } | ||
1627 | return bresult; | ||
1628 | } else if (!(bitmap & 0x0F)) { | ||
1629 | for (i = 0; i < 4; i++) | ||
1630 | result[3][i] = result[c1][i]; | ||
1631 | return false; | ||
1632 | } else if (!(bitmap & 0xF0) && is2t) { | ||
1633 | for (i = 4; i < 8; i++) | ||
1634 | result[3][i] = result[c1][i]; | ||
1635 | return false; | ||
1636 | } else { | ||
1637 | return false; | ||
1638 | } | ||
1639 | } | ||
1640 | |||
1641 | static void _rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, | ||
1642 | long result[][8], u8 t, bool is2t) | ||
1643 | { | ||
1644 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1645 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1646 | u32 i; | ||
1647 | u8 patha_ok, pathb_ok; | ||
1648 | const u32 adda_reg[IQK_ADDA_REG_NUM] = { | ||
1649 | 0x85c, 0xe6c, 0xe70, 0xe74, | ||
1650 | 0xe78, 0xe7c, 0xe80, 0xe84, | ||
1651 | 0xe88, 0xe8c, 0xed0, 0xed4, | ||
1652 | 0xed8, 0xedc, 0xee0, 0xeec | ||
1653 | }; | ||
1654 | const u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { | ||
1655 | 0x522, 0x550, 0x551, 0x040 | ||
1656 | }; | ||
1657 | const u32 iqk_bb_reg[IQK_BB_REG_NUM] = { | ||
1658 | ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, RFPGA0_XCD_RFINTERFACESW, | ||
1659 | 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0x800 | ||
1660 | }; | ||
1661 | const u32 retrycount = 2; | ||
1662 | |||
1663 | if (t == 0) { | ||
1664 | save_adda_reg(hw, adda_reg, rtlphy->adda_backup, 16); | ||
1665 | save_mac_reg(hw, iqk_mac_reg, rtlphy->iqk_mac_backup); | ||
1666 | save_adda_reg(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, | ||
1667 | IQK_BB_REG_NUM); | ||
1668 | } | ||
1669 | _rtl88e_phy_path_adda_on(hw, adda_reg, true, is2t); | ||
1670 | if (t == 0) { | ||
1671 | rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, | ||
1672 | RFPGA0_XA_HSSIPARAMETER1, BIT(8)); | ||
1673 | } | ||
1674 | |||
1675 | if (!rtlphy->rfpi_enable) | ||
1676 | _rtl88e_phy_pi_mode_switch(hw, true); | ||
1677 | /*BB Setting*/ | ||
1678 | rtl_set_bbreg(hw, 0x800, BIT(24), 0x00); | ||
1679 | rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); | ||
1680 | rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); | ||
1681 | rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); | ||
1682 | |||
1683 | rtl_set_bbreg(hw, 0x870, BIT(10), 0x01); | ||
1684 | rtl_set_bbreg(hw, 0x870, BIT(26), 0x01); | ||
1685 | rtl_set_bbreg(hw, 0x860, BIT(10), 0x00); | ||
1686 | rtl_set_bbreg(hw, 0x864, BIT(10), 0x00); | ||
1687 | |||
1688 | if (is2t) { | ||
1689 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); | ||
1690 | rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); | ||
1691 | } | ||
1692 | _rtl88e_phy_mac_setting_calibration(hw, iqk_mac_reg, | ||
1693 | rtlphy->iqk_mac_backup); | ||
1694 | rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000); | ||
1695 | if (is2t) | ||
1696 | rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x0f600000); | ||
1697 | |||
1698 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); | ||
1699 | rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); | ||
1700 | rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x81004800); | ||
1701 | for (i = 0; i < retrycount; i++) { | ||
1702 | patha_ok = _rtl88e_phy_path_a_iqk(hw, is2t); | ||
1703 | if (patha_ok == 0x01) { | ||
1704 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1705 | "Path A Tx IQK Success!!\n"); | ||
1706 | result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & | ||
1707 | 0x3FF0000) >> 16; | ||
1708 | result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & | ||
1709 | 0x3FF0000) >> 16; | ||
1710 | break; | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1714 | for (i = 0; i < retrycount; i++) { | ||
1715 | patha_ok = _rtl88e_phy_path_a_rx_iqk(hw, is2t); | ||
1716 | if (patha_ok == 0x03) { | ||
1717 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1718 | "Path A Rx IQK Success!!\n"); | ||
1719 | result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & | ||
1720 | 0x3FF0000) >> 16; | ||
1721 | result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & | ||
1722 | 0x3FF0000) >> 16; | ||
1723 | break; | ||
1724 | } else { | ||
1725 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1726 | "Path a RX iqk fail!!!\n"); | ||
1727 | } | ||
1728 | } | ||
1729 | |||
1730 | if (0 == patha_ok) { | ||
1731 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1732 | "Path A IQK Success!!\n"); | ||
1733 | } | ||
1734 | if (is2t) { | ||
1735 | _rtl88e_phy_path_a_standby(hw); | ||
1736 | _rtl88e_phy_path_adda_on(hw, adda_reg, false, is2t); | ||
1737 | for (i = 0; i < retrycount; i++) { | ||
1738 | pathb_ok = _rtl88e_phy_path_b_iqk(hw); | ||
1739 | if (pathb_ok == 0x03) { | ||
1740 | result[t][4] = (rtl_get_bbreg(hw, | ||
1741 | 0xeb4, MASKDWORD) & | ||
1742 | 0x3FF0000) >> 16; | ||
1743 | result[t][5] = | ||
1744 | (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & | ||
1745 | 0x3FF0000) >> 16; | ||
1746 | result[t][6] = | ||
1747 | (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & | ||
1748 | 0x3FF0000) >> 16; | ||
1749 | result[t][7] = | ||
1750 | (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & | ||
1751 | 0x3FF0000) >> 16; | ||
1752 | break; | ||
1753 | } else if (i == (retrycount - 1) && pathb_ok == 0x01) { | ||
1754 | result[t][4] = (rtl_get_bbreg(hw, | ||
1755 | 0xeb4, MASKDWORD) & | ||
1756 | 0x3FF0000) >> 16; | ||
1757 | } | ||
1758 | result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & | ||
1759 | 0x3FF0000) >> 16; | ||
1760 | } | ||
1761 | } | ||
1762 | |||
1763 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); | ||
1764 | |||
1765 | if (t != 0) { | ||
1766 | if (!rtlphy->rfpi_enable) | ||
1767 | _rtl88e_phy_pi_mode_switch(hw, false); | ||
1768 | reload_adda(hw, adda_reg, rtlphy->adda_backup, 16); | ||
1769 | reload_mac(hw, iqk_mac_reg, rtlphy->iqk_mac_backup); | ||
1770 | reload_adda(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, | ||
1771 | IQK_BB_REG_NUM); | ||
1772 | |||
1773 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); | ||
1774 | if (is2t) | ||
1775 | rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); | ||
1776 | rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); | ||
1777 | rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); | ||
1778 | } | ||
1779 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "88ee IQK Finish!!\n"); | ||
1780 | } | ||
1781 | |||
1782 | static void _rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) | ||
1783 | { | ||
1784 | u8 tmpreg; | ||
1785 | u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; | ||
1786 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1787 | int jj = RF90_PATH_A; | ||
1788 | int kk = RF90_PATH_B; | ||
1789 | |||
1790 | tmpreg = rtl_read_byte(rtlpriv, 0xd03); | ||
1791 | |||
1792 | if ((tmpreg & 0x70) != 0) | ||
1793 | rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); | ||
1794 | else | ||
1795 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | ||
1796 | |||
1797 | if ((tmpreg & 0x70) != 0) { | ||
1798 | rf_a_mode = rtl_get_rfreg(hw, jj, 0x00, MASK12BITS); | ||
1799 | |||
1800 | if (is2t) | ||
1801 | rf_b_mode = rtl_get_rfreg(hw, kk, 0x00, | ||
1802 | MASK12BITS); | ||
1803 | |||
1804 | rtl_set_rfreg(hw, jj, 0x00, MASK12BITS, | ||
1805 | (rf_a_mode & 0x8FFFF) | 0x10000); | ||
1806 | |||
1807 | if (is2t) | ||
1808 | rtl_set_rfreg(hw, kk, 0x00, MASK12BITS, | ||
1809 | (rf_b_mode & 0x8FFFF) | 0x10000); | ||
1810 | } | ||
1811 | lc_cal = rtl_get_rfreg(hw, jj, 0x18, MASK12BITS); | ||
1812 | |||
1813 | rtl_set_rfreg(hw, jj, 0x18, MASK12BITS, lc_cal | 0x08000); | ||
1814 | |||
1815 | mdelay(100); | ||
1816 | |||
1817 | if ((tmpreg & 0x70) != 0) { | ||
1818 | rtl_write_byte(rtlpriv, 0xd03, tmpreg); | ||
1819 | rtl_set_rfreg(hw, jj, 0x00, MASK12BITS, rf_a_mode); | ||
1820 | |||
1821 | if (is2t) | ||
1822 | rtl_set_rfreg(hw, kk, 0x00, MASK12BITS, | ||
1823 | rf_b_mode); | ||
1824 | } else { | ||
1825 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | ||
1826 | } | ||
1827 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); | ||
1828 | } | ||
1829 | |||
1830 | static void rfpath_switch(struct ieee80211_hw *hw, | ||
1831 | bool bmain, bool is2t) | ||
1832 | { | ||
1833 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1834 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1835 | struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw)); | ||
1836 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); | ||
1837 | |||
1838 | if (is_hal_stop(rtlhal)) { | ||
1839 | u8 u1btmp; | ||
1840 | u1btmp = rtl_read_byte(rtlpriv, REG_LEDCFG0); | ||
1841 | rtl_write_byte(rtlpriv, REG_LEDCFG0, u1btmp | BIT(7)); | ||
1842 | rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); | ||
1843 | } | ||
1844 | if (is2t) { | ||
1845 | if (bmain) | ||
1846 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, | ||
1847 | BIT(5) | BIT(6), 0x1); | ||
1848 | else | ||
1849 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, | ||
1850 | BIT(5) | BIT(6), 0x2); | ||
1851 | } else { | ||
1852 | rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(8) | BIT(9), 0); | ||
1853 | rtl_set_bbreg(hw, 0x914, MASKLWORD, 0x0201); | ||
1854 | |||
1855 | /* We use the RF definition of MAIN and AUX, left antenna and | ||
1856 | * right antenna repectively. | ||
1857 | * Default output at AUX. | ||
1858 | */ | ||
1859 | if (bmain) { | ||
1860 | rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(14) | | ||
1861 | BIT(13) | BIT(12), 0); | ||
1862 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(5) | | ||
1863 | BIT(4) | BIT(3), 0); | ||
1864 | if (fuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1865 | rtl_set_bbreg(hw, RCONFIG_RAM64X16, BIT(31), 0); | ||
1866 | } else { | ||
1867 | rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(14) | | ||
1868 | BIT(13) | BIT(12), 1); | ||
1869 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(5) | | ||
1870 | BIT(4) | BIT(3), 1); | ||
1871 | if (fuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1872 | rtl_set_bbreg(hw, RCONFIG_RAM64X16, BIT(31), 1); | ||
1873 | } | ||
1874 | } | ||
1875 | } | ||
1876 | |||
1877 | #undef IQK_ADDA_REG_NUM | ||
1878 | #undef IQK_DELAY_TIME | ||
1879 | |||
1880 | void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery) | ||
1881 | { | ||
1882 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1883 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1884 | long result[4][8]; | ||
1885 | u8 i, final; | ||
1886 | bool patha_ok; | ||
1887 | long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_tmp = 0; | ||
1888 | bool is12simular, is13simular, is23simular; | ||
1889 | u32 iqk_bb_reg[9] = { | ||
1890 | ROFDM0_XARXIQIMBAL, | ||
1891 | ROFDM0_XBRXIQIMBAL, | ||
1892 | ROFDM0_ECCATHRES, | ||
1893 | ROFDM0_AGCRSSITABLE, | ||
1894 | ROFDM0_XATXIQIMBAL, | ||
1895 | ROFDM0_XBTXIQIMBAL, | ||
1896 | ROFDM0_XCTXAFE, | ||
1897 | ROFDM0_XDTXAFE, | ||
1898 | ROFDM0_RXIQEXTANTA | ||
1899 | }; | ||
1900 | |||
1901 | if (recovery) { | ||
1902 | reload_adda(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 9); | ||
1903 | return; | ||
1904 | } | ||
1905 | |||
1906 | memset(result, 0, 32 * sizeof(long)); | ||
1907 | final = 0xff; | ||
1908 | patha_ok = false; | ||
1909 | is12simular = false; | ||
1910 | is23simular = false; | ||
1911 | is13simular = false; | ||
1912 | for (i = 0; i < 3; i++) { | ||
1913 | if (get_rf_type(rtlphy) == RF_2T2R) | ||
1914 | _rtl88e_phy_iq_calibrate(hw, result, i, true); | ||
1915 | else | ||
1916 | _rtl88e_phy_iq_calibrate(hw, result, i, false); | ||
1917 | if (i == 1) { | ||
1918 | is12simular = sim_comp(hw, result, 0, 1); | ||
1919 | if (is12simular) { | ||
1920 | final = 0; | ||
1921 | break; | ||
1922 | } | ||
1923 | } | ||
1924 | if (i == 2) { | ||
1925 | is13simular = sim_comp(hw, result, 0, 2); | ||
1926 | if (is13simular) { | ||
1927 | final = 0; | ||
1928 | break; | ||
1929 | } | ||
1930 | is23simular = sim_comp(hw, result, 1, 2); | ||
1931 | if (is23simular) { | ||
1932 | final = 1; | ||
1933 | } else { | ||
1934 | for (i = 0; i < 8; i++) | ||
1935 | reg_tmp += result[3][i]; | ||
1936 | |||
1937 | if (reg_tmp != 0) | ||
1938 | final = 3; | ||
1939 | else | ||
1940 | final = 0xFF; | ||
1941 | } | ||
1942 | } | ||
1943 | } | ||
1944 | for (i = 0; i < 4; i++) { | ||
1945 | reg_e94 = result[i][0]; | ||
1946 | reg_e9c = result[i][1]; | ||
1947 | reg_ea4 = result[i][2]; | ||
1948 | reg_eb4 = result[i][4]; | ||
1949 | reg_ebc = result[i][5]; | ||
1950 | } | ||
1951 | if (final != 0xff) { | ||
1952 | reg_e94 = result[final][0]; | ||
1953 | rtlphy->reg_e94 = reg_e94; | ||
1954 | reg_e9c = result[final][1]; | ||
1955 | rtlphy->reg_e9c = reg_e9c; | ||
1956 | reg_ea4 = result[final][2]; | ||
1957 | reg_eb4 = result[final][4]; | ||
1958 | rtlphy->reg_eb4 = reg_eb4; | ||
1959 | reg_ebc = result[final][5]; | ||
1960 | rtlphy->reg_ebc = reg_ebc; | ||
1961 | patha_ok = true; | ||
1962 | } else { | ||
1963 | rtlphy->reg_e94 = 0x100; | ||
1964 | rtlphy->reg_eb4 = 0x100; | ||
1965 | rtlphy->reg_ebc = 0x0; | ||
1966 | rtlphy->reg_e9c = 0x0; | ||
1967 | } | ||
1968 | if (reg_e94 != 0) /*&&(reg_ea4 != 0) */ | ||
1969 | fill_iqk(hw, patha_ok, result, final, (reg_ea4 == 0)); | ||
1970 | if (final != 0xFF) { | ||
1971 | for (i = 0; i < IQK_MATRIX_REG_NUM; i++) | ||
1972 | rtlphy->iqk_matrix[0].value[0][i] = result[final][i]; | ||
1973 | rtlphy->iqk_matrix[0].iqk_done = true; | ||
1974 | } | ||
1975 | save_adda_reg(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 9); | ||
1976 | } | ||
1977 | |||
1978 | void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw) | ||
1979 | { | ||
1980 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1981 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1982 | struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); | ||
1983 | bool start_conttx = false, singletone = false; | ||
1984 | u32 timeout = 2000, timecount = 0; | ||
1985 | |||
1986 | if (start_conttx || singletone) | ||
1987 | return; | ||
1988 | |||
1989 | while (rtlpriv->mac80211.act_scanning && timecount < timeout) { | ||
1990 | udelay(50); | ||
1991 | timecount += 50; | ||
1992 | } | ||
1993 | |||
1994 | rtlphy->lck_inprogress = true; | ||
1995 | RTPRINT(rtlpriv, FINIT, INIT_IQK, | ||
1996 | "LCK:Start!!! currentband %x delay %d ms\n", | ||
1997 | rtlhal->current_bandtype, timecount); | ||
1998 | |||
1999 | _rtl88e_phy_lc_calibrate(hw, false); | ||
2000 | |||
2001 | rtlphy->lck_inprogress = false; | ||
2002 | } | ||
2003 | |||
2004 | void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) | ||
2005 | { | ||
2006 | rfpath_switch(hw, bmain, false); | ||
2007 | } | ||
2008 | |||
2009 | bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) | ||
2010 | { | ||
2011 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2012 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
2013 | bool postprocessing = false; | ||
2014 | |||
2015 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
2016 | "-->IO Cmd(%#x), set_io_inprogress(%d)\n", | ||
2017 | iotype, rtlphy->set_io_inprogress); | ||
2018 | do { | ||
2019 | switch (iotype) { | ||
2020 | case IO_CMD_RESUME_DM_BY_SCAN: | ||
2021 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
2022 | "[IO CMD] Resume DM after scan.\n"); | ||
2023 | postprocessing = true; | ||
2024 | break; | ||
2025 | case IO_CMD_PAUSE_DM_BY_SCAN: | ||
2026 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
2027 | "[IO CMD] Pause DM before scan.\n"); | ||
2028 | postprocessing = true; | ||
2029 | break; | ||
2030 | default: | ||
2031 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
2032 | "switch case not processed\n"); | ||
2033 | break; | ||
2034 | } | ||
2035 | } while (false); | ||
2036 | if (postprocessing && !rtlphy->set_io_inprogress) { | ||
2037 | rtlphy->set_io_inprogress = true; | ||
2038 | rtlphy->current_io_type = iotype; | ||
2039 | } else { | ||
2040 | return false; | ||
2041 | } | ||
2042 | rtl88e_phy_set_io(hw); | ||
2043 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); | ||
2044 | return true; | ||
2045 | } | ||
2046 | |||
2047 | static void rtl88ee_phy_set_rf_on(struct ieee80211_hw *hw) | ||
2048 | { | ||
2049 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2050 | |||
2051 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); | ||
2052 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); | ||
2053 | /*rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);*/ | ||
2054 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | ||
2055 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); | ||
2056 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | ||
2057 | } | ||
2058 | |||
2059 | static void _rtl88ee_phy_set_rf_sleep(struct ieee80211_hw *hw) | ||
2060 | { | ||
2061 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2062 | int jj = RF90_PATH_A; | ||
2063 | |||
2064 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | ||
2065 | rtl_set_rfreg(hw, jj, 0x00, RFREG_OFFSET_MASK, 0x00); | ||
2066 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | ||
2067 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); | ||
2068 | } | ||
2069 | |||
2070 | static bool _rtl88ee_phy_set_rf_power_state(struct ieee80211_hw *hw, | ||
2071 | enum rf_pwrstate rfpwr_state) | ||
2072 | { | ||
2073 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2074 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
2075 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2076 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
2077 | struct rtl8192_tx_ring *ring = NULL; | ||
2078 | bool bresult = true; | ||
2079 | u8 i, queue_id; | ||
2080 | |||
2081 | switch (rfpwr_state) { | ||
2082 | case ERFON:{ | ||
2083 | if ((ppsc->rfpwr_state == ERFOFF) && | ||
2084 | RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { | ||
2085 | bool rtstatus; | ||
2086 | u32 init = 0; | ||
2087 | do { | ||
2088 | init++; | ||
2089 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2090 | "IPS Set eRf nic enable\n"); | ||
2091 | rtstatus = rtl_ps_enable_nic(hw); | ||
2092 | } while ((rtstatus != true) && (init < 10)); | ||
2093 | RT_CLEAR_PS_LEVEL(ppsc, | ||
2094 | RT_RF_OFF_LEVL_HALT_NIC); | ||
2095 | } else { | ||
2096 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2097 | "Set ERFON sleeped:%d ms\n", | ||
2098 | jiffies_to_msecs(jiffies - ppsc-> | ||
2099 | last_sleep_jiffies)); | ||
2100 | ppsc->last_awake_jiffies = jiffies; | ||
2101 | rtl88ee_phy_set_rf_on(hw); | ||
2102 | } | ||
2103 | if (mac->link_state == MAC80211_LINKED) | ||
2104 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK); | ||
2105 | else | ||
2106 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK); | ||
2107 | break; } | ||
2108 | case ERFOFF:{ | ||
2109 | for (queue_id = 0, i = 0; | ||
2110 | queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { | ||
2111 | ring = &pcipriv->dev.tx_ring[queue_id]; | ||
2112 | if (skb_queue_len(&ring->queue) == 0) { | ||
2113 | queue_id++; | ||
2114 | continue; | ||
2115 | } else { | ||
2116 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2117 | "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", | ||
2118 | (i + 1), queue_id, | ||
2119 | skb_queue_len(&ring->queue)); | ||
2120 | |||
2121 | udelay(10); | ||
2122 | i++; | ||
2123 | } | ||
2124 | if (i >= MAX_DOZE_WAITING_TIMES_9x) { | ||
2125 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2126 | "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", | ||
2127 | MAX_DOZE_WAITING_TIMES_9x, | ||
2128 | queue_id, | ||
2129 | skb_queue_len(&ring->queue)); | ||
2130 | break; | ||
2131 | } | ||
2132 | } | ||
2133 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { | ||
2134 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2135 | "IPS Set eRf nic disable\n"); | ||
2136 | rtl_ps_disable_nic(hw); | ||
2137 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
2138 | } else { | ||
2139 | if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { | ||
2140 | rtlpriv->cfg->ops->led_control(hw, | ||
2141 | LED_CTL_NO_LINK); | ||
2142 | } else { | ||
2143 | rtlpriv->cfg->ops->led_control(hw, | ||
2144 | LED_CTL_POWER_OFF); | ||
2145 | } | ||
2146 | } | ||
2147 | break; } | ||
2148 | case ERFSLEEP:{ | ||
2149 | if (ppsc->rfpwr_state == ERFOFF) | ||
2150 | break; | ||
2151 | for (queue_id = 0, i = 0; | ||
2152 | queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { | ||
2153 | ring = &pcipriv->dev.tx_ring[queue_id]; | ||
2154 | if (skb_queue_len(&ring->queue) == 0) { | ||
2155 | queue_id++; | ||
2156 | continue; | ||
2157 | } else { | ||
2158 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2159 | "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", | ||
2160 | (i + 1), queue_id, | ||
2161 | skb_queue_len(&ring->queue)); | ||
2162 | |||
2163 | udelay(10); | ||
2164 | i++; | ||
2165 | } | ||
2166 | if (i >= MAX_DOZE_WAITING_TIMES_9x) { | ||
2167 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2168 | "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", | ||
2169 | MAX_DOZE_WAITING_TIMES_9x, | ||
2170 | queue_id, | ||
2171 | skb_queue_len(&ring->queue)); | ||
2172 | break; | ||
2173 | } | ||
2174 | } | ||
2175 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2176 | "Set ERFSLEEP awaked:%d ms\n", | ||
2177 | jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies)); | ||
2178 | ppsc->last_sleep_jiffies = jiffies; | ||
2179 | _rtl88ee_phy_set_rf_sleep(hw); | ||
2180 | break; } | ||
2181 | default: | ||
2182 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
2183 | "switch case not processed\n"); | ||
2184 | bresult = false; | ||
2185 | break; | ||
2186 | } | ||
2187 | if (bresult) | ||
2188 | ppsc->rfpwr_state = rfpwr_state; | ||
2189 | return bresult; | ||
2190 | } | ||
2191 | |||
2192 | bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw, | ||
2193 | enum rf_pwrstate rfpwr_state) | ||
2194 | { | ||
2195 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
2196 | bool bresult; | ||
2197 | |||
2198 | if (rfpwr_state == ppsc->rfpwr_state) | ||
2199 | return false; | ||
2200 | bresult = _rtl88ee_phy_set_rf_power_state(hw, rfpwr_state); | ||
2201 | return bresult; | ||
2202 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h new file mode 100644 index 000000000000..f1acd6d27e44 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h | |||
@@ -0,0 +1,236 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92C_PHY_H__ | ||
31 | #define __RTL92C_PHY_H__ | ||
32 | |||
33 | /*It must always set to 4, otherwise read efuse table secquence will be wrong.*/ | ||
34 | #define MAX_TX_COUNT 4 | ||
35 | |||
36 | #define MAX_PRECMD_CNT 16 | ||
37 | #define MAX_RFDEPENDCMD_CNT 16 | ||
38 | #define MAX_POSTCMD_CNT 16 | ||
39 | |||
40 | #define MAX_DOZE_WAITING_TIMES_9x 64 | ||
41 | |||
42 | #define RT_CANNOT_IO(hw) false | ||
43 | #define HIGHPOWER_RADIOA_ARRAYLEN 22 | ||
44 | |||
45 | #define IQK_ADDA_REG_NUM 16 | ||
46 | #define IQK_BB_REG_NUM 9 | ||
47 | #define MAX_TOLERANCE 5 | ||
48 | #define IQK_DELAY_TIME 10 | ||
49 | #define IDX_MAP 15 | ||
50 | |||
51 | #define APK_BB_REG_NUM 5 | ||
52 | #define APK_AFE_REG_NUM 16 | ||
53 | #define APK_CURVE_REG_NUM 4 | ||
54 | #define PATH_NUM 2 | ||
55 | |||
56 | #define LOOP_LIMIT 5 | ||
57 | #define MAX_STALL_TIME 50 | ||
58 | #define ANTENNADIVERSITYVALUE 0x80 | ||
59 | #define MAX_TXPWR_IDX_NMODE_92S 63 | ||
60 | #define RESET_CNT_LIMIT 3 | ||
61 | |||
62 | #define IQK_ADDA_REG_NUM 16 | ||
63 | #define IQK_MAC_REG_NUM 4 | ||
64 | |||
65 | #define RF6052_MAX_PATH 2 | ||
66 | |||
67 | #define CT_OFFSET_MAC_ADDR 0X16 | ||
68 | |||
69 | #define CT_OFFSET_CCK_TX_PWR_IDX 0x5A | ||
70 | #define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 | ||
71 | #define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 | ||
72 | #define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 | ||
73 | #define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C | ||
74 | |||
75 | #define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F | ||
76 | #define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 | ||
77 | |||
78 | #define CT_OFFSET_CHANNEL_PLAH 0x75 | ||
79 | #define CT_OFFSET_THERMAL_METER 0x78 | ||
80 | #define CT_OFFSET_RF_OPTION 0x79 | ||
81 | #define CT_OFFSET_VERSION 0x7E | ||
82 | #define CT_OFFSET_CUSTOMER_ID 0x7F | ||
83 | |||
84 | #define RTL92C_MAX_PATH_NUM 2 | ||
85 | |||
86 | enum swchnlcmd_id { | ||
87 | CMDID_END, | ||
88 | CMDID_SET_TXPOWEROWER_LEVEL, | ||
89 | CMDID_BBREGWRITE10, | ||
90 | CMDID_WRITEPORT_ULONG, | ||
91 | CMDID_WRITEPORT_USHORT, | ||
92 | CMDID_WRITEPORT_UCHAR, | ||
93 | CMDID_RF_WRITEREG, | ||
94 | }; | ||
95 | |||
96 | struct swchnlcmd { | ||
97 | enum swchnlcmd_id cmdid; | ||
98 | u32 para1; | ||
99 | u32 para2; | ||
100 | u32 msdelay; | ||
101 | }; | ||
102 | |||
103 | enum hw90_block_e { | ||
104 | HW90_BLOCK_MAC = 0, | ||
105 | HW90_BLOCK_PHY0 = 1, | ||
106 | HW90_BLOCK_PHY1 = 2, | ||
107 | HW90_BLOCK_RF = 3, | ||
108 | HW90_BLOCK_MAXIMUM = 4, | ||
109 | }; | ||
110 | |||
111 | enum baseband_config_type { | ||
112 | BASEBAND_CONFIG_PHY_REG = 0, | ||
113 | BASEBAND_CONFIG_AGC_TAB = 1, | ||
114 | }; | ||
115 | |||
116 | enum ra_offset_area { | ||
117 | RA_OFFSET_LEGACY_OFDM1, | ||
118 | RA_OFFSET_LEGACY_OFDM2, | ||
119 | RA_OFFSET_HT_OFDM1, | ||
120 | RA_OFFSET_HT_OFDM2, | ||
121 | RA_OFFSET_HT_OFDM3, | ||
122 | RA_OFFSET_HT_OFDM4, | ||
123 | RA_OFFSET_HT_CCK, | ||
124 | }; | ||
125 | |||
126 | enum antenna_path { | ||
127 | ANTENNA_NONE, | ||
128 | ANTENNA_D, | ||
129 | ANTENNA_C, | ||
130 | ANTENNA_CD, | ||
131 | ANTENNA_B, | ||
132 | ANTENNA_BD, | ||
133 | ANTENNA_BC, | ||
134 | ANTENNA_BCD, | ||
135 | ANTENNA_A, | ||
136 | ANTENNA_AD, | ||
137 | ANTENNA_AC, | ||
138 | ANTENNA_ACD, | ||
139 | ANTENNA_AB, | ||
140 | ANTENNA_ABD, | ||
141 | ANTENNA_ABC, | ||
142 | ANTENNA_ABCD | ||
143 | }; | ||
144 | |||
145 | struct r_antenna_select_ofdm { | ||
146 | u32 r_tx_antenna:4; | ||
147 | u32 r_ant_l:4; | ||
148 | u32 r_ant_non_ht:4; | ||
149 | u32 r_ant_ht1:4; | ||
150 | u32 r_ant_ht2:4; | ||
151 | u32 r_ant_ht_s1:4; | ||
152 | u32 r_ant_non_ht_s1:4; | ||
153 | u32 ofdm_txsc:2; | ||
154 | u32 reserved:2; | ||
155 | }; | ||
156 | |||
157 | struct r_antenna_select_cck { | ||
158 | u8 r_cckrx_enable_2:2; | ||
159 | u8 r_cckrx_enable:2; | ||
160 | u8 r_ccktx_enable:4; | ||
161 | }; | ||
162 | |||
163 | |||
164 | struct efuse_contents { | ||
165 | u8 mac_addr[ETH_ALEN]; | ||
166 | u8 cck_tx_power_idx[6]; | ||
167 | u8 ht40_1s_tx_power_idx[6]; | ||
168 | u8 ht40_2s_tx_power_idx_diff[3]; | ||
169 | u8 ht20_tx_power_idx_diff[3]; | ||
170 | u8 ofdm_tx_power_idx_diff[3]; | ||
171 | u8 ht40_max_power_offset[3]; | ||
172 | u8 ht20_max_power_offset[3]; | ||
173 | u8 channel_plan; | ||
174 | u8 thermal_meter; | ||
175 | u8 rf_option[5]; | ||
176 | u8 version; | ||
177 | u8 oem_id; | ||
178 | u8 regulatory; | ||
179 | }; | ||
180 | |||
181 | struct tx_power_struct { | ||
182 | u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
183 | u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
184 | u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
185 | u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
186 | u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
187 | u8 legacy_ht_txpowerdiff; | ||
188 | u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
189 | u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
190 | u8 pwrgroup_cnt; | ||
191 | u32 mcs_original_offset[4][16]; | ||
192 | }; | ||
193 | |||
194 | enum _ANT_DIV_TYPE { | ||
195 | NO_ANTDIV = 0xFF, | ||
196 | CG_TRX_HW_ANTDIV = 0x01, | ||
197 | CGCS_RX_HW_ANTDIV = 0x02, | ||
198 | FIXED_HW_ANTDIV = 0x03, | ||
199 | CG_TRX_SMART_ANTDIV = 0x04, | ||
200 | CGCS_RX_SW_ANTDIV = 0x05, | ||
201 | }; | ||
202 | |||
203 | extern u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, | ||
204 | u32 regaddr, u32 bitmask); | ||
205 | extern void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, | ||
206 | u32 regaddr, u32 bitmask, u32 data); | ||
207 | extern u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, | ||
208 | enum radio_path rfpath, u32 regaddr, | ||
209 | u32 bitmask); | ||
210 | extern void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, | ||
211 | enum radio_path rfpath, u32 regaddr, | ||
212 | u32 bitmask, u32 data); | ||
213 | extern bool rtl88e_phy_mac_config(struct ieee80211_hw *hw); | ||
214 | extern bool rtl88e_phy_bb_config(struct ieee80211_hw *hw); | ||
215 | extern bool rtl88e_phy_rf_config(struct ieee80211_hw *hw); | ||
216 | extern void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); | ||
217 | extern void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, | ||
218 | long *powerlevel); | ||
219 | extern void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); | ||
220 | extern void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, | ||
221 | u8 operation); | ||
222 | extern void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw); | ||
223 | extern void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw, | ||
224 | enum nl80211_channel_type ch_type); | ||
225 | extern void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw); | ||
226 | extern u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw); | ||
227 | extern void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); | ||
228 | void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw); | ||
229 | void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); | ||
230 | bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | ||
231 | enum radio_path rfpath); | ||
232 | bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); | ||
233 | extern bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw, | ||
234 | enum rf_pwrstate rfpwr_state); | ||
235 | |||
236 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c new file mode 100644 index 000000000000..6dc4e3a954f6 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c | |||
@@ -0,0 +1,109 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "pwrseqcmd.h" | ||
31 | #include "pwrseq.h" | ||
32 | |||
33 | /* drivers should parse below arrays and do the corresponding actions */ | ||
34 | /*3 Power on Array*/ | ||
35 | struct wlan_pwr_cfg rtl8188e_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS + | ||
36 | RTL8188E_TRANS_END_STEPS] = { | ||
37 | RTL8188E_TRANS_CARDEMU_TO_ACT | ||
38 | RTL8188E_TRANS_END | ||
39 | }; | ||
40 | |||
41 | /*3Radio off GPIO Array */ | ||
42 | struct wlan_pwr_cfg rtl8188e_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS | ||
43 | + RTL8188E_TRANS_END_STEPS] = { | ||
44 | RTL8188E_TRANS_ACT_TO_CARDEMU | ||
45 | RTL8188E_TRANS_END | ||
46 | }; | ||
47 | |||
48 | /*3Card Disable Array*/ | ||
49 | struct wlan_pwr_cfg rtl8188e_card_disable_flow | ||
50 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
51 | RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + | ||
52 | RTL8188E_TRANS_END_STEPS] = { | ||
53 | RTL8188E_TRANS_ACT_TO_CARDEMU | ||
54 | RTL8188E_TRANS_CARDEMU_TO_CARDDIS | ||
55 | RTL8188E_TRANS_END | ||
56 | }; | ||
57 | |||
58 | /*3 Card Enable Array*/ | ||
59 | struct wlan_pwr_cfg rtl8188e_card_enable_flow | ||
60 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
61 | RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + | ||
62 | RTL8188E_TRANS_END_STEPS] = { | ||
63 | RTL8188E_TRANS_CARDDIS_TO_CARDEMU | ||
64 | RTL8188E_TRANS_CARDEMU_TO_ACT | ||
65 | RTL8188E_TRANS_END | ||
66 | }; | ||
67 | |||
68 | /*3Suspend Array*/ | ||
69 | struct wlan_pwr_cfg rtl8188e_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS | ||
70 | + RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS | ||
71 | + RTL8188E_TRANS_END_STEPS] = { | ||
72 | RTL8188E_TRANS_ACT_TO_CARDEMU | ||
73 | RTL8188E_TRANS_CARDEMU_TO_SUS | ||
74 | RTL8188E_TRANS_END | ||
75 | }; | ||
76 | |||
77 | /*3 Resume Array*/ | ||
78 | struct wlan_pwr_cfg rtl8188e_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS | ||
79 | + RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS | ||
80 | + RTL8188E_TRANS_END_STEPS] = { | ||
81 | RTL8188E_TRANS_SUS_TO_CARDEMU | ||
82 | RTL8188E_TRANS_CARDEMU_TO_ACT | ||
83 | RTL8188E_TRANS_END | ||
84 | }; | ||
85 | |||
86 | /*3HWPDN Array*/ | ||
87 | struct wlan_pwr_cfg rtl8188e_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS | ||
88 | + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS | ||
89 | + RTL8188E_TRANS_END_STEPS] = { | ||
90 | RTL8188E_TRANS_ACT_TO_CARDEMU | ||
91 | RTL8188E_TRANS_CARDEMU_TO_PDN | ||
92 | RTL8188E_TRANS_END | ||
93 | }; | ||
94 | |||
95 | /*3 Enter LPS */ | ||
96 | struct wlan_pwr_cfg rtl8188e_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS | ||
97 | + RTL8188E_TRANS_END_STEPS] = { | ||
98 | /*FW behavior*/ | ||
99 | RTL8188E_TRANS_ACT_TO_LPS | ||
100 | RTL8188E_TRANS_END | ||
101 | }; | ||
102 | |||
103 | /*3 Leave LPS */ | ||
104 | struct wlan_pwr_cfg rtl8188e_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS | ||
105 | + RTL8188E_TRANS_END_STEPS] = { | ||
106 | /*FW behavior*/ | ||
107 | RTL8188E_TRANS_LPS_TO_ACT | ||
108 | RTL8188E_TRANS_END | ||
109 | }; | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h new file mode 100644 index 000000000000..028ec6dd52b4 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h | |||
@@ -0,0 +1,327 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL8723E_PWRSEQ_H__ | ||
31 | #define __RTL8723E_PWRSEQ_H__ | ||
32 | |||
33 | #include "pwrseqcmd.h" | ||
34 | /* | ||
35 | Check document WM-20110607-Paul-RTL8188E_Power_Architecture-R02.vsd | ||
36 | There are 6 HW Power States: | ||
37 | 0: POFF--Power Off | ||
38 | 1: PDN--Power Down | ||
39 | 2: CARDEMU--Card Emulation | ||
40 | 3: ACT--Active Mode | ||
41 | 4: LPS--Low Power State | ||
42 | 5: SUS--Suspend | ||
43 | |||
44 | The transision from different states are defined below | ||
45 | TRANS_CARDEMU_TO_ACT | ||
46 | TRANS_ACT_TO_CARDEMU | ||
47 | TRANS_CARDEMU_TO_SUS | ||
48 | TRANS_SUS_TO_CARDEMU | ||
49 | TRANS_CARDEMU_TO_PDN | ||
50 | TRANS_ACT_TO_LPS | ||
51 | TRANS_LPS_TO_ACT | ||
52 | |||
53 | TRANS_END | ||
54 | PWR SEQ Version: rtl8188e_PwrSeq_V09.h | ||
55 | */ | ||
56 | |||
57 | #define RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS 10 | ||
58 | #define RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS 10 | ||
59 | #define RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS 10 | ||
60 | #define RTL8188E_TRANS_SUS_TO_CARDEMU_STEPS 10 | ||
61 | #define RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS 10 | ||
62 | #define RTL8188E_TRANS_PDN_TO_CARDEMU_STEPS 10 | ||
63 | #define RTL8188E_TRANS_ACT_TO_LPS_STEPS 15 | ||
64 | #define RTL8188E_TRANS_LPS_TO_ACT_STEPS 15 | ||
65 | #define RTL8188E_TRANS_END_STEPS 1 | ||
66 | |||
67 | |||
68 | #define RTL8188E_TRANS_CARDEMU_TO_ACT \ | ||
69 | /* format */ \ | ||
70 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ | ||
71 | {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
72 | /* wait till 0x04[17] = 1 power ready*/ \ | ||
73 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)}, \ | ||
74 | {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
75 | /* 0x02[1:0] = 0 reset BB*/ \ | ||
76 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0)|BIT(1), 0}, \ | ||
77 | {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
78 | /*0x24[23] = 2b'01 schmit trigger */ \ | ||
79 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, \ | ||
80 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
81 | /* 0x04[15] = 0 disable HWPDN (control by DRV)*/ \ | ||
82 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, \ | ||
83 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
84 | /*0x04[12:11] = 2b'00 disable WL suspend*/ \ | ||
85 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3), 0}, \ | ||
86 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
87 | /*0x04[8] = 1 polling until return 0*/ \ | ||
88 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ | ||
89 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
90 | /*wait till 0x04[8] = 0*/ \ | ||
91 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}, \ | ||
92 | {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
93 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*LDO normal mode*/\ | ||
94 | {0x0074, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
95 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*SDIO Driving*/\ | ||
96 | |||
97 | #define RTL8188E_TRANS_ACT_TO_CARDEMU \ | ||
98 | /* format */ \ | ||
99 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ | ||
100 | {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
101 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*0x1F[7:0] = 0 turn off RF*/\ | ||
102 | {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
103 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*LDO Sleep mode*/\ | ||
104 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
105 | /*0x04[9] = 1 turn off MAC by HW state machine*/ \ | ||
106 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ | ||
107 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
108 | /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ | ||
109 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, \ | ||
110 | |||
111 | |||
112 | #define RTL8188E_TRANS_CARDEMU_TO_SUS \ | ||
113 | /* format */ \ | ||
114 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ | ||
115 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
116 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
117 | /*0x04[12:11] = 2b'01enable WL suspend*/ \ | ||
118 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ | ||
119 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ | ||
120 | /*0x04[12:11] = 2b'11enable WL suspend for PCIe*/ \ | ||
121 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4)},\ | ||
122 | {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
123 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
124 | /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\ | ||
125 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, BIT(7)}, \ | ||
126 | {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
127 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
128 | /*Clear SIC_EN register 0x40[12] = 1'b0 */ \ | ||
129 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ | ||
130 | {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
131 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
132 | /*Set USB suspend enable local register 0xfe10[4]= 1 */ \ | ||
133 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \ | ||
134 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
135 | /*Set SDIO suspend local register*/ \ | ||
136 | PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ | ||
137 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
138 | /*wait power state to suspend*/ \ | ||
139 | PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, | ||
140 | |||
141 | #define RTL8188E_TRANS_SUS_TO_CARDEMU \ | ||
142 | /* format */ \ | ||
143 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
144 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
145 | /*Set SDIO suspend local register*/ \ | ||
146 | PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \ | ||
147 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
148 | /*wait power state to suspend*/ \ | ||
149 | PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \ | ||
150 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
151 | /*0x04[12:11] = 2b'01enable WL suspend*/ \ | ||
152 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, | ||
153 | |||
154 | #define RTL8188E_TRANS_CARDEMU_TO_CARDDIS \ | ||
155 | /* format */ \ | ||
156 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
157 | {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
158 | /*0x24[23] = 2b'01 schmit trigger */ \ | ||
159 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, \ | ||
160 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
161 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
162 | /*0x04[12:11] = 2b'01 enable WL suspend*/ \ | ||
163 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ | ||
164 | {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
165 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
166 | /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\ | ||
167 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, \ | ||
168 | {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
169 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
170 | /*Clear SIC_EN register 0x40[12] = 1'b0 */ \ | ||
171 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ | ||
172 | {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ | ||
173 | /*Set USB suspend enable local register 0xfe10[4]= 1 */ \ | ||
174 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \ | ||
175 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
176 | /*Set SDIO suspend local register*/ \ | ||
177 | PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ | ||
178 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
179 | PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/ | ||
180 | |||
181 | #define RTL8188E_TRANS_CARDDIS_TO_CARDEMU \ | ||
182 | /* format */ \ | ||
183 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
184 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
185 | PWR_BASEADDR_SDIO,\ | ||
186 | PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ \ | ||
187 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
188 | PWR_BASEADDR_SDIO,\ | ||
189 | PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\ | ||
190 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
191 | PWR_BASEADDR_MAC, \ | ||
192 | PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, \ | ||
193 | /*0x04[12:11] = 2b'01enable WL suspend*/ | ||
194 | |||
195 | |||
196 | #define RTL8188E_TRANS_CARDEMU_TO_PDN \ | ||
197 | /* format */ \ | ||
198 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
199 | {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
200 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/ \ | ||
201 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
202 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/ | ||
203 | |||
204 | |||
205 | #define RTL8188E_TRANS_PDN_TO_CARDEMU \ | ||
206 | /* format */ \ | ||
207 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
208 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
209 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/ | ||
210 | |||
211 | |||
212 | #define RTL8188E_TRANS_ACT_TO_LPS \ | ||
213 | /* format */ \ | ||
214 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ | ||
215 | {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
216 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F},/*Tx Pause*/ \ | ||
217 | {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
218 | /*zero if no pkt is tx*/\ | ||
219 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ | ||
220 | {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
221 | /*Should be zero if no packet is transmitting*/ \ | ||
222 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ | ||
223 | {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
224 | /*Should be zero if no packet is transmitting*/ \ | ||
225 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ | ||
226 | {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
227 | /*Should be zero if no packet is transmitting*/ \ | ||
228 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ | ||
229 | {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
230 | /*CCK and OFDM are disabled, and clock are gated*/ \ | ||
231 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ | ||
232 | {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
233 | PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/\ | ||
234 | {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
235 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F},/*Reset MAC TRX*/ \ | ||
236 | {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
237 | /*check if removed later*/ \ | ||
238 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \ | ||
239 | {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
240 | /*Respond TxOK to scheduler*/ \ | ||
241 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, \ | ||
242 | |||
243 | |||
244 | #define RTL8188E_TRANS_LPS_TO_ACT \ | ||
245 | /* format */ \ | ||
246 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
247 | {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
248 | PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/ \ | ||
249 | {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ | ||
250 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/ \ | ||
251 | {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ | ||
252 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/ \ | ||
253 | {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
254 | PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/ \ | ||
255 | {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
256 | /*. 0x08[4] = 0 switch TSF to 40M*/ \ | ||
257 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ | ||
258 | {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
259 | /*Polling 0x109[7]= 0 TSF in 40M*/ \ | ||
260 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, \ | ||
261 | {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
262 | /*. 0x29[7:6] = 2b'00 enable BB clock*/ \ | ||
263 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0}, \ | ||
264 | {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
265 | /*. 0x101[1] = 1*/\ | ||
266 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ | ||
267 | {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
268 | /*. 0x100[7:0] = 0xFF enable WMAC TRX*/\ | ||
269 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \ | ||
270 | {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
271 | /*. 0x02[1:0] = 2b'11 enable BB macro*/\ | ||
272 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0)}, \ | ||
273 | {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ | ||
274 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/ | ||
275 | |||
276 | |||
277 | #define RTL8188E_TRANS_END \ | ||
278 | /* format */ \ | ||
279 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ | ||
280 | {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ | ||
281 | 0, PWR_CMD_END, 0, 0} | ||
282 | |||
283 | extern struct wlan_pwr_cfg rtl8188e_power_on_flow | ||
284 | [RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS + | ||
285 | RTL8188E_TRANS_END_STEPS]; | ||
286 | extern struct wlan_pwr_cfg rtl8188e_radio_off_flow | ||
287 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
288 | RTL8188E_TRANS_END_STEPS]; | ||
289 | extern struct wlan_pwr_cfg rtl8188e_card_disable_flow | ||
290 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
291 | RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + | ||
292 | RTL8188E_TRANS_END_STEPS]; | ||
293 | extern struct wlan_pwr_cfg rtl8188e_card_enable_flow | ||
294 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
295 | RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + | ||
296 | RTL8188E_TRANS_END_STEPS]; | ||
297 | extern struct wlan_pwr_cfg rtl8188e_suspend_flow | ||
298 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
299 | RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS + | ||
300 | RTL8188E_TRANS_END_STEPS]; | ||
301 | extern struct wlan_pwr_cfg rtl8188e_resume_flow | ||
302 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
303 | RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS + | ||
304 | RTL8188E_TRANS_END_STEPS]; | ||
305 | extern struct wlan_pwr_cfg rtl8188e_hwpdn_flow | ||
306 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
307 | RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + | ||
308 | RTL8188E_TRANS_END_STEPS]; | ||
309 | extern struct wlan_pwr_cfg rtl8188e_enter_lps_flow | ||
310 | [RTL8188E_TRANS_ACT_TO_LPS_STEPS + | ||
311 | RTL8188E_TRANS_END_STEPS]; | ||
312 | extern struct wlan_pwr_cfg rtl8188e_leave_lps_flow | ||
313 | [RTL8188E_TRANS_LPS_TO_ACT_STEPS + | ||
314 | RTL8188E_TRANS_END_STEPS]; | ||
315 | |||
316 | /* RTL8723 Power Configuration CMDs for PCIe interface */ | ||
317 | #define Rtl8188E_NIC_PWR_ON_FLOW rtl8188e_power_on_flow | ||
318 | #define Rtl8188E_NIC_RF_OFF_FLOW rtl8188e_radio_off_flow | ||
319 | #define Rtl8188E_NIC_DISABLE_FLOW rtl8188e_card_disable_flow | ||
320 | #define Rtl8188E_NIC_ENABLE_FLOW rtl8188e_card_enable_flow | ||
321 | #define Rtl8188E_NIC_SUSPEND_FLOW rtl8188e_suspend_flow | ||
322 | #define Rtl8188E_NIC_RESUME_FLOW rtl8188e_resume_flow | ||
323 | #define Rtl8188E_NIC_PDN_FLOW rtl8188e_hwpdn_flow | ||
324 | #define Rtl8188E_NIC_LPS_ENTER_FLOW rtl8188e_enter_lps_flow | ||
325 | #define Rtl8188E_NIC_LPS_LEAVE_FLOW rtl8188e_leave_lps_flow | ||
326 | |||
327 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c new file mode 100644 index 000000000000..a9cfa13be3a8 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "pwrseq.h" | ||
31 | |||
32 | |||
33 | /* Description: | ||
34 | * This routine deal with the Power Configuration CMDs | ||
35 | * parsing for RTL8723/RTL8188E Series IC. | ||
36 | * Assumption: | ||
37 | * We should follow specific format which was released from HW SD. | ||
38 | * | ||
39 | * 2011.07.07, added by Roger. | ||
40 | */ | ||
41 | |||
42 | bool rtl88_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version, | ||
43 | u8 fab_version, u8 interface_type, | ||
44 | struct wlan_pwr_cfg pwrcfgcmd[]) | ||
45 | { | ||
46 | struct wlan_pwr_cfg cmd = {0}; | ||
47 | bool polling_bit = false; | ||
48 | u32 ary_idx = 0; | ||
49 | u8 val = 0; | ||
50 | u32 offset = 0; | ||
51 | u32 polling_count = 0; | ||
52 | u32 max_polling_cnt = 5000; | ||
53 | |||
54 | do { | ||
55 | cmd = pwrcfgcmd[ary_idx]; | ||
56 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
57 | "rtl88_hal_pwrseqcmdparsing(): offset(%#x), cut_msk(%#x), fab_msk(%#x)," | ||
58 | "interface_msk(%#x), base(%#x), cmd(%#x), msk(%#x), val(%#x)\n", | ||
59 | GET_PWR_CFG_OFFSET(cmd), | ||
60 | GET_PWR_CFG_CUT_MASK(cmd), | ||
61 | GET_PWR_CFG_FAB_MASK(cmd), | ||
62 | GET_PWR_CFG_INTF_MASK(cmd), | ||
63 | GET_PWR_CFG_BASE(cmd), | ||
64 | GET_PWR_CFG_CMD(cmd), | ||
65 | GET_PWR_CFG_MASK(cmd), | ||
66 | GET_PWR_CFG_VALUE(cmd)); | ||
67 | |||
68 | if ((GET_PWR_CFG_FAB_MASK(cmd) & fab_version) && | ||
69 | (GET_PWR_CFG_CUT_MASK(cmd) & cut_version) && | ||
70 | (GET_PWR_CFG_INTF_MASK(cmd) & interface_type)) { | ||
71 | switch (GET_PWR_CFG_CMD(cmd)) { | ||
72 | case PWR_CMD_READ: | ||
73 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
74 | "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_READ\n"); | ||
75 | break; | ||
76 | case PWR_CMD_WRITE: { | ||
77 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
78 | "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_WRITE\n"); | ||
79 | offset = GET_PWR_CFG_OFFSET(cmd); | ||
80 | |||
81 | /*Read the val from system register*/ | ||
82 | val = rtl_read_byte(rtlpriv, offset); | ||
83 | val &= (~(GET_PWR_CFG_MASK(cmd))); | ||
84 | val |= (GET_PWR_CFG_VALUE(cmd) & | ||
85 | GET_PWR_CFG_MASK(cmd)); | ||
86 | |||
87 | /*Write the val back to sytem register*/ | ||
88 | rtl_write_byte(rtlpriv, offset, val); | ||
89 | } | ||
90 | break; | ||
91 | case PWR_CMD_POLLING: | ||
92 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
93 | "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_POLLING\n"); | ||
94 | polling_bit = false; | ||
95 | offset = GET_PWR_CFG_OFFSET(cmd); | ||
96 | |||
97 | do { | ||
98 | val = rtl_read_byte(rtlpriv, offset); | ||
99 | |||
100 | val = val & GET_PWR_CFG_MASK(cmd); | ||
101 | if (val == (GET_PWR_CFG_VALUE(cmd) & | ||
102 | GET_PWR_CFG_MASK(cmd))) | ||
103 | polling_bit = true; | ||
104 | else | ||
105 | udelay(10); | ||
106 | |||
107 | if (polling_count++ > max_polling_cnt) { | ||
108 | RT_TRACE(rtlpriv, COMP_INIT, | ||
109 | DBG_LOUD, | ||
110 | "polling fail in pwrseqcmd\n"); | ||
111 | return false; | ||
112 | } | ||
113 | } while (!polling_bit); | ||
114 | |||
115 | break; | ||
116 | case PWR_CMD_DELAY: | ||
117 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
118 | "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_DELAY\n"); | ||
119 | if (GET_PWR_CFG_VALUE(cmd) == PWRSEQ_DELAY_US) | ||
120 | udelay(GET_PWR_CFG_OFFSET(cmd)); | ||
121 | else | ||
122 | mdelay(GET_PWR_CFG_OFFSET(cmd)); | ||
123 | break; | ||
124 | case PWR_CMD_END: | ||
125 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
126 | "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_END\n"); | ||
127 | return true; | ||
128 | break; | ||
129 | default: | ||
130 | RT_ASSERT(false, | ||
131 | "rtl88_hal_pwrseqcmdparsing(): Unknown CMD!!\n"); | ||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | ary_idx++; | ||
137 | } while (1); | ||
138 | |||
139 | return true; | ||
140 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h new file mode 100644 index 000000000000..d9ae280bb1a2 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h | |||
@@ -0,0 +1,97 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL8723E_PWRSEQCMD_H__ | ||
31 | #define __RTL8723E_PWRSEQCMD_H__ | ||
32 | |||
33 | #include "../wifi.h" | ||
34 | /*---------------------------------------------*/ | ||
35 | /* The value of cmd: 4 bits */ | ||
36 | /*---------------------------------------------*/ | ||
37 | #define PWR_CMD_READ 0x00 | ||
38 | #define PWR_CMD_WRITE 0x01 | ||
39 | #define PWR_CMD_POLLING 0x02 | ||
40 | #define PWR_CMD_DELAY 0x03 | ||
41 | #define PWR_CMD_END 0x04 | ||
42 | |||
43 | /* define the base address of each block */ | ||
44 | #define PWR_BASEADDR_MAC 0x00 | ||
45 | #define PWR_BASEADDR_USB 0x01 | ||
46 | #define PWR_BASEADDR_PCIE 0x02 | ||
47 | #define PWR_BASEADDR_SDIO 0x03 | ||
48 | |||
49 | #define PWR_INTF_SDIO_MSK BIT(0) | ||
50 | #define PWR_INTF_USB_MSK BIT(1) | ||
51 | #define PWR_INTF_PCI_MSK BIT(2) | ||
52 | #define PWR_INTF_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) | ||
53 | |||
54 | #define PWR_FAB_TSMC_MSK BIT(0) | ||
55 | #define PWR_FAB_UMC_MSK BIT(1) | ||
56 | #define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) | ||
57 | |||
58 | #define PWR_CUT_TESTCHIP_MSK BIT(0) | ||
59 | #define PWR_CUT_A_MSK BIT(1) | ||
60 | #define PWR_CUT_B_MSK BIT(2) | ||
61 | #define PWR_CUT_C_MSK BIT(3) | ||
62 | #define PWR_CUT_D_MSK BIT(4) | ||
63 | #define PWR_CUT_E_MSK BIT(5) | ||
64 | #define PWR_CUT_F_MSK BIT(6) | ||
65 | #define PWR_CUT_G_MSK BIT(7) | ||
66 | #define PWR_CUT_ALL_MSK 0xFF | ||
67 | |||
68 | enum pwrseq_delay_unit { | ||
69 | PWRSEQ_DELAY_US, | ||
70 | PWRSEQ_DELAY_MS, | ||
71 | }; | ||
72 | |||
73 | struct wlan_pwr_cfg { | ||
74 | u16 offset; | ||
75 | u8 cut_msk; | ||
76 | u8 fab_msk:4; | ||
77 | u8 interface_msk:4; | ||
78 | u8 base:4; | ||
79 | u8 cmd:4; | ||
80 | u8 msk; | ||
81 | u8 value; | ||
82 | }; | ||
83 | |||
84 | #define GET_PWR_CFG_OFFSET(__PWR) (__PWR.offset) | ||
85 | #define GET_PWR_CFG_CUT_MASK(__PWR) (__PWR.cut_msk) | ||
86 | #define GET_PWR_CFG_FAB_MASK(__PWR) (__PWR.fab_msk) | ||
87 | #define GET_PWR_CFG_INTF_MASK(__PWR) (__PWR.interface_msk) | ||
88 | #define GET_PWR_CFG_BASE(__PWR) (__PWR.base) | ||
89 | #define GET_PWR_CFG_CMD(__PWR) (__PWR.cmd) | ||
90 | #define GET_PWR_CFG_MASK(__PWR) (__PWR.msk) | ||
91 | #define GET_PWR_CFG_VALUE(__PWR) (__PWR.value) | ||
92 | |||
93 | bool rtl88_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version, | ||
94 | u8 fab_version, u8 interface_type, | ||
95 | struct wlan_pwr_cfg pwrcfgcmd[]); | ||
96 | |||
97 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h new file mode 100644 index 000000000000..d849abf7d94a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h | |||
@@ -0,0 +1,2258 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92C_REG_H__ | ||
31 | #define __RTL92C_REG_H__ | ||
32 | |||
33 | #define TXPKT_BUF_SELECT 0x69 | ||
34 | #define RXPKT_BUF_SELECT 0xA5 | ||
35 | #define DISABLE_TRXPKT_BUF_ACCESS 0x0 | ||
36 | |||
37 | #define REG_SYS_ISO_CTRL 0x0000 | ||
38 | #define REG_SYS_FUNC_EN 0x0002 | ||
39 | #define REG_APS_FSMCO 0x0004 | ||
40 | #define REG_SYS_CLKR 0x0008 | ||
41 | #define REG_9346CR 0x000A | ||
42 | #define REG_EE_VPD 0x000C | ||
43 | #define REG_AFE_MISC 0x0010 | ||
44 | #define REG_SPS0_CTRL 0x0011 | ||
45 | #define REG_SPS_OCP_CFG 0x0018 | ||
46 | #define REG_RSV_CTRL 0x001C | ||
47 | #define REG_RF_CTRL 0x001F | ||
48 | #define REG_LDOA15_CTRL 0x0020 | ||
49 | #define REG_LDOV12D_CTRL 0x0021 | ||
50 | #define REG_LDOHCI12_CTRL 0x0022 | ||
51 | #define REG_LPLDO_CTRL 0x0023 | ||
52 | #define REG_AFE_XTAL_CTRL 0x0024 | ||
53 | #define REG_AFE_LDO_CTRL 0x0027 /* 1.5v for 8188EE test | ||
54 | * chip, 1.4v for MP chip | ||
55 | */ | ||
56 | #define REG_AFE_PLL_CTRL 0x0028 | ||
57 | #define REG_EFUSE_CTRL 0x0030 | ||
58 | #define REG_EFUSE_TEST 0x0034 | ||
59 | #define REG_PWR_DATA 0x0038 | ||
60 | #define REG_CAL_TIMER 0x003C | ||
61 | #define REG_ACLK_MON 0x003E | ||
62 | #define REG_GPIO_MUXCFG 0x0040 | ||
63 | #define REG_GPIO_IO_SEL 0x0042 | ||
64 | #define REG_MAC_PINMUX_CFG 0x0043 | ||
65 | #define REG_GPIO_PIN_CTRL 0x0044 | ||
66 | #define REG_GPIO_INTM 0x0048 | ||
67 | #define REG_LEDCFG0 0x004C | ||
68 | #define REG_LEDCFG1 0x004D | ||
69 | #define REG_LEDCFG2 0x004E | ||
70 | #define REG_LEDCFG3 0x004F | ||
71 | #define REG_FSIMR 0x0050 | ||
72 | #define REG_FSISR 0x0054 | ||
73 | #define REG_HSIMR 0x0058 | ||
74 | #define REG_HSISR 0x005c | ||
75 | #define REG_GPIO_PIN_CTRL_2 0x0060 | ||
76 | #define REG_GPIO_IO_SEL_2 0x0062 | ||
77 | #define REG_GPIO_OUTPUT 0x006c | ||
78 | #define REG_AFE_XTAL_CTRL_EXT 0x0078 | ||
79 | #define REG_XCK_OUT_CTRL 0x007c | ||
80 | #define REG_MCUFWDL 0x0080 | ||
81 | #define REG_WOL_EVENT 0x0081 | ||
82 | #define REG_MCUTSTCFG 0x0084 | ||
83 | |||
84 | |||
85 | #define REG_HIMR 0x00B0 | ||
86 | #define REG_HISR 0x00B4 | ||
87 | #define REG_HIMRE 0x00B8 | ||
88 | #define REG_HISRE 0x00BC | ||
89 | |||
90 | #define REG_EFUSE_ACCESS 0x00CF | ||
91 | |||
92 | #define REG_BIST_SCAN 0x00D0 | ||
93 | #define REG_BIST_RPT 0x00D4 | ||
94 | #define REG_BIST_ROM_RPT 0x00D8 | ||
95 | #define REG_USB_SIE_INTF 0x00E0 | ||
96 | #define REG_PCIE_MIO_INTF 0x00E4 | ||
97 | #define REG_PCIE_MIO_INTD 0x00E8 | ||
98 | #define REG_HPON_FSM 0x00EC | ||
99 | #define REG_SYS_CFG 0x00F0 | ||
100 | |||
101 | #define REG_CR 0x0100 | ||
102 | #define REG_PBP 0x0104 | ||
103 | #define REG_PKT_BUFF_ACCESS_CTRL 0x0106 | ||
104 | #define REG_TRXDMA_CTRL 0x010C | ||
105 | #define REG_TRXFF_BNDY 0x0114 | ||
106 | #define REG_TRXFF_STATUS 0x0118 | ||
107 | #define REG_RXFF_PTR 0x011C | ||
108 | |||
109 | #define REG_CPWM 0x012F | ||
110 | #define REG_FWIMR 0x0130 | ||
111 | #define REG_FWISR 0x0134 | ||
112 | #define REG_PKTBUF_DBG_CTRL 0x0140 | ||
113 | #define REG_PKTBUF_DBG_DATA_L 0x0144 | ||
114 | #define REG_PKTBUF_DBG_DATA_H 0x0148 | ||
115 | #define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL+2) | ||
116 | |||
117 | #define REG_TC0_CTRL 0x0150 | ||
118 | #define REG_TC1_CTRL 0x0154 | ||
119 | #define REG_TC2_CTRL 0x0158 | ||
120 | #define REG_TC3_CTRL 0x015C | ||
121 | #define REG_TC4_CTRL 0x0160 | ||
122 | #define REG_TCUNIT_BASE 0x0164 | ||
123 | #define REG_MBIST_START 0x0174 | ||
124 | #define REG_MBIST_DONE 0x0178 | ||
125 | #define REG_MBIST_FAIL 0x017C | ||
126 | #define REG_32K_CTRL 0x0194 | ||
127 | #define REG_C2HEVT_MSG_NORMAL 0x01A0 | ||
128 | #define REG_C2HEVT_CLEAR 0x01AF | ||
129 | #define REG_C2HEVT_MSG_TEST 0x01B8 | ||
130 | #define REG_MCUTST_1 0x01c0 | ||
131 | #define REG_FMETHR 0x01C8 | ||
132 | #define REG_HMETFR 0x01CC | ||
133 | #define REG_HMEBOX_0 0x01D0 | ||
134 | #define REG_HMEBOX_1 0x01D4 | ||
135 | #define REG_HMEBOX_2 0x01D8 | ||
136 | #define REG_HMEBOX_3 0x01DC | ||
137 | |||
138 | #define REG_LLT_INIT 0x01E0 | ||
139 | #define REG_BB_ACCEESS_CTRL 0x01E8 | ||
140 | #define REG_BB_ACCESS_DATA 0x01EC | ||
141 | |||
142 | #define REG_HMEBOX_EXT_0 0x01F0 | ||
143 | #define REG_HMEBOX_EXT_1 0x01F4 | ||
144 | #define REG_HMEBOX_EXT_2 0x01F8 | ||
145 | #define REG_HMEBOX_EXT_3 0x01FC | ||
146 | |||
147 | #define REG_RQPN 0x0200 | ||
148 | #define REG_FIFOPAGE 0x0204 | ||
149 | #define REG_TDECTRL 0x0208 | ||
150 | #define REG_TXDMA_OFFSET_CHK 0x020C | ||
151 | #define REG_TXDMA_STATUS 0x0210 | ||
152 | #define REG_RQPN_NPQ 0x0214 | ||
153 | |||
154 | #define REG_RXDMA_AGG_PG_TH 0x0280 | ||
155 | #define REG_FW_UPD_RDPTR 0x0284 /* FW shall update this | ||
156 | * register before FW * write | ||
157 | * RXPKT_RELEASE_POLL to 1 | ||
158 | */ | ||
159 | #define REG_RXDMA_CONTROL 0x0286 /* Control the RX DMA.*/ | ||
160 | #define REG_RXPKT_NUM 0x0287 /* The number of packets | ||
161 | * in RXPKTBUF. | ||
162 | */ | ||
163 | #define REG_PCIE_CTRL_REG 0x0300 | ||
164 | #define REG_INT_MIG 0x0304 | ||
165 | #define REG_BCNQ_DESA 0x0308 | ||
166 | #define REG_HQ_DESA 0x0310 | ||
167 | #define REG_MGQ_DESA 0x0318 | ||
168 | #define REG_VOQ_DESA 0x0320 | ||
169 | #define REG_VIQ_DESA 0x0328 | ||
170 | #define REG_BEQ_DESA 0x0330 | ||
171 | #define REG_BKQ_DESA 0x0338 | ||
172 | #define REG_RX_DESA 0x0340 | ||
173 | |||
174 | #define REG_DBI 0x0348 | ||
175 | #define REG_MDIO 0x0354 | ||
176 | #define REG_DBG_SEL 0x0360 | ||
177 | #define REG_PCIE_HRPWM 0x0361 | ||
178 | #define REG_PCIE_HCPWM 0x0363 | ||
179 | #define REG_UART_CTRL 0x0364 | ||
180 | #define REG_WATCH_DOG 0x0368 | ||
181 | #define REG_UART_TX_DESA 0x0370 | ||
182 | #define REG_UART_RX_DESA 0x0378 | ||
183 | |||
184 | |||
185 | #define REG_HDAQ_DESA_NODEF 0x0000 | ||
186 | #define REG_CMDQ_DESA_NODEF 0x0000 | ||
187 | |||
188 | #define REG_VOQ_INFORMATION 0x0400 | ||
189 | #define REG_VIQ_INFORMATION 0x0404 | ||
190 | #define REG_BEQ_INFORMATION 0x0408 | ||
191 | #define REG_BKQ_INFORMATION 0x040C | ||
192 | #define REG_MGQ_INFORMATION 0x0410 | ||
193 | #define REG_HGQ_INFORMATION 0x0414 | ||
194 | #define REG_BCNQ_INFORMATION 0x0418 | ||
195 | #define REG_TXPKT_EMPTY 0x041A | ||
196 | |||
197 | |||
198 | #define REG_CPU_MGQ_INFORMATION 0x041C | ||
199 | #define REG_FWHW_TXQ_CTRL 0x0420 | ||
200 | #define REG_HWSEQ_CTRL 0x0423 | ||
201 | #define REG_TXPKTBUF_BCNQ_BDNY 0x0424 | ||
202 | #define REG_TXPKTBUF_MGQ_BDNY 0x0425 | ||
203 | #define REG_MULTI_BCNQ_EN 0x0426 | ||
204 | #define REG_MULTI_BCNQ_OFFSET 0x0427 | ||
205 | #define REG_SPEC_SIFS 0x0428 | ||
206 | #define REG_RL 0x042A | ||
207 | #define REG_DARFRC 0x0430 | ||
208 | #define REG_RARFRC 0x0438 | ||
209 | #define REG_RRSR 0x0440 | ||
210 | #define REG_ARFR0 0x0444 | ||
211 | #define REG_ARFR1 0x0448 | ||
212 | #define REG_ARFR2 0x044C | ||
213 | #define REG_ARFR3 0x0450 | ||
214 | #define REG_AGGLEN_LMT 0x0458 | ||
215 | #define REG_AMPDU_MIN_SPACE 0x045C | ||
216 | #define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D | ||
217 | #define REG_FAST_EDCA_CTRL 0x0460 | ||
218 | #define REG_RD_RESP_PKT_TH 0x0463 | ||
219 | #define REG_INIRTS_RATE_SEL 0x0480 | ||
220 | #define REG_INIDATA_RATE_SEL 0x0484 | ||
221 | #define REG_POWER_STATUS 0x04A4 | ||
222 | #define REG_POWER_STAGE1 0x04B4 | ||
223 | #define REG_POWER_STAGE2 0x04B8 | ||
224 | #define REG_PKT_LIFE_TIME 0x04C0 | ||
225 | #define REG_STBC_SETTING 0x04C4 | ||
226 | #define REG_PROT_MODE_CTRL 0x04C8 | ||
227 | #define REG_BAR_MODE_CTRL 0x04CC | ||
228 | #define REG_RA_TRY_RATE_AGG_LMT 0x04CF | ||
229 | #define REG_EARLY_MODE_CONTROL 0x04D0 | ||
230 | #define REG_NQOS_SEQ 0x04DC | ||
231 | #define REG_QOS_SEQ 0x04DE | ||
232 | #define REG_NEED_CPU_HANDLE 0x04E0 | ||
233 | #define REG_PKT_LOSE_RPT 0x04E1 | ||
234 | #define REG_PTCL_ERR_STATUS 0x04E2 | ||
235 | #define REG_TX_RPT_CTRL 0x04EC | ||
236 | #define REG_TX_RPT_TIME 0x04F0 | ||
237 | #define REG_DUMMY 0x04FC | ||
238 | |||
239 | #define REG_EDCA_VO_PARAM 0x0500 | ||
240 | #define REG_EDCA_VI_PARAM 0x0504 | ||
241 | #define REG_EDCA_BE_PARAM 0x0508 | ||
242 | #define REG_EDCA_BK_PARAM 0x050C | ||
243 | #define REG_BCNTCFG 0x0510 | ||
244 | #define REG_PIFS 0x0512 | ||
245 | #define REG_RDG_PIFS 0x0513 | ||
246 | #define REG_SIFS_CTX 0x0514 | ||
247 | #define REG_SIFS_TRX 0x0516 | ||
248 | #define REG_AGGR_BREAK_TIME 0x051A | ||
249 | #define REG_SLOT 0x051B | ||
250 | #define REG_TX_PTCL_CTRL 0x0520 | ||
251 | #define REG_TXPAUSE 0x0522 | ||
252 | #define REG_DIS_TXREQ_CLR 0x0523 | ||
253 | #define REG_RD_CTRL 0x0524 | ||
254 | #define REG_TBTT_PROHIBIT 0x0540 | ||
255 | #define REG_RD_NAV_NXT 0x0544 | ||
256 | #define REG_NAV_PROT_LEN 0x0546 | ||
257 | #define REG_BCN_CTRL 0x0550 | ||
258 | #define REG_USTIME_TSF 0x0551 | ||
259 | #define REG_MBID_NUM 0x0552 | ||
260 | #define REG_DUAL_TSF_RST 0x0553 | ||
261 | #define REG_BCN_INTERVAL 0x0554 | ||
262 | #define REG_MBSSID_BCN_SPACE 0x0554 | ||
263 | #define REG_DRVERLYINT 0x0558 | ||
264 | #define REG_BCNDMATIM 0x0559 | ||
265 | #define REG_ATIMWND 0x055A | ||
266 | #define REG_BCN_MAX_ERR 0x055D | ||
267 | #define REG_RXTSF_OFFSET_CCK 0x055E | ||
268 | #define REG_RXTSF_OFFSET_OFDM 0x055F | ||
269 | #define REG_TSFTR 0x0560 | ||
270 | #define REG_INIT_TSFTR 0x0564 | ||
271 | #define REG_PSTIMER 0x0580 | ||
272 | #define REG_TIMER0 0x0584 | ||
273 | #define REG_TIMER1 0x0588 | ||
274 | #define REG_ACMHWCTRL 0x05C0 | ||
275 | #define REG_ACMRSTCTRL 0x05C1 | ||
276 | #define REG_ACMAVG 0x05C2 | ||
277 | #define REG_VO_ADMTIME 0x05C4 | ||
278 | #define REG_VI_ADMTIME 0x05C6 | ||
279 | #define REG_BE_ADMTIME 0x05C8 | ||
280 | #define REG_EDCA_RANDOM_GEN 0x05CC | ||
281 | #define REG_SCH_TXCMD 0x05D0 | ||
282 | |||
283 | #define REG_APSD_CTRL 0x0600 | ||
284 | #define REG_BWOPMODE 0x0603 | ||
285 | #define REG_TCR 0x0604 | ||
286 | #define REG_RCR 0x0608 | ||
287 | #define REG_RX_PKT_LIMIT 0x060C | ||
288 | #define REG_RX_DLK_TIME 0x060D | ||
289 | #define REG_RX_DRVINFO_SZ 0x060F | ||
290 | |||
291 | #define REG_MACID 0x0610 | ||
292 | #define REG_BSSID 0x0618 | ||
293 | #define REG_MAR 0x0620 | ||
294 | #define REG_MBIDCAMCFG 0x0628 | ||
295 | |||
296 | #define REG_USTIME_EDCA 0x0638 | ||
297 | #define REG_MAC_SPEC_SIFS 0x063A | ||
298 | #define REG_RESP_SIFS_CCK 0x063C | ||
299 | #define REG_RESP_SIFS_OFDM 0x063E | ||
300 | #define REG_ACKTO 0x0640 | ||
301 | #define REG_CTS2TO 0x0641 | ||
302 | #define REG_EIFS 0x0642 | ||
303 | |||
304 | #define REG_NAV_CTRL 0x0650 | ||
305 | #define REG_BACAMCMD 0x0654 | ||
306 | #define REG_BACAMCONTENT 0x0658 | ||
307 | #define REG_LBDLY 0x0660 | ||
308 | #define REG_FWDLY 0x0661 | ||
309 | #define REG_RXERR_RPT 0x0664 | ||
310 | #define REG_TRXPTCL_CTL 0x0668 | ||
311 | |||
312 | #define REG_CAMCMD 0x0670 | ||
313 | #define REG_CAMWRITE 0x0674 | ||
314 | #define REG_CAMREAD 0x0678 | ||
315 | #define REG_CAMDBG 0x067C | ||
316 | #define REG_SECCFG 0x0680 | ||
317 | |||
318 | #define REG_WOW_CTRL 0x0690 | ||
319 | #define REG_PSSTATUS 0x0691 | ||
320 | #define REG_PS_RX_INFO 0x0692 | ||
321 | #define REG_UAPSD_TID 0x0693 | ||
322 | #define REG_LPNAV_CTRL 0x0694 | ||
323 | #define REG_WKFMCAM_NUM 0x0698 | ||
324 | #define REG_WKFMCAM_RWD 0x069C | ||
325 | #define REG_RXFLTMAP0 0x06A0 | ||
326 | #define REG_RXFLTMAP1 0x06A2 | ||
327 | #define REG_RXFLTMAP2 0x06A4 | ||
328 | #define REG_BCN_PSR_RPT 0x06A8 | ||
329 | #define REG_CALB32K_CTRL 0x06AC | ||
330 | #define REG_PKT_MON_CTRL 0x06B4 | ||
331 | #define REG_BT_COEX_TABLE 0x06C0 | ||
332 | #define REG_WMAC_RESP_TXINFO 0x06D8 | ||
333 | |||
334 | #define REG_USB_INFO 0xFE17 | ||
335 | #define REG_USB_SPECIAL_OPTION 0xFE55 | ||
336 | #define REG_USB_DMA_AGG_TO 0xFE5B | ||
337 | #define REG_USB_AGG_TO 0xFE5C | ||
338 | #define REG_USB_AGG_TH 0xFE5D | ||
339 | |||
340 | #define REG_TEST_USB_TXQS 0xFE48 | ||
341 | #define REG_TEST_SIE_VID 0xFE60 | ||
342 | #define REG_TEST_SIE_PID 0xFE62 | ||
343 | #define REG_TEST_SIE_OPTIONAL 0xFE64 | ||
344 | #define REG_TEST_SIE_CHIRP_K 0xFE65 | ||
345 | #define REG_TEST_SIE_PHY 0xFE66 | ||
346 | #define REG_TEST_SIE_MAC_ADDR 0xFE70 | ||
347 | #define REG_TEST_SIE_STRING 0xFE80 | ||
348 | |||
349 | #define REG_NORMAL_SIE_VID 0xFE60 | ||
350 | #define REG_NORMAL_SIE_PID 0xFE62 | ||
351 | #define REG_NORMAL_SIE_OPTIONAL 0xFE64 | ||
352 | #define REG_NORMAL_SIE_EP 0xFE65 | ||
353 | #define REG_NORMAL_SIE_PHY 0xFE68 | ||
354 | #define REG_NORMAL_SIE_MAC_ADDR 0xFE70 | ||
355 | #define REG_NORMAL_SIE_STRING 0xFE80 | ||
356 | |||
357 | #define CR9346 REG_9346CR | ||
358 | #define MSR (REG_CR + 2) | ||
359 | #define ISR REG_HISR | ||
360 | #define TSFR REG_TSFTR | ||
361 | |||
362 | #define MACIDR0 REG_MACID | ||
363 | #define MACIDR4 (REG_MACID + 4) | ||
364 | |||
365 | #define PBP REG_PBP | ||
366 | |||
367 | #define IDR0 MACIDR0 | ||
368 | #define IDR4 MACIDR4 | ||
369 | |||
370 | #define UNUSED_REGISTER 0x1BF | ||
371 | #define DCAM UNUSED_REGISTER | ||
372 | #define PSR UNUSED_REGISTER | ||
373 | #define BBADDR UNUSED_REGISTER | ||
374 | #define PHYDATAR UNUSED_REGISTER | ||
375 | |||
376 | #define INVALID_BBRF_VALUE 0x12345678 | ||
377 | |||
378 | #define MAX_MSS_DENSITY_2T 0x13 | ||
379 | #define MAX_MSS_DENSITY_1T 0x0A | ||
380 | |||
381 | #define CMDEEPROM_EN BIT(5) | ||
382 | #define CMDEEPROM_SEL BIT(4) | ||
383 | #define CMD9346CR_9356SEL BIT(4) | ||
384 | #define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) | ||
385 | #define AUTOLOAD_EFUSE CMDEEPROM_EN | ||
386 | |||
387 | #define GPIOSEL_GPIO 0 | ||
388 | #define GPIOSEL_ENBT BIT(5) | ||
389 | |||
390 | #define GPIO_IN REG_GPIO_PIN_CTRL | ||
391 | #define GPIO_OUT (REG_GPIO_PIN_CTRL+1) | ||
392 | #define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) | ||
393 | #define GPIO_MOD (REG_GPIO_PIN_CTRL+3) | ||
394 | |||
395 | /* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */ | ||
396 | #define HSIMR_GPIO12_0_INT_EN BIT(0) | ||
397 | #define HSIMR_SPS_OCP_INT_EN BIT(5) | ||
398 | #define HSIMR_RON_INT_EN BIT(6) | ||
399 | #define HSIMR_PDN_INT_EN BIT(7) | ||
400 | #define HSIMR_GPIO9_INT_EN BIT(25) | ||
401 | |||
402 | |||
403 | /* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */ | ||
404 | #define HSISR_GPIO12_0_INT BIT(0) | ||
405 | #define HSISR_SPS_OCP_INT BIT(5) | ||
406 | #define HSISR_RON_INT_EN BIT(6) | ||
407 | #define HSISR_PDNINT BIT(7) | ||
408 | #define HSISR_GPIO9_INT BIT(25) | ||
409 | |||
410 | #define MSR_NOLINK 0x00 | ||
411 | #define MSR_ADHOC 0x01 | ||
412 | #define MSR_INFRA 0x02 | ||
413 | #define MSR_AP 0x03 | ||
414 | |||
415 | #define RRSR_RSC_OFFSET 21 | ||
416 | #define RRSR_SHORT_OFFSET 23 | ||
417 | #define RRSR_RSC_BW_40M 0x600000 | ||
418 | #define RRSR_RSC_UPSUBCHNL 0x400000 | ||
419 | #define RRSR_RSC_LOWSUBCHNL 0x200000 | ||
420 | #define RRSR_SHORT 0x800000 | ||
421 | #define RRSR_1M BIT(0) | ||
422 | #define RRSR_2M BIT(1) | ||
423 | #define RRSR_5_5M BIT(2) | ||
424 | #define RRSR_11M BIT(3) | ||
425 | #define RRSR_6M BIT(4) | ||
426 | #define RRSR_9M BIT(5) | ||
427 | #define RRSR_12M BIT(6) | ||
428 | #define RRSR_18M BIT(7) | ||
429 | #define RRSR_24M BIT(8) | ||
430 | #define RRSR_36M BIT(9) | ||
431 | #define RRSR_48M BIT(10) | ||
432 | #define RRSR_54M BIT(11) | ||
433 | #define RRSR_MCS0 BIT(12) | ||
434 | #define RRSR_MCS1 BIT(13) | ||
435 | #define RRSR_MCS2 BIT(14) | ||
436 | #define RRSR_MCS3 BIT(15) | ||
437 | #define RRSR_MCS4 BIT(16) | ||
438 | #define RRSR_MCS5 BIT(17) | ||
439 | #define RRSR_MCS6 BIT(18) | ||
440 | #define RRSR_MCS7 BIT(19) | ||
441 | #define BRSR_ACKSHORTPMB BIT(23) | ||
442 | |||
443 | #define RATR_1M 0x00000001 | ||
444 | #define RATR_2M 0x00000002 | ||
445 | #define RATR_55M 0x00000004 | ||
446 | #define RATR_11M 0x00000008 | ||
447 | #define RATR_6M 0x00000010 | ||
448 | #define RATR_9M 0x00000020 | ||
449 | #define RATR_12M 0x00000040 | ||
450 | #define RATR_18M 0x00000080 | ||
451 | #define RATR_24M 0x00000100 | ||
452 | #define RATR_36M 0x00000200 | ||
453 | #define RATR_48M 0x00000400 | ||
454 | #define RATR_54M 0x00000800 | ||
455 | #define RATR_MCS0 0x00001000 | ||
456 | #define RATR_MCS1 0x00002000 | ||
457 | #define RATR_MCS2 0x00004000 | ||
458 | #define RATR_MCS3 0x00008000 | ||
459 | #define RATR_MCS4 0x00010000 | ||
460 | #define RATR_MCS5 0x00020000 | ||
461 | #define RATR_MCS6 0x00040000 | ||
462 | #define RATR_MCS7 0x00080000 | ||
463 | #define RATR_MCS8 0x00100000 | ||
464 | #define RATR_MCS9 0x00200000 | ||
465 | #define RATR_MCS10 0x00400000 | ||
466 | #define RATR_MCS11 0x00800000 | ||
467 | #define RATR_MCS12 0x01000000 | ||
468 | #define RATR_MCS13 0x02000000 | ||
469 | #define RATR_MCS14 0x04000000 | ||
470 | #define RATR_MCS15 0x08000000 | ||
471 | |||
472 | #define RATE_1M BIT(0) | ||
473 | #define RATE_2M BIT(1) | ||
474 | #define RATE_5_5M BIT(2) | ||
475 | #define RATE_11M BIT(3) | ||
476 | #define RATE_6M BIT(4) | ||
477 | #define RATE_9M BIT(5) | ||
478 | #define RATE_12M BIT(6) | ||
479 | #define RATE_18M BIT(7) | ||
480 | #define RATE_24M BIT(8) | ||
481 | #define RATE_36M BIT(9) | ||
482 | #define RATE_48M BIT(10) | ||
483 | #define RATE_54M BIT(11) | ||
484 | #define RATE_MCS0 BIT(12) | ||
485 | #define RATE_MCS1 BIT(13) | ||
486 | #define RATE_MCS2 BIT(14) | ||
487 | #define RATE_MCS3 BIT(15) | ||
488 | #define RATE_MCS4 BIT(16) | ||
489 | #define RATE_MCS5 BIT(17) | ||
490 | #define RATE_MCS6 BIT(18) | ||
491 | #define RATE_MCS7 BIT(19) | ||
492 | #define RATE_MCS8 BIT(20) | ||
493 | #define RATE_MCS9 BIT(21) | ||
494 | #define RATE_MCS10 BIT(22) | ||
495 | #define RATE_MCS11 BIT(23) | ||
496 | #define RATE_MCS12 BIT(24) | ||
497 | #define RATE_MCS13 BIT(25) | ||
498 | #define RATE_MCS14 BIT(26) | ||
499 | #define RATE_MCS15 BIT(27) | ||
500 | |||
501 | #define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) | ||
502 | #define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M | \ | ||
503 | RATR_24M | RATR_36M | RATR_48M | RATR_54M) | ||
504 | #define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ | ||
505 | RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \ | ||
506 | RATR_MCS6 | RATR_MCS7) | ||
507 | #define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ | ||
508 | RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ | ||
509 | RATR_MCS14 | RATR_MCS15) | ||
510 | |||
511 | #define BW_OPMODE_20MHZ BIT(2) | ||
512 | #define BW_OPMODE_5G BIT(1) | ||
513 | #define BW_OPMODE_11J BIT(0) | ||
514 | |||
515 | #define CAM_VALID BIT(15) | ||
516 | #define CAM_NOTVALID 0x0000 | ||
517 | #define CAM_USEDK BIT(5) | ||
518 | |||
519 | #define CAM_NONE 0x0 | ||
520 | #define CAM_WEP40 0x01 | ||
521 | #define CAM_TKIP 0x02 | ||
522 | #define CAM_AES 0x04 | ||
523 | #define CAM_WEP104 0x05 | ||
524 | |||
525 | #define TOTAL_CAM_ENTRY 32 | ||
526 | #define HALF_CAM_ENTRY 16 | ||
527 | |||
528 | #define CAM_WRITE BIT(16) | ||
529 | #define CAM_READ 0x00000000 | ||
530 | #define CAM_POLLINIG BIT(31) | ||
531 | |||
532 | #define SCR_USEDK 0x01 | ||
533 | #define SCR_TXSEC_ENABLE 0x02 | ||
534 | #define SCR_RXSEC_ENABLE 0x04 | ||
535 | |||
536 | #define WOW_PMEN BIT(0) | ||
537 | #define WOW_WOMEN BIT(1) | ||
538 | #define WOW_MAGIC BIT(2) | ||
539 | #define WOW_UWF BIT(3) | ||
540 | |||
541 | /********************************************* | ||
542 | * 8188 IMR/ISR bits | ||
543 | **********************************************/ | ||
544 | #define IMR_DISABLED 0x0 | ||
545 | /* IMR DW0(0x0060-0063) Bit 0-31 */ | ||
546 | #define IMR_TXCCK BIT(30) /* TXRPT interrupt when CCX bit of | ||
547 | * the packet is set | ||
548 | */ | ||
549 | #define IMR_PSTIMEOUT BIT(29) /* Power Save Time Out Interrupt */ | ||
550 | #define IMR_GTINT4 BIT(28) /* When GTIMER4 expires, | ||
551 | * this bit is set to 1 | ||
552 | */ | ||
553 | #define IMR_GTINT3 BIT(27) /* When GTIMER3 expires, | ||
554 | * this bit is set to 1 | ||
555 | */ | ||
556 | #define IMR_TBDER BIT(26) /* Transmit Beacon0 Error */ | ||
557 | #define IMR_TBDOK BIT(25) /* Transmit Beacon0 OK */ | ||
558 | #define IMR_TSF_BIT32_TOGGLE BIT(24) /* TSF Timer BIT32 toggle ind int */ | ||
559 | #define IMR_BCNDMAINT0 BIT(20) /* Beacon DMA Interrupt 0 */ | ||
560 | #define IMR_BCNDOK0 BIT(16) /* Beacon Queue DMA OK0 */ | ||
561 | #define IMR_HSISR_IND_ON_INT BIT(15) /* HSISR Indicator (HSIMR & HSISR is | ||
562 | * true, this bit is set to 1) | ||
563 | */ | ||
564 | #define IMR_BCNDMAINT_E BIT(14) /* Beacon DMA Int Extension for Win7 */ | ||
565 | #define IMR_ATIMEND BIT(12) /* CTWidnow End or ATIM Window End */ | ||
566 | #define IMR_HISR1_IND_INT BIT(11) /* HISR1 Indicator (HISR1 & HIMR1 is | ||
567 | * true, this bit is set to 1) | ||
568 | */ | ||
569 | #define IMR_C2HCMD BIT(10) /* CPU to Host Command INT Status, | ||
570 | * Write 1 clear | ||
571 | */ | ||
572 | #define IMR_CPWM2 BIT(9) /* CPU power Mode exchange INT Status, | ||
573 | * Write 1 clear | ||
574 | */ | ||
575 | #define IMR_CPWM BIT(8) /* CPU power Mode exchange INT Status, | ||
576 | * Write 1 clear | ||
577 | */ | ||
578 | #define IMR_HIGHDOK BIT(7) /* High Queue DMA OK */ | ||
579 | #define IMR_MGNTDOK BIT(6) /* Management Queue DMA OK */ | ||
580 | #define IMR_BKDOK BIT(5) /* AC_BK DMA OK */ | ||
581 | #define IMR_BEDOK BIT(4) /* AC_BE DMA OK */ | ||
582 | #define IMR_VIDOK BIT(3) /* AC_VI DMA OK */ | ||
583 | #define IMR_VODOK BIT(2) /* AC_VO DMA OK */ | ||
584 | #define IMR_RDU BIT(1) /* Rx Descriptor Unavailable */ | ||
585 | #define IMR_ROK BIT(0) /* Receive DMA OK */ | ||
586 | |||
587 | /* IMR DW1(0x00B4-00B7) Bit 0-31 */ | ||
588 | #define IMR_BCNDMAINT7 BIT(27) /* Beacon DMA Interrupt 7 */ | ||
589 | #define IMR_BCNDMAINT6 BIT(26) /* Beacon DMA Interrupt 6 */ | ||
590 | #define IMR_BCNDMAINT5 BIT(25) /* Beacon DMA Interrupt 5 */ | ||
591 | #define IMR_BCNDMAINT4 BIT(24) /* Beacon DMA Interrupt 4 */ | ||
592 | #define IMR_BCNDMAINT3 BIT(23) /* Beacon DMA Interrupt 3 */ | ||
593 | #define IMR_BCNDMAINT2 BIT(22) /* Beacon DMA Interrupt 2 */ | ||
594 | #define IMR_BCNDMAINT1 BIT(21) /* Beacon DMA Interrupt 1 */ | ||
595 | #define IMR_BCNDOK7 BIT(20) /* Beacon Queue DMA OK Interrup 7 */ | ||
596 | #define IMR_BCNDOK6 BIT(19) /* Beacon Queue DMA OK Interrup 6 */ | ||
597 | #define IMR_BCNDOK5 BIT(18) /* Beacon Queue DMA OK Interrup 5 */ | ||
598 | #define IMR_BCNDOK4 BIT(17) /* Beacon Queue DMA OK Interrup 4 */ | ||
599 | #define IMR_BCNDOK3 BIT(16) /* Beacon Queue DMA OK Interrup 3 */ | ||
600 | #define IMR_BCNDOK2 BIT(15) /* Beacon Queue DMA OK Interrup 2 */ | ||
601 | #define IMR_BCNDOK1 BIT(14) /* Beacon Queue DMA OK Interrup 1 */ | ||
602 | #define IMR_ATIMEND_E BIT(13) /* ATIM Window End Extension for Win7 */ | ||
603 | #define IMR_TXERR BIT(11) /* Tx Err Flag Int Status, | ||
604 | * write 1 clear. | ||
605 | */ | ||
606 | #define IMR_RXERR BIT(10) /* Rx Err Flag INT Status, | ||
607 | * Write 1 clear | ||
608 | */ | ||
609 | #define IMR_TXFOVW BIT(9) /* Transmit FIFO Overflow */ | ||
610 | #define IMR_RXFOVW BIT(8) /* Receive FIFO Overflow */ | ||
611 | |||
612 | |||
613 | #define HWSET_MAX_SIZE 512 | ||
614 | #define EFUSE_MAX_SECTION 64 | ||
615 | #define EFUSE_REAL_CONTENT_LEN 256 | ||
616 | #define EFUSE_OOB_PROTECT_BYTES 18 /* PG data exclude header, | ||
617 | * dummy 7 bytes frome CP | ||
618 | * test and reserved 1byte. | ||
619 | */ | ||
620 | |||
621 | #define EEPROM_DEFAULT_TSSI 0x0 | ||
622 | #define EEPROM_DEFAULT_TXPOWERDIFF 0x0 | ||
623 | #define EEPROM_DEFAULT_CRYSTALCAP 0x5 | ||
624 | #define EEPROM_DEFAULT_BOARDTYPE 0x02 | ||
625 | #define EEPROM_DEFAULT_TXPOWER 0x1010 | ||
626 | #define EEPROM_DEFAULT_HT2T_TXPWR 0x10 | ||
627 | |||
628 | #define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 | ||
629 | #define EEPROM_DEFAULT_THERMALMETER 0x18 | ||
630 | #define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 | ||
631 | #define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 | ||
632 | #define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 | ||
633 | #define EEPROM_DEFAULT_HT40_2SDIFF 0x0 | ||
634 | #define EEPROM_DEFAULT_HT20_DIFF 2 | ||
635 | #define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 | ||
636 | #define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 | ||
637 | #define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 | ||
638 | |||
639 | #define RF_OPTION1 0x79 | ||
640 | #define RF_OPTION2 0x7A | ||
641 | #define RF_OPTION3 0x7B | ||
642 | #define RF_OPTION4 0x7C | ||
643 | |||
644 | #define EEPROM_DEFAULT_PID 0x1234 | ||
645 | #define EEPROM_DEFAULT_VID 0x5678 | ||
646 | #define EEPROM_DEFAULT_CUSTOMERID 0xAB | ||
647 | #define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD | ||
648 | #define EEPROM_DEFAULT_VERSION 0 | ||
649 | |||
650 | #define EEPROM_CHANNEL_PLAN_FCC 0x0 | ||
651 | #define EEPROM_CHANNEL_PLAN_IC 0x1 | ||
652 | #define EEPROM_CHANNEL_PLAN_ETSI 0x2 | ||
653 | #define EEPROM_CHANNEL_PLAN_SPAIN 0x3 | ||
654 | #define EEPROM_CHANNEL_PLAN_FRANCE 0x4 | ||
655 | #define EEPROM_CHANNEL_PLAN_MKK 0x5 | ||
656 | #define EEPROM_CHANNEL_PLAN_MKK1 0x6 | ||
657 | #define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 | ||
658 | #define EEPROM_CHANNEL_PLAN_TELEC 0x8 | ||
659 | #define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 | ||
660 | #define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA | ||
661 | #define EEPROM_CHANNEL_PLAN_NCC 0xB | ||
662 | #define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 | ||
663 | |||
664 | #define EEPROM_CID_DEFAULT 0x0 | ||
665 | #define EEPROM_CID_TOSHIBA 0x4 | ||
666 | #define EEPROM_CID_CCX 0x10 | ||
667 | #define EEPROM_CID_QMI 0x0D | ||
668 | #define EEPROM_CID_WHQL 0xFE | ||
669 | |||
670 | #define RTL8188E_EEPROM_ID 0x8129 | ||
671 | |||
672 | #define EEPROM_HPON 0x02 | ||
673 | #define EEPROM_CLK 0x06 | ||
674 | #define EEPROM_TESTR 0x08 | ||
675 | |||
676 | #define EEPROM_TXPOWERCCK 0x10 | ||
677 | #define EEPROM_TXPOWERHT40_1S 0x16 | ||
678 | #define EEPROM_TXPOWERHT20DIFF 0x1B | ||
679 | #define EEPROM_TXPOWER_OFDMDIFF 0x1B | ||
680 | |||
681 | #define EEPROM_TX_PWR_INX 0x10 | ||
682 | |||
683 | #define EEPROM_CHANNELPLAN 0xB8 | ||
684 | #define EEPROM_XTAL_88E 0xB9 | ||
685 | #define EEPROM_THERMAL_METER_88E 0xBA | ||
686 | #define EEPROM_IQK_LCK_88E 0xBB | ||
687 | |||
688 | #define EEPROM_RF_BOARD_OPTION_88E 0xC1 | ||
689 | #define EEPROM_RF_FEATURE_OPTION_88E 0xC2 | ||
690 | #define EEPROM_RF_BT_SETTING_88E 0xC3 | ||
691 | #define EEPROM_VERSION 0xC4 | ||
692 | #define EEPROM_CUSTOMER_ID 0xC5 | ||
693 | #define EEPROM_RF_ANTENNA_OPT_88E 0xC9 | ||
694 | |||
695 | #define EEPROM_MAC_ADDR 0xD0 | ||
696 | #define EEPROM_VID 0xD6 | ||
697 | #define EEPROM_DID 0xD8 | ||
698 | #define EEPROM_SVID 0xDA | ||
699 | #define EEPROM_SMID 0xDC | ||
700 | |||
701 | #define STOPBECON BIT(6) | ||
702 | #define STOPHIGHT BIT(5) | ||
703 | #define STOPMGT BIT(4) | ||
704 | #define STOPVO BIT(3) | ||
705 | #define STOPVI BIT(2) | ||
706 | #define STOPBE BIT(1) | ||
707 | #define STOPBK BIT(0) | ||
708 | |||
709 | #define RCR_APPFCS BIT(31) | ||
710 | #define RCR_APP_MIC BIT(30) | ||
711 | #define RCR_APP_ICV BIT(29) | ||
712 | #define RCR_APP_PHYST_RXFF BIT(28) | ||
713 | #define RCR_APP_BA_SSN BIT(27) | ||
714 | #define RCR_ENMBID BIT(24) | ||
715 | #define RCR_LSIGEN BIT(23) | ||
716 | #define RCR_MFBEN BIT(22) | ||
717 | #define RCR_HTC_LOC_CTRL BIT(14) | ||
718 | #define RCR_AMF BIT(13) | ||
719 | #define RCR_ACF BIT(12) | ||
720 | #define RCR_ADF BIT(11) | ||
721 | #define RCR_AICV BIT(9) | ||
722 | #define RCR_ACRC32 BIT(8) | ||
723 | #define RCR_CBSSID_BCN BIT(7) | ||
724 | #define RCR_CBSSID_DATA BIT(6) | ||
725 | #define RCR_CBSSID RCR_CBSSID_DATA | ||
726 | #define RCR_APWRMGT BIT(5) | ||
727 | #define RCR_ADD3 BIT(4) | ||
728 | #define RCR_AB BIT(3) | ||
729 | #define RCR_AM BIT(2) | ||
730 | #define RCR_APM BIT(1) | ||
731 | #define RCR_AAP BIT(0) | ||
732 | #define RCR_MXDMA_OFFSET 8 | ||
733 | #define RCR_FIFO_OFFSET 13 | ||
734 | |||
735 | #define RSV_CTRL 0x001C | ||
736 | #define RD_CTRL 0x0524 | ||
737 | |||
738 | #define REG_USB_INFO 0xFE17 | ||
739 | #define REG_USB_SPECIAL_OPTION 0xFE55 | ||
740 | #define REG_USB_DMA_AGG_TO 0xFE5B | ||
741 | #define REG_USB_AGG_TO 0xFE5C | ||
742 | #define REG_USB_AGG_TH 0xFE5D | ||
743 | |||
744 | #define REG_USB_VID 0xFE60 | ||
745 | #define REG_USB_PID 0xFE62 | ||
746 | #define REG_USB_OPTIONAL 0xFE64 | ||
747 | #define REG_USB_CHIRP_K 0xFE65 | ||
748 | #define REG_USB_PHY 0xFE66 | ||
749 | #define REG_USB_MAC_ADDR 0xFE70 | ||
750 | #define REG_USB_HRPWM 0xFE58 | ||
751 | #define REG_USB_HCPWM 0xFE57 | ||
752 | |||
753 | #define SW18_FPWM BIT(3) | ||
754 | |||
755 | #define ISO_MD2PP BIT(0) | ||
756 | #define ISO_UA2USB BIT(1) | ||
757 | #define ISO_UD2CORE BIT(2) | ||
758 | #define ISO_PA2PCIE BIT(3) | ||
759 | #define ISO_PD2CORE BIT(4) | ||
760 | #define ISO_IP2MAC BIT(5) | ||
761 | #define ISO_DIOP BIT(6) | ||
762 | #define ISO_DIOE BIT(7) | ||
763 | #define ISO_EB2CORE BIT(8) | ||
764 | #define ISO_DIOR BIT(9) | ||
765 | |||
766 | #define PWC_EV25V BIT(14) | ||
767 | #define PWC_EV12V BIT(15) | ||
768 | |||
769 | #define FEN_BBRSTB BIT(0) | ||
770 | #define FEN_BB_GLB_RSTN BIT(1) | ||
771 | #define FEN_USBA BIT(2) | ||
772 | #define FEN_UPLL BIT(3) | ||
773 | #define FEN_USBD BIT(4) | ||
774 | #define FEN_DIO_PCIE BIT(5) | ||
775 | #define FEN_PCIEA BIT(6) | ||
776 | #define FEN_PPLL BIT(7) | ||
777 | #define FEN_PCIED BIT(8) | ||
778 | #define FEN_DIOE BIT(9) | ||
779 | #define FEN_CPUEN BIT(10) | ||
780 | #define FEN_DCORE BIT(11) | ||
781 | #define FEN_ELDR BIT(12) | ||
782 | #define FEN_DIO_RF BIT(13) | ||
783 | #define FEN_HWPDN BIT(14) | ||
784 | #define FEN_MREGEN BIT(15) | ||
785 | |||
786 | #define PFM_LDALL BIT(0) | ||
787 | #define PFM_ALDN BIT(1) | ||
788 | #define PFM_LDKP BIT(2) | ||
789 | #define PFM_WOWL BIT(3) | ||
790 | #define ENPDN BIT(4) | ||
791 | #define PDN_PL BIT(5) | ||
792 | #define APFM_ONMAC BIT(8) | ||
793 | #define APFM_OFF BIT(9) | ||
794 | #define APFM_RSM BIT(10) | ||
795 | #define AFSM_HSUS BIT(11) | ||
796 | #define AFSM_PCIE BIT(12) | ||
797 | #define APDM_MAC BIT(13) | ||
798 | #define APDM_HOST BIT(14) | ||
799 | #define APDM_HPDN BIT(15) | ||
800 | #define RDY_MACON BIT(16) | ||
801 | #define SUS_HOST BIT(17) | ||
802 | #define ROP_ALD BIT(20) | ||
803 | #define ROP_PWR BIT(21) | ||
804 | #define ROP_SPS BIT(22) | ||
805 | #define SOP_MRST BIT(25) | ||
806 | #define SOP_FUSE BIT(26) | ||
807 | #define SOP_ABG BIT(27) | ||
808 | #define SOP_AMB BIT(28) | ||
809 | #define SOP_RCK BIT(29) | ||
810 | #define SOP_A8M BIT(30) | ||
811 | #define XOP_BTCK BIT(31) | ||
812 | |||
813 | #define ANAD16V_EN BIT(0) | ||
814 | #define ANA8M BIT(1) | ||
815 | #define MACSLP BIT(4) | ||
816 | #define LOADER_CLK_EN BIT(5) | ||
817 | #define _80M_SSC_DIS BIT(7) | ||
818 | #define _80M_SSC_EN_HO BIT(8) | ||
819 | #define PHY_SSC_RSTB BIT(9) | ||
820 | #define SEC_CLK_EN BIT(10) | ||
821 | #define MAC_CLK_EN BIT(11) | ||
822 | #define SYS_CLK_EN BIT(12) | ||
823 | #define RING_CLK_EN BIT(13) | ||
824 | |||
825 | #define BOOT_FROM_EEPROM BIT(4) | ||
826 | #define EEPROM_EN BIT(5) | ||
827 | |||
828 | #define AFE_BGEN BIT(0) | ||
829 | #define AFE_MBEN BIT(1) | ||
830 | #define MAC_ID_EN BIT(7) | ||
831 | |||
832 | #define WLOCK_ALL BIT(0) | ||
833 | #define WLOCK_00 BIT(1) | ||
834 | #define WLOCK_04 BIT(2) | ||
835 | #define WLOCK_08 BIT(3) | ||
836 | #define WLOCK_40 BIT(4) | ||
837 | #define R_DIS_PRST_0 BIT(5) | ||
838 | #define R_DIS_PRST_1 BIT(6) | ||
839 | #define LOCK_ALL_EN BIT(7) | ||
840 | |||
841 | #define RF_EN BIT(0) | ||
842 | #define RF_RSTB BIT(1) | ||
843 | #define RF_SDMRSTB BIT(2) | ||
844 | |||
845 | #define LDA15_EN BIT(0) | ||
846 | #define LDA15_STBY BIT(1) | ||
847 | #define LDA15_OBUF BIT(2) | ||
848 | #define LDA15_REG_VOS BIT(3) | ||
849 | #define _LDA15_VOADJ(x) (((x) & 0x7) << 4) | ||
850 | |||
851 | #define LDV12_EN BIT(0) | ||
852 | #define LDV12_SDBY BIT(1) | ||
853 | #define LPLDO_HSM BIT(2) | ||
854 | #define LPLDO_LSM_DIS BIT(3) | ||
855 | #define _LDV12_VADJ(x) (((x) & 0xF) << 4) | ||
856 | |||
857 | #define XTAL_EN BIT(0) | ||
858 | #define XTAL_BSEL BIT(1) | ||
859 | #define _XTAL_BOSC(x) (((x) & 0x3) << 2) | ||
860 | #define _XTAL_CADJ(x) (((x) & 0xF) << 4) | ||
861 | #define XTAL_GATE_USB BIT(8) | ||
862 | #define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) | ||
863 | #define XTAL_GATE_AFE BIT(11) | ||
864 | #define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) | ||
865 | #define XTAL_RF_GATE BIT(14) | ||
866 | #define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) | ||
867 | #define XTAL_GATE_DIG BIT(17) | ||
868 | #define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) | ||
869 | #define XTAL_BT_GATE BIT(20) | ||
870 | #define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) | ||
871 | #define _XTAL_GPIO(x) (((x) & 0x7) << 23) | ||
872 | |||
873 | #define CKDLY_AFE BIT(26) | ||
874 | #define CKDLY_USB BIT(27) | ||
875 | #define CKDLY_DIG BIT(28) | ||
876 | #define CKDLY_BT BIT(29) | ||
877 | |||
878 | #define APLL_EN BIT(0) | ||
879 | #define APLL_320_EN BIT(1) | ||
880 | #define APLL_FREF_SEL BIT(2) | ||
881 | #define APLL_EDGE_SEL BIT(3) | ||
882 | #define APLL_WDOGB BIT(4) | ||
883 | #define APLL_LPFEN BIT(5) | ||
884 | |||
885 | #define APLL_REF_CLK_13MHZ 0x1 | ||
886 | #define APLL_REF_CLK_19_2MHZ 0x2 | ||
887 | #define APLL_REF_CLK_20MHZ 0x3 | ||
888 | #define APLL_REF_CLK_25MHZ 0x4 | ||
889 | #define APLL_REF_CLK_26MHZ 0x5 | ||
890 | #define APLL_REF_CLK_38_4MHZ 0x6 | ||
891 | #define APLL_REF_CLK_40MHZ 0x7 | ||
892 | |||
893 | #define APLL_320EN BIT(14) | ||
894 | #define APLL_80EN BIT(15) | ||
895 | #define APLL_1MEN BIT(24) | ||
896 | |||
897 | #define ALD_EN BIT(18) | ||
898 | #define EF_PD BIT(19) | ||
899 | #define EF_FLAG BIT(31) | ||
900 | |||
901 | #define EF_TRPT BIT(7) | ||
902 | #define LDOE25_EN BIT(31) | ||
903 | |||
904 | #define RSM_EN BIT(0) | ||
905 | #define TIMER_EN BIT(4) | ||
906 | |||
907 | #define TRSW0EN BIT(2) | ||
908 | #define TRSW1EN BIT(3) | ||
909 | #define EROM_EN BIT(4) | ||
910 | #define ENBT BIT(5) | ||
911 | #define ENUART BIT(8) | ||
912 | #define UART_910 BIT(9) | ||
913 | #define ENPMAC BIT(10) | ||
914 | #define SIC_SWRST BIT(11) | ||
915 | #define ENSIC BIT(12) | ||
916 | #define SIC_23 BIT(13) | ||
917 | #define ENHDP BIT(14) | ||
918 | #define SIC_LBK BIT(15) | ||
919 | |||
920 | #define LED0PL BIT(4) | ||
921 | #define LED1PL BIT(12) | ||
922 | #define LED0DIS BIT(7) | ||
923 | |||
924 | #define MCUFWDL_EN BIT(0) | ||
925 | #define MCUFWDL_RDY BIT(1) | ||
926 | #define FWDL_CHKSUM_RPT BIT(2) | ||
927 | #define MACINI_RDY BIT(3) | ||
928 | #define BBINI_RDY BIT(4) | ||
929 | #define RFINI_RDY BIT(5) | ||
930 | #define WINTINI_RDY BIT(6) | ||
931 | #define CPRST BIT(23) | ||
932 | |||
933 | #define XCLK_VLD BIT(0) | ||
934 | #define ACLK_VLD BIT(1) | ||
935 | #define UCLK_VLD BIT(2) | ||
936 | #define PCLK_VLD BIT(3) | ||
937 | #define PCIRSTB BIT(4) | ||
938 | #define V15_VLD BIT(5) | ||
939 | #define TRP_B15V_EN BIT(7) | ||
940 | #define SIC_IDLE BIT(8) | ||
941 | #define BD_MAC2 BIT(9) | ||
942 | #define BD_MAC1 BIT(10) | ||
943 | #define IC_MACPHY_MODE BIT(11) | ||
944 | #define VENDOR_ID BIT(19) | ||
945 | #define PAD_HWPD_IDN BIT(22) | ||
946 | #define TRP_VAUX_EN BIT(23) | ||
947 | #define TRP_BT_EN BIT(24) | ||
948 | #define BD_PKG_SEL BIT(25) | ||
949 | #define BD_HCI_SEL BIT(26) | ||
950 | #define TYPE_ID BIT(27) | ||
951 | |||
952 | #define CHIP_VER_RTL_MASK 0xF000 | ||
953 | #define CHIP_VER_RTL_SHIFT 12 | ||
954 | |||
955 | #define REG_LBMODE (REG_CR + 3) | ||
956 | |||
957 | #define HCI_TXDMA_EN BIT(0) | ||
958 | #define HCI_RXDMA_EN BIT(1) | ||
959 | #define TXDMA_EN BIT(2) | ||
960 | #define RXDMA_EN BIT(3) | ||
961 | #define PROTOCOL_EN BIT(4) | ||
962 | #define SCHEDULE_EN BIT(5) | ||
963 | #define MACTXEN BIT(6) | ||
964 | #define MACRXEN BIT(7) | ||
965 | #define ENSWBCN BIT(8) | ||
966 | #define ENSEC BIT(9) | ||
967 | |||
968 | #define _NETTYPE(x) (((x) & 0x3) << 16) | ||
969 | #define MASK_NETTYPE 0x30000 | ||
970 | #define NT_NO_LINK 0x0 | ||
971 | #define NT_LINK_AD_HOC 0x1 | ||
972 | #define NT_LINK_AP 0x2 | ||
973 | #define NT_AS_AP 0x3 | ||
974 | |||
975 | #define _LBMODE(x) (((x) & 0xF) << 24) | ||
976 | #define MASK_LBMODE 0xF000000 | ||
977 | #define LOOPBACK_NORMAL 0x0 | ||
978 | #define LOOPBACK_IMMEDIATELY 0xB | ||
979 | #define LOOPBACK_MAC_DELAY 0x3 | ||
980 | #define LOOPBACK_PHY 0x1 | ||
981 | #define LOOPBACK_DMA 0x7 | ||
982 | |||
983 | #define GET_RX_PAGE_SIZE(value) ((value) & 0xF) | ||
984 | #define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) | ||
985 | #define _PSRX_MASK 0xF | ||
986 | #define _PSTX_MASK 0xF0 | ||
987 | #define _PSRX(x) (x) | ||
988 | #define _PSTX(x) ((x) << 4) | ||
989 | |||
990 | #define PBP_64 0x0 | ||
991 | #define PBP_128 0x1 | ||
992 | #define PBP_256 0x2 | ||
993 | #define PBP_512 0x3 | ||
994 | #define PBP_1024 0x4 | ||
995 | |||
996 | #define RXDMA_ARBBW_EN BIT(0) | ||
997 | #define RXSHFT_EN BIT(1) | ||
998 | #define RXDMA_AGG_EN BIT(2) | ||
999 | #define QS_VO_QUEUE BIT(8) | ||
1000 | #define QS_VI_QUEUE BIT(9) | ||
1001 | #define QS_BE_QUEUE BIT(10) | ||
1002 | #define QS_BK_QUEUE BIT(11) | ||
1003 | #define QS_MANAGER_QUEUE BIT(12) | ||
1004 | #define QS_HIGH_QUEUE BIT(13) | ||
1005 | |||
1006 | #define HQSEL_VOQ BIT(0) | ||
1007 | #define HQSEL_VIQ BIT(1) | ||
1008 | #define HQSEL_BEQ BIT(2) | ||
1009 | #define HQSEL_BKQ BIT(3) | ||
1010 | #define HQSEL_MGTQ BIT(4) | ||
1011 | #define HQSEL_HIQ BIT(5) | ||
1012 | |||
1013 | #define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) | ||
1014 | #define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) | ||
1015 | #define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) | ||
1016 | #define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) | ||
1017 | #define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) | ||
1018 | #define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) | ||
1019 | |||
1020 | #define QUEUE_LOW 1 | ||
1021 | #define QUEUE_NORMAL 2 | ||
1022 | #define QUEUE_HIGH 3 | ||
1023 | |||
1024 | #define _LLT_NO_ACTIVE 0x0 | ||
1025 | #define _LLT_WRITE_ACCESS 0x1 | ||
1026 | #define _LLT_READ_ACCESS 0x2 | ||
1027 | |||
1028 | #define _LLT_INIT_DATA(x) ((x) & 0xFF) | ||
1029 | #define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) | ||
1030 | #define _LLT_OP(x) (((x) & 0x3) << 30) | ||
1031 | #define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) | ||
1032 | |||
1033 | #define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) | ||
1034 | #define BB_WRITE_EN BIT(30) | ||
1035 | #define BB_READ_EN BIT(31) | ||
1036 | |||
1037 | #define _HPQ(x) ((x) & 0xFF) | ||
1038 | #define _LPQ(x) (((x) & 0xFF) << 8) | ||
1039 | #define _PUBQ(x) (((x) & 0xFF) << 16) | ||
1040 | #define _NPQ(x) ((x) & 0xFF) | ||
1041 | |||
1042 | #define HPQ_PUBLIC_DIS BIT(24) | ||
1043 | #define LPQ_PUBLIC_DIS BIT(25) | ||
1044 | #define LD_RQPN BIT(31) | ||
1045 | |||
1046 | #define BCN_VALID BIT(16) | ||
1047 | #define BCN_HEAD(x) (((x) & 0xFF) << 8) | ||
1048 | #define BCN_HEAD_MASK 0xFF00 | ||
1049 | |||
1050 | #define BLK_DESC_NUM_SHIFT 4 | ||
1051 | #define BLK_DESC_NUM_MASK 0xF | ||
1052 | |||
1053 | #define DROP_DATA_EN BIT(9) | ||
1054 | |||
1055 | #define EN_AMPDU_RTY_NEW BIT(7) | ||
1056 | |||
1057 | #define _INIRTSMCS_SEL(x) ((x) & 0x3F) | ||
1058 | |||
1059 | #define _SPEC_SIFS_CCK(x) ((x) & 0xFF) | ||
1060 | #define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) | ||
1061 | |||
1062 | #define RATE_REG_BITMAP_ALL 0xFFFFF | ||
1063 | |||
1064 | #define _RRSC_BITMAP(x) ((x) & 0xFFFFF) | ||
1065 | |||
1066 | #define _RRSR_RSC(x) (((x) & 0x3) << 21) | ||
1067 | #define RRSR_RSC_RESERVED 0x0 | ||
1068 | #define RRSR_RSC_UPPER_SUBCHANNEL 0x1 | ||
1069 | #define RRSR_RSC_LOWER_SUBCHANNEL 0x2 | ||
1070 | #define RRSR_RSC_DUPLICATE_MODE 0x3 | ||
1071 | |||
1072 | #define USE_SHORT_G1 BIT(20) | ||
1073 | |||
1074 | #define _AGGLMT_MCS0(x) ((x) & 0xF) | ||
1075 | #define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) | ||
1076 | #define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) | ||
1077 | #define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) | ||
1078 | #define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) | ||
1079 | #define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) | ||
1080 | #define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) | ||
1081 | #define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) | ||
1082 | |||
1083 | #define RETRY_LIMIT_SHORT_SHIFT 8 | ||
1084 | #define RETRY_LIMIT_LONG_SHIFT 0 | ||
1085 | |||
1086 | #define _DARF_RC1(x) ((x) & 0x1F) | ||
1087 | #define _DARF_RC2(x) (((x) & 0x1F) << 8) | ||
1088 | #define _DARF_RC3(x) (((x) & 0x1F) << 16) | ||
1089 | #define _DARF_RC4(x) (((x) & 0x1F) << 24) | ||
1090 | #define _DARF_RC5(x) ((x) & 0x1F) | ||
1091 | #define _DARF_RC6(x) (((x) & 0x1F) << 8) | ||
1092 | #define _DARF_RC7(x) (((x) & 0x1F) << 16) | ||
1093 | #define _DARF_RC8(x) (((x) & 0x1F) << 24) | ||
1094 | |||
1095 | #define _RARF_RC1(x) ((x) & 0x1F) | ||
1096 | #define _RARF_RC2(x) (((x) & 0x1F) << 8) | ||
1097 | #define _RARF_RC3(x) (((x) & 0x1F) << 16) | ||
1098 | #define _RARF_RC4(x) (((x) & 0x1F) << 24) | ||
1099 | #define _RARF_RC5(x) ((x) & 0x1F) | ||
1100 | #define _RARF_RC6(x) (((x) & 0x1F) << 8) | ||
1101 | #define _RARF_RC7(x) (((x) & 0x1F) << 16) | ||
1102 | #define _RARF_RC8(x) (((x) & 0x1F) << 24) | ||
1103 | |||
1104 | #define AC_PARAM_TXOP_LIMIT_OFFSET 16 | ||
1105 | #define AC_PARAM_ECW_MAX_OFFSET 12 | ||
1106 | #define AC_PARAM_ECW_MIN_OFFSET 8 | ||
1107 | #define AC_PARAM_AIFS_OFFSET 0 | ||
1108 | |||
1109 | #define _AIFS(x) (x) | ||
1110 | #define _ECW_MAX_MIN(x) ((x) << 8) | ||
1111 | #define _TXOP_LIMIT(x) ((x) << 16) | ||
1112 | |||
1113 | #define _BCNIFS(x) ((x) & 0xFF) | ||
1114 | #define _BCNECW(x) ((((x) & 0xF)) << 8) | ||
1115 | |||
1116 | #define _LRL(x) ((x) & 0x3F) | ||
1117 | #define _SRL(x) (((x) & 0x3F) << 8) | ||
1118 | |||
1119 | #define _SIFS_CCK_CTX(x) ((x) & 0xFF) | ||
1120 | #define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8); | ||
1121 | |||
1122 | #define _SIFS_OFDM_CTX(x) ((x) & 0xFF) | ||
1123 | #define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8); | ||
1124 | |||
1125 | #define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) | ||
1126 | |||
1127 | #define DIS_EDCA_CNT_DWN BIT(11) | ||
1128 | |||
1129 | #define EN_MBSSID BIT(1) | ||
1130 | #define EN_TXBCN_RPT BIT(2) | ||
1131 | #define EN_BCN_FUNCTION BIT(3) | ||
1132 | |||
1133 | #define TSFTR_RST BIT(0) | ||
1134 | #define TSFTR1_RST BIT(1) | ||
1135 | |||
1136 | #define STOP_BCNQ BIT(6) | ||
1137 | |||
1138 | #define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) | ||
1139 | #define DIS_TSF_UDT0_TEST_CHIP BIT(5) | ||
1140 | |||
1141 | #define ACMHW_HWEN BIT(0) | ||
1142 | #define ACMHW_BEQEN BIT(1) | ||
1143 | #define ACMHW_VIQEN BIT(2) | ||
1144 | #define ACMHW_VOQEN BIT(3) | ||
1145 | #define ACMHW_BEQSTATUS BIT(4) | ||
1146 | #define ACMHW_VIQSTATUS BIT(5) | ||
1147 | #define ACMHW_VOQSTATUS BIT(6) | ||
1148 | |||
1149 | #define APSDOFF BIT(6) | ||
1150 | #define APSDOFF_STATUS BIT(7) | ||
1151 | |||
1152 | #define BW_20MHZ BIT(2) | ||
1153 | |||
1154 | #define RATE_BITMAP_ALL 0xFFFFF | ||
1155 | |||
1156 | #define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 | ||
1157 | |||
1158 | #define TSFRST BIT(0) | ||
1159 | #define DIS_GCLK BIT(1) | ||
1160 | #define PAD_SEL BIT(2) | ||
1161 | #define PWR_ST BIT(6) | ||
1162 | #define PWRBIT_OW_EN BIT(7) | ||
1163 | #define ACRC BIT(8) | ||
1164 | #define CFENDFORM BIT(9) | ||
1165 | #define ICV BIT(10) | ||
1166 | |||
1167 | #define AAP BIT(0) | ||
1168 | #define APM BIT(1) | ||
1169 | #define AM BIT(2) | ||
1170 | #define AB BIT(3) | ||
1171 | #define ADD3 BIT(4) | ||
1172 | #define APWRMGT BIT(5) | ||
1173 | #define CBSSID BIT(6) | ||
1174 | #define CBSSID_DATA BIT(6) | ||
1175 | #define CBSSID_BCN BIT(7) | ||
1176 | #define ACRC32 BIT(8) | ||
1177 | #define AICV BIT(9) | ||
1178 | #define ADF BIT(11) | ||
1179 | #define ACF BIT(12) | ||
1180 | #define AMF BIT(13) | ||
1181 | #define HTC_LOC_CTRL BIT(14) | ||
1182 | #define UC_DATA_EN BIT(16) | ||
1183 | #define BM_DATA_EN BIT(17) | ||
1184 | #define MFBEN BIT(22) | ||
1185 | #define LSIGEN BIT(23) | ||
1186 | #define ENMBID BIT(24) | ||
1187 | #define APP_BASSN BIT(27) | ||
1188 | #define APP_PHYSTS BIT(28) | ||
1189 | #define APP_ICV BIT(29) | ||
1190 | #define APP_MIC BIT(30) | ||
1191 | #define APP_FCS BIT(31) | ||
1192 | |||
1193 | #define _MIN_SPACE(x) ((x) & 0x7) | ||
1194 | #define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) | ||
1195 | |||
1196 | #define RXERR_TYPE_OFDM_PPDU 0 | ||
1197 | #define RXERR_TYPE_OFDM_FALSE_ALARM 1 | ||
1198 | #define RXERR_TYPE_OFDM_MPDU_OK 2 | ||
1199 | #define RXERR_TYPE_OFDM_MPDU_FAIL 3 | ||
1200 | #define RXERR_TYPE_CCK_PPDU 4 | ||
1201 | #define RXERR_TYPE_CCK_FALSE_ALARM 5 | ||
1202 | #define RXERR_TYPE_CCK_MPDU_OK 6 | ||
1203 | #define RXERR_TYPE_CCK_MPDU_FAIL 7 | ||
1204 | #define RXERR_TYPE_HT_PPDU 8 | ||
1205 | #define RXERR_TYPE_HT_FALSE_ALARM 9 | ||
1206 | #define RXERR_TYPE_HT_MPDU_TOTAL 10 | ||
1207 | #define RXERR_TYPE_HT_MPDU_OK 11 | ||
1208 | #define RXERR_TYPE_HT_MPDU_FAIL 12 | ||
1209 | #define RXERR_TYPE_RX_FULL_DROP 15 | ||
1210 | |||
1211 | #define RXERR_COUNTER_MASK 0xFFFFF | ||
1212 | #define RXERR_RPT_RST BIT(27) | ||
1213 | #define _RXERR_RPT_SEL(type) ((type) << 28) | ||
1214 | |||
1215 | #define SCR_TXUSEDK BIT(0) | ||
1216 | #define SCR_RXUSEDK BIT(1) | ||
1217 | #define SCR_TXENCENABLE BIT(2) | ||
1218 | #define SCR_RXDECENABLE BIT(3) | ||
1219 | #define SCR_SKBYA2 BIT(4) | ||
1220 | #define SCR_NOSKMC BIT(5) | ||
1221 | #define SCR_TXBCUSEDK BIT(6) | ||
1222 | #define SCR_RXBCUSEDK BIT(7) | ||
1223 | |||
1224 | #define USB_IS_HIGH_SPEED 0 | ||
1225 | #define USB_IS_FULL_SPEED 1 | ||
1226 | #define USB_SPEED_MASK BIT(5) | ||
1227 | |||
1228 | #define USB_NORMAL_SIE_EP_MASK 0xF | ||
1229 | #define USB_NORMAL_SIE_EP_SHIFT 4 | ||
1230 | |||
1231 | #define USB_TEST_EP_MASK 0x30 | ||
1232 | #define USB_TEST_EP_SHIFT 4 | ||
1233 | |||
1234 | #define USB_AGG_EN BIT(3) | ||
1235 | |||
1236 | #define MAC_ADDR_LEN 6 | ||
1237 | #define LAST_ENTRY_OF_TX_PKT_BUFFER 175/*255 88e*/ | ||
1238 | |||
1239 | #define POLLING_LLT_THRESHOLD 20 | ||
1240 | #define POLLING_READY_TIMEOUT_COUNT 3000 | ||
1241 | |||
1242 | #define MAX_MSS_DENSITY_2T 0x13 | ||
1243 | #define MAX_MSS_DENSITY_1T 0x0A | ||
1244 | |||
1245 | #define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) | ||
1246 | #define EPROM_CMD_CONFIG 0x3 | ||
1247 | #define EPROM_CMD_LOAD 1 | ||
1248 | |||
1249 | #define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE | ||
1250 | |||
1251 | #define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) | ||
1252 | |||
1253 | #define RPMAC_RESET 0x100 | ||
1254 | #define RPMAC_TXSTART 0x104 | ||
1255 | #define RPMAC_TXLEGACYSIG 0x108 | ||
1256 | #define RPMAC_TXHTSIG1 0x10c | ||
1257 | #define RPMAC_TXHTSIG2 0x110 | ||
1258 | #define RPMAC_PHYDEBUG 0x114 | ||
1259 | #define RPMAC_TXPACKETNUM 0x118 | ||
1260 | #define RPMAC_TXIDLE 0x11c | ||
1261 | #define RPMAC_TXMACHEADER0 0x120 | ||
1262 | #define RPMAC_TXMACHEADER1 0x124 | ||
1263 | #define RPMAC_TXMACHEADER2 0x128 | ||
1264 | #define RPMAC_TXMACHEADER3 0x12c | ||
1265 | #define RPMAC_TXMACHEADER4 0x130 | ||
1266 | #define RPMAC_TXMACHEADER5 0x134 | ||
1267 | #define RPMAC_TXDADATYPE 0x138 | ||
1268 | #define RPMAC_TXRANDOMSEED 0x13c | ||
1269 | #define RPMAC_CCKPLCPPREAMBLE 0x140 | ||
1270 | #define RPMAC_CCKPLCPHEADER 0x144 | ||
1271 | #define RPMAC_CCKCRC16 0x148 | ||
1272 | #define RPMAC_OFDMRXCRC32OK 0x170 | ||
1273 | #define RPMAC_OFDMRXCRC32Er 0x174 | ||
1274 | #define RPMAC_OFDMRXPARITYER 0x178 | ||
1275 | #define RPMAC_OFDMRXCRC8ER 0x17c | ||
1276 | #define RPMAC_CCKCRXRC16ER 0x180 | ||
1277 | #define RPMAC_CCKCRXRC32ER 0x184 | ||
1278 | #define RPMAC_CCKCRXRC32OK 0x188 | ||
1279 | #define RPMAC_TXSTATUS 0x18c | ||
1280 | |||
1281 | #define RFPGA0_RFMOD 0x800 | ||
1282 | |||
1283 | #define RFPGA0_TXINFO 0x804 | ||
1284 | #define RFPGA0_PSDFUNCTION 0x808 | ||
1285 | |||
1286 | #define RFPGA0_TXGAINSTAGE 0x80c | ||
1287 | |||
1288 | #define RFPGA0_RFTIMING1 0x810 | ||
1289 | #define RFPGA0_RFTIMING2 0x814 | ||
1290 | |||
1291 | #define RFPGA0_XA_HSSIPARAMETER1 0x820 | ||
1292 | #define RFPGA0_XA_HSSIPARAMETER2 0x824 | ||
1293 | #define RFPGA0_XB_HSSIPARAMETER1 0x828 | ||
1294 | #define RFPGA0_XB_HSSIPARAMETER2 0x82c | ||
1295 | |||
1296 | #define RFPGA0_XA_LSSIPARAMETER 0x840 | ||
1297 | #define RFPGA0_XB_LSSIPARAMETER 0x844 | ||
1298 | |||
1299 | #define RFPGA0_RFWAKEUPPARAMETER 0x850 | ||
1300 | #define RFPGA0_RFSLEEPUPPARAMETER 0x854 | ||
1301 | |||
1302 | #define RFPGA0_XAB_SWITCHCONTROL 0x858 | ||
1303 | #define RFPGA0_XCD_SWITCHCONTROL 0x85c | ||
1304 | |||
1305 | #define RFPGA0_XA_RFINTERFACEOE 0x860 | ||
1306 | #define RFPGA0_XB_RFINTERFACEOE 0x864 | ||
1307 | |||
1308 | #define RFPGA0_XAB_RFINTERFACESW 0x870 | ||
1309 | #define RFPGA0_XCD_RFINTERFACESW 0x874 | ||
1310 | |||
1311 | #define rFPGA0_XAB_RFPARAMETER 0x878 | ||
1312 | #define rFPGA0_XCD_RFPARAMETER 0x87c | ||
1313 | |||
1314 | #define RFPGA0_ANALOGPARAMETER1 0x880 | ||
1315 | #define RFPGA0_ANALOGPARAMETER2 0x884 | ||
1316 | #define RFPGA0_ANALOGPARAMETER3 0x888 | ||
1317 | #define RFPGA0_ANALOGPARAMETER4 0x88c | ||
1318 | |||
1319 | #define RFPGA0_XA_LSSIREADBACK 0x8a0 | ||
1320 | #define RFPGA0_XB_LSSIREADBACK 0x8a4 | ||
1321 | #define RFPGA0_XC_LSSIREADBACK 0x8a8 | ||
1322 | #define RFPGA0_XD_LSSIREADBACK 0x8ac | ||
1323 | |||
1324 | #define RFPGA0_PSDREPORT 0x8b4 | ||
1325 | #define TRANSCEIVEA_HSPI_READBACK 0x8b8 | ||
1326 | #define TRANSCEIVEB_HSPI_READBACK 0x8bc | ||
1327 | #define REG_SC_CNT 0x8c4 | ||
1328 | #define RFPGA0_XAB_RFINTERFACERB 0x8e0 | ||
1329 | #define RFPGA0_XCD_RFINTERFACERB 0x8e4 | ||
1330 | |||
1331 | #define RFPGA1_RFMOD 0x900 | ||
1332 | |||
1333 | #define RFPGA1_TXBLOCK 0x904 | ||
1334 | #define RFPGA1_DEBUGSELECT 0x908 | ||
1335 | #define RFPGA1_TXINFO 0x90c | ||
1336 | |||
1337 | #define RCCK0_SYSTEM 0xa00 | ||
1338 | |||
1339 | #define RCCK0_AFESETTING 0xa04 | ||
1340 | #define RCCK0_CCA 0xa08 | ||
1341 | |||
1342 | #define RCCK0_RXAGC1 0xa0c | ||
1343 | #define RCCK0_RXAGC2 0xa10 | ||
1344 | |||
1345 | #define RCCK0_RXHP 0xa14 | ||
1346 | |||
1347 | #define RCCK0_DSPPARAMETER1 0xa18 | ||
1348 | #define RCCK0_DSPPARAMETER2 0xa1c | ||
1349 | |||
1350 | #define RCCK0_TXFILTER1 0xa20 | ||
1351 | #define RCCK0_TXFILTER2 0xa24 | ||
1352 | #define RCCK0_DEBUGPORT 0xa28 | ||
1353 | #define RCCK0_FALSEALARMREPORT 0xa2c | ||
1354 | #define RCCK0_TRSSIREPORT 0xa50 | ||
1355 | #define RCCK0_RXREPORT 0xa54 | ||
1356 | #define RCCK0_FACOUNTERLOWER 0xa5c | ||
1357 | #define RCCK0_FACOUNTERUPPER 0xa58 | ||
1358 | #define RCCK0_CCA_CNT 0xa60 | ||
1359 | |||
1360 | |||
1361 | /* PageB(0xB00) */ | ||
1362 | #define RPDP_ANTA 0xb00 | ||
1363 | #define RPDP_ANTA_4 0xb04 | ||
1364 | #define RPDP_ANTA_8 0xb08 | ||
1365 | #define RPDP_ANTA_C 0xb0c | ||
1366 | #define RPDP_ANTA_10 0xb10 | ||
1367 | #define RPDP_ANTA_14 0xb14 | ||
1368 | #define RPDP_ANTA_18 0xb18 | ||
1369 | #define RPDP_ANTA_1C 0xb1c | ||
1370 | #define RPDP_ANTA_20 0xb20 | ||
1371 | #define RPDP_ANTA_24 0xb24 | ||
1372 | |||
1373 | #define RCONFIG_PMPD_ANTA 0xb28 | ||
1374 | #define RCONFIG_RAM64X16 0xb2c | ||
1375 | |||
1376 | #define RBNDA 0xb30 | ||
1377 | #define RHSSIPAR 0xb34 | ||
1378 | |||
1379 | #define RCONFIG_ANTA 0xb68 | ||
1380 | #define RCONFIG_ANTB 0xb6c | ||
1381 | |||
1382 | #define RPDP_ANTB 0xb70 | ||
1383 | #define RPDP_ANTB_4 0xb74 | ||
1384 | #define RPDP_ANTB_8 0xb78 | ||
1385 | #define RPDP_ANTB_C 0xb7c | ||
1386 | #define RPDP_ANTB_10 0xb80 | ||
1387 | #define RPDP_ANTB_14 0xb84 | ||
1388 | #define RPDP_ANTB_18 0xb88 | ||
1389 | #define RPDP_ANTB_1C 0xb8c | ||
1390 | #define RPDP_ANTB_20 0xb90 | ||
1391 | #define RPDP_ANTB_24 0xb94 | ||
1392 | |||
1393 | #define RCONFIG_PMPD_ANTB 0xb98 | ||
1394 | |||
1395 | #define RBNDB 0xba0 | ||
1396 | |||
1397 | #define RAPK 0xbd8 | ||
1398 | #define rPm_Rx0_AntA 0xbdc | ||
1399 | #define rPm_Rx1_AntA 0xbe0 | ||
1400 | #define rPm_Rx2_AntA 0xbe4 | ||
1401 | #define rPm_Rx3_AntA 0xbe8 | ||
1402 | #define rPm_Rx0_AntB 0xbec | ||
1403 | #define rPm_Rx1_AntB 0xbf0 | ||
1404 | #define rPm_Rx2_AntB 0xbf4 | ||
1405 | #define rPm_Rx3_AntB 0xbf8 | ||
1406 | |||
1407 | /*Page C*/ | ||
1408 | #define ROFDM0_LSTF 0xc00 | ||
1409 | |||
1410 | #define ROFDM0_TRXPATHENABLE 0xc04 | ||
1411 | #define ROFDM0_TRMUXPAR 0xc08 | ||
1412 | #define ROFDM0_TRSWISOLATION 0xc0c | ||
1413 | |||
1414 | #define ROFDM0_XARXAFE 0xc10 | ||
1415 | #define ROFDM0_XARXIQIMBAL 0xc14 | ||
1416 | #define ROFDM0_XBRXAFE 0xc18 | ||
1417 | #define ROFDM0_XBRXIQIMBAL 0xc1c | ||
1418 | #define ROFDM0_XCRXAFE 0xc20 | ||
1419 | #define ROFDM0_XCRXIQIMBAL 0xc24 | ||
1420 | #define ROFDM0_XDRXAFE 0xc28 | ||
1421 | #define ROFDM0_XDRXIQIMBAL 0xc2c | ||
1422 | |||
1423 | #define ROFDM0_RXDETECTOR1 0xc30 | ||
1424 | #define ROFDM0_RXDETECTOR2 0xc34 | ||
1425 | #define ROFDM0_RXDETECTOR3 0xc38 | ||
1426 | #define ROFDM0_RXDETECTOR4 0xc3c | ||
1427 | |||
1428 | #define ROFDM0_RXDSP 0xc40 | ||
1429 | #define ROFDM0_CFOANDDAGC 0xc44 | ||
1430 | #define ROFDM0_CCADROPTHRES 0xc48 | ||
1431 | #define ROFDM0_ECCATHRES 0xc4c | ||
1432 | |||
1433 | #define ROFDM0_XAAGCCORE1 0xc50 | ||
1434 | #define ROFDM0_XAAGCCORE2 0xc54 | ||
1435 | #define ROFDM0_XBAGCCORE1 0xc58 | ||
1436 | #define ROFDM0_XBAGCCORE2 0xc5c | ||
1437 | #define ROFDM0_XCAGCCORE1 0xc60 | ||
1438 | #define ROFDM0_XCAGCCORE2 0xc64 | ||
1439 | #define ROFDM0_XDAGCCORE1 0xc68 | ||
1440 | #define ROFDM0_XDAGCCORE2 0xc6c | ||
1441 | |||
1442 | #define ROFDM0_AGCPARAMETER1 0xc70 | ||
1443 | #define ROFDM0_AGCPARAMETER2 0xc74 | ||
1444 | #define ROFDM0_AGCRSSITABLE 0xc78 | ||
1445 | #define ROFDM0_HTSTFAGC 0xc7c | ||
1446 | |||
1447 | #define ROFDM0_XATXIQIMBAL 0xc80 | ||
1448 | #define ROFDM0_XATXAFE 0xc84 | ||
1449 | #define ROFDM0_XBTXIQIMBAL 0xc88 | ||
1450 | #define ROFDM0_XBTXAFE 0xc8c | ||
1451 | #define ROFDM0_XCTXIQIMBAL 0xc90 | ||
1452 | #define ROFDM0_XCTXAFE 0xc94 | ||
1453 | #define ROFDM0_XDTXIQIMBAL 0xc98 | ||
1454 | #define ROFDM0_XDTXAFE 0xc9c | ||
1455 | |||
1456 | #define ROFDM0_RXIQEXTANTA 0xca0 | ||
1457 | #define ROFDM0_TXCOEFF1 0xca4 | ||
1458 | #define ROFDM0_TXCOEFF2 0xca8 | ||
1459 | #define ROFDM0_TXCOEFF3 0xcac | ||
1460 | #define ROFDM0_TXCOEFF4 0xcb0 | ||
1461 | #define ROFDM0_TXCOEFF5 0xcb4 | ||
1462 | #define ROFDM0_TXCOEFF6 0xcb8 | ||
1463 | |||
1464 | #define ROFDM0_RXHPPARAMETER 0xce0 | ||
1465 | #define ROFDM0_TXPSEUDONOISEWGT 0xce4 | ||
1466 | #define ROFDM0_FRAMESYNC 0xcf0 | ||
1467 | #define ROFDM0_DFSREPORT 0xcf4 | ||
1468 | |||
1469 | |||
1470 | #define ROFDM1_LSTF 0xd00 | ||
1471 | #define ROFDM1_TRXPATHENABLE 0xd04 | ||
1472 | |||
1473 | #define ROFDM1_CF0 0xd08 | ||
1474 | #define ROFDM1_CSI1 0xd10 | ||
1475 | #define ROFDM1_SBD 0xd14 | ||
1476 | #define ROFDM1_CSI2 0xd18 | ||
1477 | #define ROFDM1_CFOTRACKING 0xd2c | ||
1478 | #define ROFDM1_TRXMESAURE1 0xd34 | ||
1479 | #define ROFDM1_INTFDET 0xd3c | ||
1480 | #define ROFDM1_PSEUDONOISESTATEAB 0xd50 | ||
1481 | #define ROFDM1_PSEUDONOISESTATECD 0xd54 | ||
1482 | #define ROFDM1_RXPSEUDONOISEWGT 0xd58 | ||
1483 | |||
1484 | #define ROFDM_PHYCOUNTER1 0xda0 | ||
1485 | #define ROFDM_PHYCOUNTER2 0xda4 | ||
1486 | #define ROFDM_PHYCOUNTER3 0xda8 | ||
1487 | |||
1488 | #define ROFDM_SHORTCFOAB 0xdac | ||
1489 | #define ROFDM_SHORTCFOCD 0xdb0 | ||
1490 | #define ROFDM_LONGCFOAB 0xdb4 | ||
1491 | #define ROFDM_LONGCFOCD 0xdb8 | ||
1492 | #define ROFDM_TAILCF0AB 0xdbc | ||
1493 | #define ROFDM_TAILCF0CD 0xdc0 | ||
1494 | #define ROFDM_PWMEASURE1 0xdc4 | ||
1495 | #define ROFDM_PWMEASURE2 0xdc8 | ||
1496 | #define ROFDM_BWREPORT 0xdcc | ||
1497 | #define ROFDM_AGCREPORT 0xdd0 | ||
1498 | #define ROFDM_RXSNR 0xdd4 | ||
1499 | #define ROFDM_RXEVMCSI 0xdd8 | ||
1500 | #define ROFDM_SIGREPORT 0xddc | ||
1501 | |||
1502 | #define RTXAGC_A_RATE18_06 0xe00 | ||
1503 | #define RTXAGC_A_RATE54_24 0xe04 | ||
1504 | #define RTXAGC_A_CCK1_MCS32 0xe08 | ||
1505 | #define RTXAGC_A_MCS03_MCS00 0xe10 | ||
1506 | #define RTXAGC_A_MCS07_MCS04 0xe14 | ||
1507 | #define RTXAGC_A_MCS11_MCS08 0xe18 | ||
1508 | #define RTXAGC_A_MCS15_MCS12 0xe1c | ||
1509 | |||
1510 | #define RTXAGC_B_RATE18_06 0x830 | ||
1511 | #define RTXAGC_B_RATE54_24 0x834 | ||
1512 | #define RTXAGC_B_CCK1_55_MCS32 0x838 | ||
1513 | #define RTXAGC_B_MCS03_MCS00 0x83c | ||
1514 | #define RTXAGC_B_MCS07_MCS04 0x848 | ||
1515 | #define RTXAGC_B_MCS11_MCS08 0x84c | ||
1516 | #define RTXAGC_B_MCS15_MCS12 0x868 | ||
1517 | #define RTXAGC_B_CCK11_A_CCK2_11 0x86c | ||
1518 | |||
1519 | #define RFPGA0_IQK 0xe28 | ||
1520 | #define RTX_IQK_TONE_A 0xe30 | ||
1521 | #define RRX_IQK_TONE_A 0xe34 | ||
1522 | #define RTX_IQK_PI_A 0xe38 | ||
1523 | #define RRX_IQK_PI_A 0xe3c | ||
1524 | |||
1525 | #define RTX_IQK 0xe40 | ||
1526 | #define RRX_IQK 0xe44 | ||
1527 | #define RIQK_AGC_PTS 0xe48 | ||
1528 | #define RIQK_AGC_RSP 0xe4c | ||
1529 | #define RTX_IQK_TONE_B 0xe50 | ||
1530 | #define RRX_IQK_TONE_B 0xe54 | ||
1531 | #define RTX_IQK_PI_B 0xe58 | ||
1532 | #define RRX_IQK_PI_B 0xe5c | ||
1533 | #define RIQK_AGC_CONT 0xe60 | ||
1534 | |||
1535 | #define RBLUE_TOOTH 0xe6c | ||
1536 | #define RRX_WAIT_CCA 0xe70 | ||
1537 | #define RTX_CCK_RFON 0xe74 | ||
1538 | #define RTX_CCK_BBON 0xe78 | ||
1539 | #define RTX_OFDM_RFON 0xe7c | ||
1540 | #define RTX_OFDM_BBON 0xe80 | ||
1541 | #define RTX_TO_RX 0xe84 | ||
1542 | #define RTX_TO_TX 0xe88 | ||
1543 | #define RRX_CCK 0xe8c | ||
1544 | |||
1545 | #define RTX_POWER_BEFORE_IQK_A 0xe94 | ||
1546 | #define RTX_POWER_AFTER_IQK_A 0xe9c | ||
1547 | |||
1548 | #define RRX_POWER_BEFORE_IQK_A 0xea0 | ||
1549 | #define RRX_POWER_BEFORE_IQK_A_2 0xea4 | ||
1550 | #define RRX_POWER_AFTER_IQK_A 0xea8 | ||
1551 | #define RRX_POWER_AFTER_IQK_A_2 0xeac | ||
1552 | |||
1553 | #define RTX_POWER_BEFORE_IQK_B 0xeb4 | ||
1554 | #define RTX_POWER_AFTER_IQK_B 0xebc | ||
1555 | |||
1556 | #define RRX_POWER_BEFORE_IQK_B 0xec0 | ||
1557 | #define RRX_POWER_BEFORE_IQK_B_2 0xec4 | ||
1558 | #define RRX_POWER_AFTER_IQK_B 0xec8 | ||
1559 | #define RRX_POWER_AFTER_IQK_B_2 0xecc | ||
1560 | |||
1561 | #define RRX_OFDM 0xed0 | ||
1562 | #define RRX_WAIT_RIFS 0xed4 | ||
1563 | #define RRX_TO_RX 0xed8 | ||
1564 | #define RSTANDBY 0xedc | ||
1565 | #define RSLEEP 0xee0 | ||
1566 | #define RPMPD_ANAEN 0xeec | ||
1567 | |||
1568 | #define RZEBRA1_HSSIENABLE 0x0 | ||
1569 | #define RZEBRA1_TRXENABLE1 0x1 | ||
1570 | #define RZEBRA1_TRXENABLE2 0x2 | ||
1571 | #define RZEBRA1_AGC 0x4 | ||
1572 | #define RZEBRA1_CHARGEPUMP 0x5 | ||
1573 | #define RZEBRA1_CHANNEL 0x7 | ||
1574 | |||
1575 | #define RZEBRA1_TXGAIN 0x8 | ||
1576 | #define RZEBRA1_TXLPF 0x9 | ||
1577 | #define RZEBRA1_RXLPF 0xb | ||
1578 | #define RZEBRA1_RXHPFCORNER 0xc | ||
1579 | |||
1580 | #define RGLOBALCTRL 0 | ||
1581 | #define RRTL8256_TXLPF 19 | ||
1582 | #define RRTL8256_RXLPF 11 | ||
1583 | #define RRTL8258_TXLPF 0x11 | ||
1584 | #define RRTL8258_RXLPF 0x13 | ||
1585 | #define RRTL8258_RSSILPF 0xa | ||
1586 | |||
1587 | #define RF_AC 0x00 | ||
1588 | |||
1589 | #define RF_IQADJ_G1 0x01 | ||
1590 | #define RF_IQADJ_G2 0x02 | ||
1591 | #define RF_POW_TRSW 0x05 | ||
1592 | |||
1593 | #define RF_GAIN_RX 0x06 | ||
1594 | #define RF_GAIN_TX 0x07 | ||
1595 | |||
1596 | #define RF_TXM_IDAC 0x08 | ||
1597 | #define RF_BS_IQGEN 0x0F | ||
1598 | |||
1599 | #define RF_MODE1 0x10 | ||
1600 | #define RF_MODE2 0x11 | ||
1601 | |||
1602 | #define RF_RX_AGC_HP 0x12 | ||
1603 | #define RF_TX_AGC 0x13 | ||
1604 | #define RF_BIAS 0x14 | ||
1605 | #define RF_IPA 0x15 | ||
1606 | #define RF_POW_ABILITY 0x17 | ||
1607 | #define RF_MODE_AG 0x18 | ||
1608 | #define RRFCHANNEL 0x18 | ||
1609 | #define RF_CHNLBW 0x18 | ||
1610 | #define RF_TOP 0x19 | ||
1611 | |||
1612 | #define RF_RX_G1 0x1A | ||
1613 | #define RF_RX_G2 0x1B | ||
1614 | |||
1615 | #define RF_RX_BB2 0x1C | ||
1616 | #define RF_RX_BB1 0x1D | ||
1617 | |||
1618 | #define RF_RCK1 0x1E | ||
1619 | #define RF_RCK2 0x1F | ||
1620 | |||
1621 | #define RF_TX_G1 0x20 | ||
1622 | #define RF_TX_G2 0x21 | ||
1623 | #define RF_TX_G3 0x22 | ||
1624 | |||
1625 | #define RF_TX_BB1 0x23 | ||
1626 | #define RF_T_METER 0x42 | ||
1627 | |||
1628 | #define RF_SYN_G1 0x25 | ||
1629 | #define RF_SYN_G2 0x26 | ||
1630 | #define RF_SYN_G3 0x27 | ||
1631 | #define RF_SYN_G4 0x28 | ||
1632 | #define RF_SYN_G5 0x29 | ||
1633 | #define RF_SYN_G6 0x2A | ||
1634 | #define RF_SYN_G7 0x2B | ||
1635 | #define RF_SYN_G8 0x2C | ||
1636 | |||
1637 | #define RF_RCK_OS 0x30 | ||
1638 | #define RF_TXPA_G1 0x31 | ||
1639 | #define RF_TXPA_G2 0x32 | ||
1640 | #define RF_TXPA_G3 0x33 | ||
1641 | |||
1642 | #define RF_TX_BIAS_A 0x35 | ||
1643 | #define RF_TX_BIAS_D 0x36 | ||
1644 | #define RF_LOBF_9 0x38 | ||
1645 | #define RF_RXRF_A3 0x3C | ||
1646 | #define RF_TRSW 0x3F | ||
1647 | |||
1648 | #define RF_TXRF_A2 0x41 | ||
1649 | #define RF_TXPA_G4 0x46 | ||
1650 | #define RF_TXPA_A4 0x4B | ||
1651 | |||
1652 | #define RF_WE_LUT 0xEF | ||
1653 | |||
1654 | #define BBBRESETB 0x100 | ||
1655 | #define BGLOBALRESETB 0x200 | ||
1656 | #define BOFDMTXSTART 0x4 | ||
1657 | #define BCCKTXSTART 0x8 | ||
1658 | #define BCRC32DEBUG 0x100 | ||
1659 | #define BPMACLOOPBACK 0x10 | ||
1660 | #define BTXLSIG 0xffffff | ||
1661 | #define BOFDMTXRATE 0xf | ||
1662 | #define BOFDMTXRESERVED 0x10 | ||
1663 | #define BOFDMTXLENGTH 0x1ffe0 | ||
1664 | #define BOFDMTXPARITY 0x20000 | ||
1665 | #define BTXHTSIG1 0xffffff | ||
1666 | #define BTXHTMCSRATE 0x7f | ||
1667 | #define BTXHTBW 0x80 | ||
1668 | #define BTXHTLENGTH 0xffff00 | ||
1669 | #define BTXHTSIG2 0xffffff | ||
1670 | #define BTXHTSMOOTHING 0x1 | ||
1671 | #define BTXHTSOUNDING 0x2 | ||
1672 | #define BTXHTRESERVED 0x4 | ||
1673 | #define BTXHTAGGREATION 0x8 | ||
1674 | #define BTXHTSTBC 0x30 | ||
1675 | #define BTXHTADVANCECODING 0x40 | ||
1676 | #define BTXHTSHORTGI 0x80 | ||
1677 | #define BTXHTNUMBERHT_LTF 0x300 | ||
1678 | #define BTXHTCRC8 0x3fc00 | ||
1679 | #define BCOUNTERRESET 0x10000 | ||
1680 | #define BNUMOFOFDMTX 0xffff | ||
1681 | #define BNUMOFCCKTX 0xffff0000 | ||
1682 | #define BTXIDLEINTERVAL 0xffff | ||
1683 | #define BOFDMSERVICE 0xffff0000 | ||
1684 | #define BTXMACHEADER 0xffffffff | ||
1685 | #define BTXDATAINIT 0xff | ||
1686 | #define BTXHTMODE 0x100 | ||
1687 | #define BTXDATATYPE 0x30000 | ||
1688 | #define BTXRANDOMSEED 0xffffffff | ||
1689 | #define BCCKTXPREAMBLE 0x1 | ||
1690 | #define BCCKTXSFD 0xffff0000 | ||
1691 | #define BCCKTXSIG 0xff | ||
1692 | #define BCCKTXSERVICE 0xff00 | ||
1693 | #define BCCKLENGTHEXT 0x8000 | ||
1694 | #define BCCKTXLENGHT 0xffff0000 | ||
1695 | #define BCCKTXCRC16 0xffff | ||
1696 | #define BCCKTXSTATUS 0x1 | ||
1697 | #define BOFDMTXSTATUS 0x2 | ||
1698 | #define IS_BB_REG_OFFSET_92S(_offset) \ | ||
1699 | ((_offset >= 0x800) && (_offset <= 0xfff)) | ||
1700 | |||
1701 | #define BRFMOD 0x1 | ||
1702 | #define BJAPANMODE 0x2 | ||
1703 | #define BCCKTXSC 0x30 | ||
1704 | #define BCCKEN 0x1000000 | ||
1705 | #define BOFDMEN 0x2000000 | ||
1706 | |||
1707 | #define BOFDMRXADCPHASE 0x10000 | ||
1708 | #define BOFDMTXDACPHASE 0x40000 | ||
1709 | #define BXATXAGC 0x3f | ||
1710 | |||
1711 | #define BXBTXAGC 0xf00 | ||
1712 | #define BXCTXAGC 0xf000 | ||
1713 | #define BXDTXAGC 0xf0000 | ||
1714 | |||
1715 | #define BPASTART 0xf0000000 | ||
1716 | #define BTRSTART 0x00f00000 | ||
1717 | #define BRFSTART 0x0000f000 | ||
1718 | #define BBBSTART 0x000000f0 | ||
1719 | #define BBBCCKSTART 0x0000000f | ||
1720 | #define BPAEND 0xf | ||
1721 | #define BTREND 0x0f000000 | ||
1722 | #define BRFEND 0x000f0000 | ||
1723 | #define BCCAMASK 0x000000f0 | ||
1724 | #define BR2RCCAMASK 0x00000f00 | ||
1725 | #define BHSSI_R2TDELAY 0xf8000000 | ||
1726 | #define BHSSI_T2RDELAY 0xf80000 | ||
1727 | #define BCONTXHSSI 0x400 | ||
1728 | #define BIGFROMCCK 0x200 | ||
1729 | #define BAGCADDRESS 0x3f | ||
1730 | #define BRXHPTX 0x7000 | ||
1731 | #define BRXHP2RX 0x38000 | ||
1732 | #define BRXHPCCKINI 0xc0000 | ||
1733 | #define BAGCTXCODE 0xc00000 | ||
1734 | #define BAGCRXCODE 0x300000 | ||
1735 | |||
1736 | #define B3WIREDATALENGTH 0x800 | ||
1737 | #define B3WIREADDREAALENGTH 0x400 | ||
1738 | |||
1739 | #define B3WIRERFPOWERDOWN 0x1 | ||
1740 | #define B5GPAPEPOLARITY 0x40000000 | ||
1741 | #define B2GPAPEPOLARITY 0x80000000 | ||
1742 | #define BRFSW_TXDEFAULTANT 0x3 | ||
1743 | #define BRFSW_TXOPTIONANT 0x30 | ||
1744 | #define BRFSW_RXDEFAULTANT 0x300 | ||
1745 | #define BRFSW_RXOPTIONANT 0x3000 | ||
1746 | #define BRFSI_3WIREDATA 0x1 | ||
1747 | #define BRFSI_3WIRECLOCK 0x2 | ||
1748 | #define BRFSI_3WIRELOAD 0x4 | ||
1749 | #define BRFSI_3WIRERW 0x8 | ||
1750 | #define BRFSI_3WIRE 0xf | ||
1751 | |||
1752 | #define BRFSI_RFENV 0x10 | ||
1753 | |||
1754 | #define BRFSI_TRSW 0x20 | ||
1755 | #define BRFSI_TRSWB 0x40 | ||
1756 | #define BRFSI_ANTSW 0x100 | ||
1757 | #define BRFSI_ANTSWB 0x200 | ||
1758 | #define BRFSI_PAPE 0x400 | ||
1759 | #define BRFSI_PAPE5G 0x800 | ||
1760 | #define BBANDSELECT 0x1 | ||
1761 | #define BHTSIG2_GI 0x80 | ||
1762 | #define BHTSIG2_SMOOTHING 0x01 | ||
1763 | #define BHTSIG2_SOUNDING 0x02 | ||
1764 | #define BHTSIG2_AGGREATON 0x08 | ||
1765 | #define BHTSIG2_STBC 0x30 | ||
1766 | #define BHTSIG2_ADVCODING 0x40 | ||
1767 | #define BHTSIG2_NUMOFHTLTF 0x300 | ||
1768 | #define BHTSIG2_CRC8 0x3fc | ||
1769 | #define BHTSIG1_MCS 0x7f | ||
1770 | #define BHTSIG1_BANDWIDTH 0x80 | ||
1771 | #define BHTSIG1_HTLENGTH 0xffff | ||
1772 | #define BLSIG_RATE 0xf | ||
1773 | #define BLSIG_RESERVED 0x10 | ||
1774 | #define BLSIG_LENGTH 0x1fffe | ||
1775 | #define BLSIG_PARITY 0x20 | ||
1776 | #define BCCKRXPHASE 0x4 | ||
1777 | |||
1778 | #define BLSSIREADADDRESS 0x7f800000 | ||
1779 | #define BLSSIREADEDGE 0x80000000 | ||
1780 | |||
1781 | #define BLSSIREADBACKDATA 0xfffff | ||
1782 | |||
1783 | #define BLSSIREADOKFLAG 0x1000 | ||
1784 | #define BCCKSAMPLERATE 0x8 | ||
1785 | #define BREGULATOR0STANDBY 0x1 | ||
1786 | #define BREGULATORPLLSTANDBY 0x2 | ||
1787 | #define BREGULATOR1STANDBY 0x4 | ||
1788 | #define BPLLPOWERUP 0x8 | ||
1789 | #define BDPLLPOWERUP 0x10 | ||
1790 | #define BDA10POWERUP 0x20 | ||
1791 | #define BAD7POWERUP 0x200 | ||
1792 | #define BDA6POWERUP 0x2000 | ||
1793 | #define BXTALPOWERUP 0x4000 | ||
1794 | #define B40MDCLKPOWERUP 0x8000 | ||
1795 | #define BDA6DEBUGMODE 0x20000 | ||
1796 | #define BDA6SWING 0x380000 | ||
1797 | |||
1798 | #define BADCLKPHASE 0x4000000 | ||
1799 | #define B80MCLKDELAY 0x18000000 | ||
1800 | #define BAFEWATCHDOGENABLE 0x20000000 | ||
1801 | |||
1802 | #define BXTALCAP01 0xc0000000 | ||
1803 | #define BXTALCAP23 0x3 | ||
1804 | #define BXTALCAP92X 0x0f000000 | ||
1805 | #define BXTALCAP 0x0f000000 | ||
1806 | |||
1807 | #define BINTDIFCLKENABLE 0x400 | ||
1808 | #define BEXTSIGCLKENABLE 0x800 | ||
1809 | #define BBANDGAP_MBIAS_POWERUP 0x10000 | ||
1810 | #define BAD11SH_GAIN 0xc0000 | ||
1811 | #define BAD11NPUT_RANGE 0x700000 | ||
1812 | #define BAD110P_CURRENT 0x3800000 | ||
1813 | #define BLPATH_LOOPBACK 0x4000000 | ||
1814 | #define BQPATH_LOOPBACK 0x8000000 | ||
1815 | #define BAFE_LOOPBACK 0x10000000 | ||
1816 | #define BDA10_SWING 0x7e0 | ||
1817 | #define BDA10_REVERSE 0x800 | ||
1818 | #define BDA_CLK_SOURCE 0x1000 | ||
1819 | #define BDA7INPUT_RANGE 0x6000 | ||
1820 | #define BDA7_GAIN 0x38000 | ||
1821 | #define BDA7OUTPUT_CM_MODE 0x40000 | ||
1822 | #define BDA7INPUT_CM_MODE 0x380000 | ||
1823 | #define BDA7CURRENT 0xc00000 | ||
1824 | #define BREGULATOR_ADJUST 0x7000000 | ||
1825 | #define BAD11POWERUP_ATTX 0x1 | ||
1826 | #define BDA10PS_ATTX 0x10 | ||
1827 | #define BAD11POWERUP_ATRX 0x100 | ||
1828 | #define BDA10PS_ATRX 0x1000 | ||
1829 | #define BCCKRX_AGC_FORMAT 0x200 | ||
1830 | #define BPSDFFT_SAMPLE_POINT 0xc000 | ||
1831 | #define BPSD_AVERAGE_NUM 0x3000 | ||
1832 | #define BIQPATH_CONTROL 0xc00 | ||
1833 | #define BPSD_FREQ 0x3ff | ||
1834 | #define BPSD_ANTENNA_PATH 0x30 | ||
1835 | #define BPSD_IQ_SWITCH 0x40 | ||
1836 | #define BPSD_RX_TRIGGER 0x400000 | ||
1837 | #define BPSD_TX_TRIGGERCW 0x80000000 | ||
1838 | #define BPSD_SINE_TONE_SCALE 0x7f000000 | ||
1839 | #define BPSD_REPORT 0xffff | ||
1840 | |||
1841 | #define BOFDM_TXSC 0x30000000 | ||
1842 | #define BCCK_TXON 0x1 | ||
1843 | #define BOFDM_TXON 0x2 | ||
1844 | #define BDEBUG_PAGE 0xfff | ||
1845 | #define BDEBUG_ITEM 0xff | ||
1846 | #define BANTL 0x10 | ||
1847 | #define BANT_NONHT 0x100 | ||
1848 | #define BANT_HT1 0x1000 | ||
1849 | #define BANT_HT2 0x10000 | ||
1850 | #define BANT_HT1S1 0x100000 | ||
1851 | #define BANT_NONHTS1 0x1000000 | ||
1852 | |||
1853 | #define BCCK_BBMODE 0x3 | ||
1854 | #define BCCK_TXPOWERSAVING 0x80 | ||
1855 | #define BCCK_RXPOWERSAVING 0x40 | ||
1856 | |||
1857 | #define BCCK_SIDEBAND 0x10 | ||
1858 | |||
1859 | #define BCCK_SCRAMBLE 0x8 | ||
1860 | #define BCCK_ANTDIVERSITY 0x8000 | ||
1861 | #define BCCK_CARRIER_RECOVERY 0x4000 | ||
1862 | #define BCCK_TXRATE 0x3000 | ||
1863 | #define BCCK_DCCANCEL 0x0800 | ||
1864 | #define BCCK_ISICANCEL 0x0400 | ||
1865 | #define BCCK_MATCH_FILTER 0x0200 | ||
1866 | #define BCCK_EQUALIZER 0x0100 | ||
1867 | #define BCCK_PREAMBLE_DETECT 0x800000 | ||
1868 | #define BCCK_FAST_FALSECCA 0x400000 | ||
1869 | #define BCCK_CH_ESTSTART 0x300000 | ||
1870 | #define BCCK_CCA_COUNT 0x080000 | ||
1871 | #define BCCK_CS_LIM 0x070000 | ||
1872 | #define BCCK_BIST_MODE 0x80000000 | ||
1873 | #define BCCK_CCAMASK 0x40000000 | ||
1874 | #define BCCK_TX_DAC_PHASE 0x4 | ||
1875 | #define BCCK_RX_ADC_PHASE 0x20000000 | ||
1876 | #define BCCKR_CP_MODE 0x0100 | ||
1877 | #define BCCK_TXDC_OFFSET 0xf0 | ||
1878 | #define BCCK_RXDC_OFFSET 0xf | ||
1879 | #define BCCK_CCA_MODE 0xc000 | ||
1880 | #define BCCK_FALSECS_LIM 0x3f00 | ||
1881 | #define BCCK_CS_RATIO 0xc00000 | ||
1882 | #define BCCK_CORGBIT_SEL 0x300000 | ||
1883 | #define BCCK_PD_LIM 0x0f0000 | ||
1884 | #define BCCK_NEWCCA 0x80000000 | ||
1885 | #define BCCK_RXHP_OF_IG 0x8000 | ||
1886 | #define BCCK_RXIG 0x7f00 | ||
1887 | #define BCCK_LNA_POLARITY 0x800000 | ||
1888 | #define BCCK_RX1ST_BAIN 0x7f0000 | ||
1889 | #define BCCK_RF_EXTEND 0x20000000 | ||
1890 | #define BCCK_RXAGC_SATLEVEL 0x1f000000 | ||
1891 | #define BCCK_RXAGC_SATCOUNT 0xe0 | ||
1892 | #define BCCKRXRFSETTLE 0x1f | ||
1893 | #define BCCK_FIXED_RXAGC 0x8000 | ||
1894 | #define BCCK_ANTENNA_POLARITY 0x2000 | ||
1895 | #define BCCK_TXFILTER_TYPE 0x0c00 | ||
1896 | #define BCCK_RXAGC_REPORTTYPE 0x0300 | ||
1897 | #define BCCK_RXDAGC_EN 0x80000000 | ||
1898 | #define BCCK_RXDAGC_PERIOD 0x20000000 | ||
1899 | #define BCCK_RXDAGC_SATLEVEL 0x1f000000 | ||
1900 | #define BCCK_TIMING_RECOVERY 0x800000 | ||
1901 | #define BCCK_TXC0 0x3f0000 | ||
1902 | #define BCCK_TXC1 0x3f000000 | ||
1903 | #define BCCK_TXC2 0x3f | ||
1904 | #define BCCK_TXC3 0x3f00 | ||
1905 | #define BCCK_TXC4 0x3f0000 | ||
1906 | #define BCCK_TXC5 0x3f000000 | ||
1907 | #define BCCK_TXC6 0x3f | ||
1908 | #define BCCK_TXC7 0x3f00 | ||
1909 | #define BCCK_DEBUGPORT 0xff0000 | ||
1910 | #define BCCK_DAC_DEBUG 0x0f000000 | ||
1911 | #define BCCK_FALSEALARM_ENABLE 0x8000 | ||
1912 | #define BCCK_FALSEALARM_READ 0x4000 | ||
1913 | #define BCCK_TRSSI 0x7f | ||
1914 | #define BCCK_RXAGC_REPORT 0xfe | ||
1915 | #define BCCK_RXREPORT_ANTSEL 0x80000000 | ||
1916 | #define BCCK_RXREPORT_MFOFF 0x40000000 | ||
1917 | #define BCCK_RXREPORT_SQLOSS 0x20000000 | ||
1918 | #define BCCK_RXREPORT_PKTLOSS 0x10000000 | ||
1919 | #define BCCK_RXREPORT_LOCKEDBIT 0x08000000 | ||
1920 | #define BCCK_RXREPORT_RATEERROR 0x04000000 | ||
1921 | #define BCCK_RXREPORT_RXRATE 0x03000000 | ||
1922 | #define BCCK_RXFA_COUNTER_LOWER 0xff | ||
1923 | #define BCCK_RXFA_COUNTER_UPPER 0xff000000 | ||
1924 | #define BCCK_RXHPAGC_START 0xe000 | ||
1925 | #define BCCK_RXHPAGC_FINAL 0x1c00 | ||
1926 | #define BCCK_RXFALSEALARM_ENABLE 0x8000 | ||
1927 | #define BCCK_FACOUNTER_FREEZE 0x4000 | ||
1928 | #define BCCK_TXPATH_SEL 0x10000000 | ||
1929 | #define BCCK_DEFAULT_RXPATH 0xc000000 | ||
1930 | #define BCCK_OPTION_RXPATH 0x3000000 | ||
1931 | |||
1932 | #define BNUM_OFSTF 0x3 | ||
1933 | #define BSHIFT_L 0xc0 | ||
1934 | #define BGI_TH 0xc | ||
1935 | #define BRXPATH_A 0x1 | ||
1936 | #define BRXPATH_B 0x2 | ||
1937 | #define BRXPATH_C 0x4 | ||
1938 | #define BRXPATH_D 0x8 | ||
1939 | #define BTXPATH_A 0x1 | ||
1940 | #define BTXPATH_B 0x2 | ||
1941 | #define BTXPATH_C 0x4 | ||
1942 | #define BTXPATH_D 0x8 | ||
1943 | #define BTRSSI_FREQ 0x200 | ||
1944 | #define BADC_BACKOFF 0x3000 | ||
1945 | #define BDFIR_BACKOFF 0xc000 | ||
1946 | #define BTRSSI_LATCH_PHASE 0x10000 | ||
1947 | #define BRX_LDC_OFFSET 0xff | ||
1948 | #define BRX_QDC_OFFSET 0xff00 | ||
1949 | #define BRX_DFIR_MODE 0x1800000 | ||
1950 | #define BRX_DCNF_TYPE 0xe000000 | ||
1951 | #define BRXIQIMB_A 0x3ff | ||
1952 | #define BRXIQIMB_B 0xfc00 | ||
1953 | #define BRXIQIMB_C 0x3f0000 | ||
1954 | #define BRXIQIMB_D 0xffc00000 | ||
1955 | #define BDC_DC_NOTCH 0x60000 | ||
1956 | #define BRXNB_NOTCH 0x1f000000 | ||
1957 | #define BPD_TH 0xf | ||
1958 | #define BPD_TH_OPT2 0xc000 | ||
1959 | #define BPWED_TH 0x700 | ||
1960 | #define BIFMF_WIN_L 0x800 | ||
1961 | #define BPD_OPTION 0x1000 | ||
1962 | #define BMF_WIN_L 0xe000 | ||
1963 | #define BBW_SEARCH_L 0x30000 | ||
1964 | #define BWIN_ENH_L 0xc0000 | ||
1965 | #define BBW_TH 0x700000 | ||
1966 | #define BED_TH2 0x3800000 | ||
1967 | #define BBW_OPTION 0x4000000 | ||
1968 | #define BRADIO_TH 0x18000000 | ||
1969 | #define BWINDOW_L 0xe0000000 | ||
1970 | #define BSBD_OPTION 0x1 | ||
1971 | #define BFRAME_TH 0x1c | ||
1972 | #define BFS_OPTION 0x60 | ||
1973 | #define BDC_SLOPE_CHECK 0x80 | ||
1974 | #define BFGUARD_COUNTER_DC_L 0xe00 | ||
1975 | #define BFRAME_WEIGHT_SHORT 0x7000 | ||
1976 | #define BSUB_TUNE 0xe00000 | ||
1977 | #define BFRAME_DC_LENGTH 0xe000000 | ||
1978 | #define BSBD_START_OFFSET 0x30000000 | ||
1979 | #define BFRAME_TH_2 0x7 | ||
1980 | #define BFRAME_GI2_TH 0x38 | ||
1981 | #define BGI2_SYNC_EN 0x40 | ||
1982 | #define BSARCH_SHORT_EARLY 0x300 | ||
1983 | #define BSARCH_SHORT_LATE 0xc00 | ||
1984 | #define BSARCH_GI2_LATE 0x70000 | ||
1985 | #define BCFOANTSUM 0x1 | ||
1986 | #define BCFOACC 0x2 | ||
1987 | #define BCFOSTARTOFFSET 0xc | ||
1988 | #define BCFOLOOPBACK 0x70 | ||
1989 | #define BCFOSUMWEIGHT 0x80 | ||
1990 | #define BDAGCENABLE 0x10000 | ||
1991 | #define BTXIQIMB_A 0x3ff | ||
1992 | #define BTXIQIMB_B 0xfc00 | ||
1993 | #define BTXIQIMB_C 0x3f0000 | ||
1994 | #define BTXIQIMB_D 0xffc00000 | ||
1995 | #define BTXIDCOFFSET 0xff | ||
1996 | #define BTXIQDCOFFSET 0xff00 | ||
1997 | #define BTXDFIRMODE 0x10000 | ||
1998 | #define BTXPESUDO_NOISEON 0x4000000 | ||
1999 | #define BTXPESUDO_NOISE_A 0xff | ||
2000 | #define BTXPESUDO_NOISE_B 0xff00 | ||
2001 | #define BTXPESUDO_NOISE_C 0xff0000 | ||
2002 | #define BTXPESUDO_NOISE_D 0xff000000 | ||
2003 | #define BCCA_DROPOPTION 0x20000 | ||
2004 | #define BCCA_DROPTHRES 0xfff00000 | ||
2005 | #define BEDCCA_H 0xf | ||
2006 | #define BEDCCA_L 0xf0 | ||
2007 | #define BLAMBDA_ED 0x300 | ||
2008 | #define BRX_INITIALGAIN 0x7f | ||
2009 | #define BRX_ANTDIV_EN 0x80 | ||
2010 | #define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 | ||
2011 | #define BRX_HIGHPOWER_FLOW 0x8000 | ||
2012 | #define BRX_AGC_FREEZE_THRES 0xc0000 | ||
2013 | #define BRX_FREEZESTEP_AGC1 0x300000 | ||
2014 | #define BRX_FREEZESTEP_AGC2 0xc00000 | ||
2015 | #define BRX_FREEZESTEP_AGC3 0x3000000 | ||
2016 | #define BRX_FREEZESTEP_AGC0 0xc000000 | ||
2017 | #define BRXRSSI_CMP_EN 0x10000000 | ||
2018 | #define BRXQUICK_AGCEN 0x20000000 | ||
2019 | #define BRXAGC_FREEZE_THRES_MODE 0x40000000 | ||
2020 | #define BRX_OVERFLOW_CHECKTYPE 0x80000000 | ||
2021 | #define BRX_AGCSHIFT 0x7f | ||
2022 | #define BTRSW_TRI_ONLY 0x80 | ||
2023 | #define BPOWER_THRES 0x300 | ||
2024 | #define BRXAGC_EN 0x1 | ||
2025 | #define BRXAGC_TOGETHER_EN 0x2 | ||
2026 | #define BRXAGC_MIN 0x4 | ||
2027 | #define BRXHP_INI 0x7 | ||
2028 | #define BRXHP_TRLNA 0x70 | ||
2029 | #define BRXHP_RSSI 0x700 | ||
2030 | #define BRXHP_BBP1 0x7000 | ||
2031 | #define BRXHP_BBP2 0x70000 | ||
2032 | #define BRXHP_BBP3 0x700000 | ||
2033 | #define BRSSI_H 0x7f0000 | ||
2034 | #define BRSSI_GEN 0x7f000000 | ||
2035 | #define BRXSETTLE_TRSW 0x7 | ||
2036 | #define BRXSETTLE_LNA 0x38 | ||
2037 | #define BRXSETTLE_RSSI 0x1c0 | ||
2038 | #define BRXSETTLE_BBP 0xe00 | ||
2039 | #define BRXSETTLE_RXHP 0x7000 | ||
2040 | #define BRXSETTLE_ANTSW_RSSI 0x38000 | ||
2041 | #define BRXSETTLE_ANTSW 0xc0000 | ||
2042 | #define BRXPROCESS_TIME_DAGC 0x300000 | ||
2043 | #define BRXSETTLE_HSSI 0x400000 | ||
2044 | #define BRXPROCESS_TIME_BBPPW 0x800000 | ||
2045 | #define BRXANTENNA_POWER_SHIFT 0x3000000 | ||
2046 | #define BRSSI_TABLE_SELECT 0xc000000 | ||
2047 | #define BRXHP_FINAL 0x7000000 | ||
2048 | #define BRXHPSETTLE_BBP 0x7 | ||
2049 | #define BRXHTSETTLE_HSSI 0x8 | ||
2050 | #define BRXHTSETTLE_RXHP 0x70 | ||
2051 | #define BRXHTSETTLE_BBPPW 0x80 | ||
2052 | #define BRXHTSETTLE_IDLE 0x300 | ||
2053 | #define BRXHTSETTLE_RESERVED 0x1c00 | ||
2054 | #define BRXHT_RXHP_EN 0x8000 | ||
2055 | #define BRXAGC_FREEZE_THRES 0x30000 | ||
2056 | #define BRXAGC_TOGETHEREN 0x40000 | ||
2057 | #define BRXHTAGC_MIN 0x80000 | ||
2058 | #define BRXHTAGC_EN 0x100000 | ||
2059 | #define BRXHTDAGC_EN 0x200000 | ||
2060 | #define BRXHT_RXHP_BBP 0x1c00000 | ||
2061 | #define BRXHT_RXHP_FINAL 0xe0000000 | ||
2062 | #define BRXPW_RADIO_TH 0x3 | ||
2063 | #define BRXPW_RADIO_EN 0x4 | ||
2064 | #define BRXMF_HOLD 0x3800 | ||
2065 | #define BRXPD_DELAY_TH1 0x38 | ||
2066 | #define BRXPD_DELAY_TH2 0x1c0 | ||
2067 | #define BRXPD_DC_COUNT_MAX 0x600 | ||
2068 | #define BRXPD_DELAY_TH 0x8000 | ||
2069 | #define BRXPROCESS_DELAY 0xf0000 | ||
2070 | #define BRXSEARCHRANGE_GI2_EARLY 0x700000 | ||
2071 | #define BRXFRAME_FUARD_COUNTER_L 0x3800000 | ||
2072 | #define BRXSGI_GUARD_L 0xc000000 | ||
2073 | #define BRXSGI_SEARCH_L 0x30000000 | ||
2074 | #define BRXSGI_TH 0xc0000000 | ||
2075 | #define BDFSCNT0 0xff | ||
2076 | #define BDFSCNT1 0xff00 | ||
2077 | #define BDFSFLAG 0xf0000 | ||
2078 | #define BMF_WEIGHT_SUM 0x300000 | ||
2079 | #define BMINIDX_TH 0x7f000000 | ||
2080 | #define BDAFORMAT 0x40000 | ||
2081 | #define BTXCH_EMU_ENABLE 0x01000000 | ||
2082 | #define BTRSW_ISOLATION_A 0x7f | ||
2083 | #define BTRSW_ISOLATION_B 0x7f00 | ||
2084 | #define BTRSW_ISOLATION_C 0x7f0000 | ||
2085 | #define BTRSW_ISOLATION_D 0x7f000000 | ||
2086 | #define BEXT_LNA_GAIN 0x7c00 | ||
2087 | |||
2088 | #define BSTBC_EN 0x4 | ||
2089 | #define BANTENNA_MAPPING 0x10 | ||
2090 | #define BNSS 0x20 | ||
2091 | #define BCFO_ANTSUM_ID 0x200 | ||
2092 | #define BPHY_COUNTER_RESET 0x8000000 | ||
2093 | #define BCFO_REPORT_GET 0x4000000 | ||
2094 | #define BOFDM_CONTINUE_TX 0x10000000 | ||
2095 | #define BOFDM_SINGLE_CARRIER 0x20000000 | ||
2096 | #define BOFDM_SINGLE_TONE 0x40000000 | ||
2097 | #define BHT_DETECT 0x100 | ||
2098 | #define BCFOEN 0x10000 | ||
2099 | #define BCFOVALUE 0xfff00000 | ||
2100 | #define BSIGTONE_RE 0x3f | ||
2101 | #define BSIGTONE_IM 0x7f00 | ||
2102 | #define BCOUNTER_CCA 0xffff | ||
2103 | #define BCOUNTER_PARITYFAIL 0xffff0000 | ||
2104 | #define BCOUNTER_RATEILLEGAL 0xffff | ||
2105 | #define BCOUNTER_CRC8FAIL 0xffff0000 | ||
2106 | #define BCOUNTER_MCSNOSUPPORT 0xffff | ||
2107 | #define BCOUNTER_FASTSYNC 0xffff | ||
2108 | #define BSHORTCFO 0xfff | ||
2109 | #define BSHORTCFOT_LENGTH 12 | ||
2110 | #define BSHORTCFOF_LENGTH 11 | ||
2111 | #define BLONGCFO 0x7ff | ||
2112 | #define BLONGCFOT_LENGTH 11 | ||
2113 | #define BLONGCFOF_LENGTH 11 | ||
2114 | #define BTAILCFO 0x1fff | ||
2115 | #define BTAILCFOT_LENGTH 13 | ||
2116 | #define BTAILCFOF_LENGTH 12 | ||
2117 | #define BNOISE_EN_PWDB 0xffff | ||
2118 | #define BCC_POWER_DB 0xffff0000 | ||
2119 | #define BMOISE_PWDB 0xffff | ||
2120 | #define BPOWERMEAST_LENGTH 10 | ||
2121 | #define BPOWERMEASF_LENGTH 3 | ||
2122 | #define BRX_HT_BW 0x1 | ||
2123 | #define BRXSC 0x6 | ||
2124 | #define BRX_HT 0x8 | ||
2125 | #define BNB_INTF_DET_ON 0x1 | ||
2126 | #define BINTF_WIN_LEN_CFG 0x30 | ||
2127 | #define BNB_INTF_TH_CFG 0x1c0 | ||
2128 | #define BRFGAIN 0x3f | ||
2129 | #define BTABLESEL 0x40 | ||
2130 | #define BTRSW 0x80 | ||
2131 | #define BRXSNR_A 0xff | ||
2132 | #define BRXSNR_B 0xff00 | ||
2133 | #define BRXSNR_C 0xff0000 | ||
2134 | #define BRXSNR_D 0xff000000 | ||
2135 | #define BSNR_EVMT_LENGTH 8 | ||
2136 | #define BSNR_EVMF_LENGTH 1 | ||
2137 | #define BCSI1ST 0xff | ||
2138 | #define BCSI2ND 0xff00 | ||
2139 | #define BRXEVM1ST 0xff0000 | ||
2140 | #define BRXEVM2ND 0xff000000 | ||
2141 | #define BSIGEVM 0xff | ||
2142 | #define BPWDB 0xff00 | ||
2143 | #define BSGIEN 0x10000 | ||
2144 | |||
2145 | #define BSFACTOR_QMA1 0xf | ||
2146 | #define BSFACTOR_QMA2 0xf0 | ||
2147 | #define BSFACTOR_QMA3 0xf00 | ||
2148 | #define BSFACTOR_QMA4 0xf000 | ||
2149 | #define BSFACTOR_QMA5 0xf0000 | ||
2150 | #define BSFACTOR_QMA6 0xf0000 | ||
2151 | #define BSFACTOR_QMA7 0xf00000 | ||
2152 | #define BSFACTOR_QMA8 0xf000000 | ||
2153 | #define BSFACTOR_QMA9 0xf0000000 | ||
2154 | #define BCSI_SCHEME 0x100000 | ||
2155 | |||
2156 | #define BNOISE_LVL_TOP_SET 0x3 | ||
2157 | #define BCHSMOOTH 0x4 | ||
2158 | #define BCHSMOOTH_CFG1 0x38 | ||
2159 | #define BCHSMOOTH_CFG2 0x1c0 | ||
2160 | #define BCHSMOOTH_CFG3 0xe00 | ||
2161 | #define BCHSMOOTH_CFG4 0x7000 | ||
2162 | #define BMRCMODE 0x800000 | ||
2163 | #define BTHEVMCFG 0x7000000 | ||
2164 | |||
2165 | #define BLOOP_FIT_TYPE 0x1 | ||
2166 | #define BUPD_CFO 0x40 | ||
2167 | #define BUPD_CFO_OFFDATA 0x80 | ||
2168 | #define BADV_UPD_CFO 0x100 | ||
2169 | #define BADV_TIME_CTRL 0x800 | ||
2170 | #define BUPD_CLKO 0x1000 | ||
2171 | #define BFC 0x6000 | ||
2172 | #define BTRACKING_MODE 0x8000 | ||
2173 | #define BPHCMP_ENABLE 0x10000 | ||
2174 | #define BUPD_CLKO_LTF 0x20000 | ||
2175 | #define BCOM_CH_CFO 0x40000 | ||
2176 | #define BCSI_ESTI_MODE 0x80000 | ||
2177 | #define BADV_UPD_EQZ 0x100000 | ||
2178 | #define BUCHCFG 0x7000000 | ||
2179 | #define BUPDEQZ 0x8000000 | ||
2180 | |||
2181 | #define BRX_PESUDO_NOISE_ON 0x20000000 | ||
2182 | #define BRX_PESUDO_NOISE_A 0xff | ||
2183 | #define BRX_PESUDO_NOISE_B 0xff00 | ||
2184 | #define BRX_PESUDO_NOISE_C 0xff0000 | ||
2185 | #define BRX_PESUDO_NOISE_D 0xff000000 | ||
2186 | #define BRX_PESUDO_NOISESTATE_A 0xffff | ||
2187 | #define BRX_PESUDO_NOISESTATE_B 0xffff0000 | ||
2188 | #define BRX_PESUDO_NOISESTATE_C 0xffff | ||
2189 | #define BRX_PESUDO_NOISESTATE_D 0xffff0000 | ||
2190 | |||
2191 | #define BZEBRA1_HSSIENABLE 0x8 | ||
2192 | #define BZEBRA1_TRXCONTROL 0xc00 | ||
2193 | #define BZEBRA1_TRXGAINSETTING 0x07f | ||
2194 | #define BZEBRA1_RXCOUNTER 0xc00 | ||
2195 | #define BZEBRA1_TXCHANGEPUMP 0x38 | ||
2196 | #define BZEBRA1_RXCHANGEPUMP 0x7 | ||
2197 | #define BZEBRA1_CHANNEL_NUM 0xf80 | ||
2198 | #define BZEBRA1_TXLPFBW 0x400 | ||
2199 | #define BZEBRA1_RXLPFBW 0x600 | ||
2200 | |||
2201 | #define BRTL8256REG_MODE_CTRL1 0x100 | ||
2202 | #define BRTL8256REG_MODE_CTRL0 0x40 | ||
2203 | #define BRTL8256REG_TXLPFBW 0x18 | ||
2204 | #define BRTL8256REG_RXLPFBW 0x600 | ||
2205 | |||
2206 | #define BRTL8258_TXLPFBW 0xc | ||
2207 | #define BRTL8258_RXLPFBW 0xc00 | ||
2208 | #define BRTL8258_RSSILPFBW 0xc0 | ||
2209 | |||
2210 | #define BBYTE0 0x1 | ||
2211 | #define BBYTE1 0x2 | ||
2212 | #define BBYTE2 0x4 | ||
2213 | #define BBYTE3 0x8 | ||
2214 | #define BWORD0 0x3 | ||
2215 | #define BWORD1 0xc | ||
2216 | #define BWORD 0xf | ||
2217 | |||
2218 | #define MASKBYTE0 0xff | ||
2219 | #define MASKBYTE1 0xff00 | ||
2220 | #define MASKBYTE2 0xff0000 | ||
2221 | #define MASKBYTE3 0xff000000 | ||
2222 | #define MASKHWORD 0xffff0000 | ||
2223 | #define MASKLWORD 0x0000ffff | ||
2224 | #define MASKDWORD 0xffffffff | ||
2225 | #define MASK12BITS 0xfff | ||
2226 | #define MASKH4BITS 0xf0000000 | ||
2227 | #define MASKOFDM_D 0xffc00000 | ||
2228 | #define MASKCCK 0x3f3f3f3f | ||
2229 | |||
2230 | #define MASK4BITS 0x0f | ||
2231 | #define MASK20BITS 0xfffff | ||
2232 | #define RFREG_OFFSET_MASK 0xfffff | ||
2233 | |||
2234 | #define BENABLE 0x1 | ||
2235 | #define BDISABLE 0x0 | ||
2236 | |||
2237 | #define LEFT_ANTENNA 0x0 | ||
2238 | #define RIGHT_ANTENNA 0x1 | ||
2239 | |||
2240 | #define TCHECK_TXSTATUS 500 | ||
2241 | #define TUPDATE_RXCOUNTER 100 | ||
2242 | |||
2243 | #define REG_UN_USED_REGISTER 0x01bf | ||
2244 | |||
2245 | /* WOL bit information */ | ||
2246 | #define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0) | ||
2247 | #define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1) | ||
2248 | #define HAL92C_WOL_DISASSOC_EVENT BIT(2) | ||
2249 | #define HAL92C_WOL_DEAUTH_EVENT BIT(3) | ||
2250 | #define HAL92C_WOL_FW_DISCONNECT_EVENT BIT(4) | ||
2251 | |||
2252 | #define WOL_REASON_PTK_UPDATE BIT(0) | ||
2253 | #define WOL_REASON_GTK_UPDATE BIT(1) | ||
2254 | #define WOL_REASON_DISASSOC BIT(2) | ||
2255 | #define WOL_REASON_DEAUTH BIT(3) | ||
2256 | #define WOL_REASON_FW_DISCONNECT BIT(4) | ||
2257 | |||
2258 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c new file mode 100644 index 000000000000..4faafdbab9c6 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c | |||
@@ -0,0 +1,467 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "reg.h" | ||
32 | #include "def.h" | ||
33 | #include "phy.h" | ||
34 | #include "rf.h" | ||
35 | #include "dm.h" | ||
36 | |||
37 | void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) | ||
38 | { | ||
39 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
40 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
41 | |||
42 | switch (bandwidth) { | ||
43 | case HT_CHANNEL_WIDTH_20: | ||
44 | rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & | ||
45 | 0xfffff3ff) | BIT(10) | BIT(11)); | ||
46 | rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, | ||
47 | rtlphy->rfreg_chnlval[0]); | ||
48 | break; | ||
49 | case HT_CHANNEL_WIDTH_20_40: | ||
50 | rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & | ||
51 | 0xfffff3ff) | BIT(10)); | ||
52 | rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, | ||
53 | rtlphy->rfreg_chnlval[0]); | ||
54 | break; | ||
55 | default: | ||
56 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
57 | "unknown bandwidth: %#X\n", bandwidth); | ||
58 | break; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | ||
63 | u8 *plevel) | ||
64 | { | ||
65 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
66 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
67 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
68 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
69 | u32 tx_agc[2] = {0, 0}, tmpval; | ||
70 | bool turbo_scanoff = false; | ||
71 | u8 idx1, idx2; | ||
72 | u8 *ptr; | ||
73 | u8 direction; | ||
74 | u32 pwrtrac_value; | ||
75 | |||
76 | if (rtlefuse->eeprom_regulatory != 0) | ||
77 | turbo_scanoff = true; | ||
78 | |||
79 | if (mac->act_scanning == true) { | ||
80 | tx_agc[RF90_PATH_A] = 0x3f3f3f3f; | ||
81 | tx_agc[RF90_PATH_B] = 0x3f3f3f3f; | ||
82 | |||
83 | if (turbo_scanoff) { | ||
84 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | ||
85 | tx_agc[idx1] = plevel[idx1] | | ||
86 | (plevel[idx1] << 8) | | ||
87 | (plevel[idx1] << 16) | | ||
88 | (plevel[idx1] << 24); | ||
89 | } | ||
90 | } | ||
91 | } else { | ||
92 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | ||
93 | tx_agc[idx1] = plevel[idx1] | (plevel[idx1] << 8) | | ||
94 | (plevel[idx1] << 16) | | ||
95 | (plevel[idx1] << 24); | ||
96 | } | ||
97 | |||
98 | if (rtlefuse->eeprom_regulatory == 0) { | ||
99 | tmpval = (rtlphy->mcs_offset[0][6]) + | ||
100 | (rtlphy->mcs_offset[0][7] << 8); | ||
101 | tx_agc[RF90_PATH_A] += tmpval; | ||
102 | |||
103 | tmpval = (rtlphy->mcs_offset[0][14]) + | ||
104 | (rtlphy->mcs_offset[0][15] << 24); | ||
105 | tx_agc[RF90_PATH_B] += tmpval; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | ||
110 | ptr = (u8 *)(&(tx_agc[idx1])); | ||
111 | for (idx2 = 0; idx2 < 4; idx2++) { | ||
112 | if (*ptr > RF6052_MAX_TX_PWR) | ||
113 | *ptr = RF6052_MAX_TX_PWR; | ||
114 | ptr++; | ||
115 | } | ||
116 | } | ||
117 | rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); | ||
118 | if (direction == 1) { | ||
119 | tx_agc[0] += pwrtrac_value; | ||
120 | tx_agc[1] += pwrtrac_value; | ||
121 | } else if (direction == 2) { | ||
122 | tx_agc[0] -= pwrtrac_value; | ||
123 | tx_agc[1] -= pwrtrac_value; | ||
124 | } | ||
125 | tmpval = tx_agc[RF90_PATH_A] & 0xff; | ||
126 | rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); | ||
127 | |||
128 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
129 | "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, | ||
130 | RTXAGC_A_CCK1_MCS32); | ||
131 | |||
132 | tmpval = tx_agc[RF90_PATH_A] >> 8; | ||
133 | |||
134 | rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); | ||
135 | |||
136 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
137 | "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, | ||
138 | RTXAGC_B_CCK11_A_CCK2_11); | ||
139 | |||
140 | tmpval = tx_agc[RF90_PATH_B] >> 24; | ||
141 | rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); | ||
142 | |||
143 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
144 | "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, | ||
145 | RTXAGC_B_CCK11_A_CCK2_11); | ||
146 | |||
147 | tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; | ||
148 | rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); | ||
149 | |||
150 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
151 | "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, | ||
152 | RTXAGC_B_CCK1_55_MCS32); | ||
153 | } | ||
154 | |||
155 | static void rtl88e_phy_get_power_base(struct ieee80211_hw *hw, | ||
156 | u8 *pwrlvlofdm, u8 *pwrlvlbw20, | ||
157 | u8 *pwrlvlbw40, u8 channel, | ||
158 | u32 *ofdmbase, u32 *mcsbase) | ||
159 | { | ||
160 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
161 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
162 | u32 base0, base1; | ||
163 | u8 i, powerlevel[2]; | ||
164 | |||
165 | for (i = 0; i < 2; i++) { | ||
166 | base0 = pwrlvlofdm[i]; | ||
167 | |||
168 | base0 = (base0 << 24) | (base0 << 16) | | ||
169 | (base0 << 8) | base0; | ||
170 | *(ofdmbase + i) = base0; | ||
171 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
172 | "[OFDM power base index rf(%c) = 0x%x]\n", | ||
173 | ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); | ||
174 | } | ||
175 | |||
176 | for (i = 0; i < 2; i++) { | ||
177 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) | ||
178 | powerlevel[i] = pwrlvlbw20[i]; | ||
179 | else | ||
180 | powerlevel[i] = pwrlvlbw40[i]; | ||
181 | base1 = powerlevel[i]; | ||
182 | base1 = (base1 << 24) | | ||
183 | (base1 << 16) | (base1 << 8) | base1; | ||
184 | |||
185 | *(mcsbase + i) = base1; | ||
186 | |||
187 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
188 | "[MCS power base index rf(%c) = 0x%x]\n", | ||
189 | ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | static void get_txpwr_by_reg(struct ieee80211_hw *hw, u8 chan, u8 index, | ||
194 | u32 *base0, u32 *base1, u32 *outval) | ||
195 | { | ||
196 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
197 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
198 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
199 | u8 i, chg = 0, pwr_lim[4], pwr_diff = 0, cust_pwr_dif; | ||
200 | u32 writeval, cust_lim, rf, tmp; | ||
201 | u8 ch = chan - 1; | ||
202 | u8 j; | ||
203 | |||
204 | for (rf = 0; rf < 2; rf++) { | ||
205 | j = index + (rf ? 8 : 0); | ||
206 | tmp = ((index < 2) ? base0[rf] : base1[rf]); | ||
207 | switch (rtlefuse->eeprom_regulatory) { | ||
208 | case 0: | ||
209 | chg = 0; | ||
210 | |||
211 | writeval = rtlphy->mcs_offset[chg][j] + tmp; | ||
212 | |||
213 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
214 | "RTK better performance, " | ||
215 | "writeval(%c) = 0x%x\n", | ||
216 | ((rf == 0) ? 'A' : 'B'), writeval); | ||
217 | break; | ||
218 | case 1: | ||
219 | if (rtlphy->pwrgroup_cnt == 1) { | ||
220 | chg = 0; | ||
221 | } else { | ||
222 | chg = chan / 3; | ||
223 | if (chan == 14) | ||
224 | chg = 5; | ||
225 | } | ||
226 | writeval = rtlphy->mcs_offset[chg][j] + tmp; | ||
227 | |||
228 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
229 | "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", | ||
230 | ((rf == 0) ? 'A' : 'B'), writeval); | ||
231 | break; | ||
232 | case 2: | ||
233 | writeval = ((index < 2) ? base0[rf] : base1[rf]); | ||
234 | |||
235 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
236 | "Better regulatory, writeval(%c) = 0x%x\n", | ||
237 | ((rf == 0) ? 'A' : 'B'), writeval); | ||
238 | break; | ||
239 | case 3: | ||
240 | chg = 0; | ||
241 | |||
242 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { | ||
243 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
244 | "customer's limit, 40MHz rf(%c) = 0x%x\n", | ||
245 | ((rf == 0) ? 'A' : 'B'), | ||
246 | rtlefuse->pwrgroup_ht40[rf][ch]); | ||
247 | } else { | ||
248 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
249 | "customer's limit, 20MHz rf(%c) = 0x%x\n", | ||
250 | ((rf == 0) ? 'A' : 'B'), | ||
251 | rtlefuse->pwrgroup_ht20[rf][ch]); | ||
252 | } | ||
253 | |||
254 | if (index < 2) | ||
255 | pwr_diff = rtlefuse->txpwr_legacyhtdiff[rf][ch]; | ||
256 | else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) | ||
257 | pwr_diff = rtlefuse->txpwr_ht20diff[rf][ch]; | ||
258 | |||
259 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) | ||
260 | cust_pwr_dif = rtlefuse->pwrgroup_ht40[rf][ch]; | ||
261 | else | ||
262 | cust_pwr_dif = rtlefuse->pwrgroup_ht20[rf][ch]; | ||
263 | |||
264 | if (pwr_diff > cust_pwr_dif) | ||
265 | pwr_diff = 0; | ||
266 | else | ||
267 | pwr_diff = cust_pwr_dif - pwr_diff; | ||
268 | |||
269 | for (i = 0; i < 4; i++) { | ||
270 | pwr_lim[i] = (u8)((rtlphy->mcs_offset[chg][j] & | ||
271 | (0x7f << (i * 8))) >> (i * 8)); | ||
272 | |||
273 | if (pwr_lim[i] > pwr_diff) | ||
274 | pwr_lim[i] = pwr_diff; | ||
275 | } | ||
276 | |||
277 | cust_lim = (pwr_lim[3] << 24) | (pwr_lim[2] << 16) | | ||
278 | (pwr_lim[1] << 8) | (pwr_lim[0]); | ||
279 | |||
280 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
281 | "Customer's limit rf(%c) = 0x%x\n", | ||
282 | ((rf == 0) ? 'A' : 'B'), cust_lim); | ||
283 | |||
284 | writeval = cust_lim + tmp; | ||
285 | |||
286 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
287 | "Customer, writeval rf(%c) = 0x%x\n", | ||
288 | ((rf == 0) ? 'A' : 'B'), writeval); | ||
289 | break; | ||
290 | default: | ||
291 | chg = 0; | ||
292 | writeval = rtlphy->mcs_offset[chg][j] + tmp; | ||
293 | |||
294 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
295 | "RTK better performance, writeval " | ||
296 | "rf(%c) = 0x%x\n", | ||
297 | ((rf == 0) ? 'A' : 'B'), writeval); | ||
298 | break; | ||
299 | } | ||
300 | |||
301 | if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) | ||
302 | writeval = writeval - 0x06060606; | ||
303 | else if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
304 | TXHIGHPWRLEVEL_BT2) | ||
305 | writeval -= 0x0c0c0c0c; | ||
306 | *(outval + rf) = writeval; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static void write_ofdm_pwr(struct ieee80211_hw *hw, u8 index, u32 *pvalue) | ||
311 | { | ||
312 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
313 | u16 regoffset_a[6] = { | ||
314 | RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, | ||
315 | RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, | ||
316 | RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 | ||
317 | }; | ||
318 | u16 regoffset_b[6] = { | ||
319 | RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, | ||
320 | RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, | ||
321 | RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 | ||
322 | }; | ||
323 | u8 i, rf, pwr_val[4]; | ||
324 | u32 writeval; | ||
325 | u16 regoffset; | ||
326 | |||
327 | for (rf = 0; rf < 2; rf++) { | ||
328 | writeval = pvalue[rf]; | ||
329 | for (i = 0; i < 4; i++) { | ||
330 | pwr_val[i] = (u8) ((writeval & (0x7f << | ||
331 | (i * 8))) >> (i * 8)); | ||
332 | |||
333 | if (pwr_val[i] > RF6052_MAX_TX_PWR) | ||
334 | pwr_val[i] = RF6052_MAX_TX_PWR; | ||
335 | } | ||
336 | writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | | ||
337 | (pwr_val[1] << 8) | pwr_val[0]; | ||
338 | |||
339 | if (rf == 0) | ||
340 | regoffset = regoffset_a[index]; | ||
341 | else | ||
342 | regoffset = regoffset_b[index]; | ||
343 | rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); | ||
344 | |||
345 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
346 | "Set 0x%x = %08x\n", regoffset, writeval); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, | ||
351 | u8 *pwrlvlofdm, | ||
352 | u8 *pwrlvlbw20, | ||
353 | u8 *pwrlvlbw40, u8 chan) | ||
354 | { | ||
355 | u32 writeval[2], base0[2], base1[2]; | ||
356 | u8 index; | ||
357 | u8 direction; | ||
358 | u32 pwrtrac_value; | ||
359 | |||
360 | rtl88e_phy_get_power_base(hw, pwrlvlofdm, pwrlvlbw20, | ||
361 | pwrlvlbw40, chan, &base0[0], | ||
362 | &base1[0]); | ||
363 | |||
364 | rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); | ||
365 | |||
366 | for (index = 0; index < 6; index++) { | ||
367 | get_txpwr_by_reg(hw, chan, index, &base0[0], &base1[0], | ||
368 | &writeval[0]); | ||
369 | if (direction == 1) { | ||
370 | writeval[0] += pwrtrac_value; | ||
371 | writeval[1] += pwrtrac_value; | ||
372 | } else if (direction == 2) { | ||
373 | writeval[0] -= pwrtrac_value; | ||
374 | writeval[1] -= pwrtrac_value; | ||
375 | } | ||
376 | write_ofdm_pwr(hw, index, &writeval[0]); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | static bool rf6052_conf_para(struct ieee80211_hw *hw) | ||
381 | { | ||
382 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
383 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
384 | u32 u4val = 0; | ||
385 | u8 rfpath; | ||
386 | bool rtstatus = true; | ||
387 | struct bb_reg_def *pphyreg; | ||
388 | |||
389 | for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { | ||
390 | pphyreg = &rtlphy->phyreg_def[rfpath]; | ||
391 | |||
392 | switch (rfpath) { | ||
393 | case RF90_PATH_A: | ||
394 | case RF90_PATH_C: | ||
395 | u4val = rtl_get_bbreg(hw, pphyreg->rfintfs, | ||
396 | BRFSI_RFENV); | ||
397 | break; | ||
398 | case RF90_PATH_B: | ||
399 | case RF90_PATH_D: | ||
400 | u4val = rtl_get_bbreg(hw, pphyreg->rfintfs, | ||
401 | BRFSI_RFENV << 16); | ||
402 | break; | ||
403 | } | ||
404 | |||
405 | rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); | ||
406 | udelay(1); | ||
407 | |||
408 | rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); | ||
409 | udelay(1); | ||
410 | |||
411 | rtl_set_bbreg(hw, pphyreg->rfhssi_para2, | ||
412 | B3WIREADDREAALENGTH, 0x0); | ||
413 | udelay(1); | ||
414 | |||
415 | rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); | ||
416 | udelay(1); | ||
417 | |||
418 | switch (rfpath) { | ||
419 | case RF90_PATH_A: | ||
420 | rtstatus = rtl88e_phy_config_rf_with_headerfile(hw, | ||
421 | (enum radio_path)rfpath); | ||
422 | break; | ||
423 | case RF90_PATH_B: | ||
424 | rtstatus = rtl88e_phy_config_rf_with_headerfile(hw, | ||
425 | (enum radio_path)rfpath); | ||
426 | break; | ||
427 | case RF90_PATH_C: | ||
428 | break; | ||
429 | case RF90_PATH_D: | ||
430 | break; | ||
431 | } | ||
432 | |||
433 | switch (rfpath) { | ||
434 | case RF90_PATH_A: | ||
435 | case RF90_PATH_C: | ||
436 | rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, u4val); | ||
437 | break; | ||
438 | case RF90_PATH_B: | ||
439 | case RF90_PATH_D: | ||
440 | rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16, | ||
441 | u4val); | ||
442 | break; | ||
443 | } | ||
444 | |||
445 | if (rtstatus != true) { | ||
446 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
447 | "Radio[%d] Fail!!", rfpath); | ||
448 | return false; | ||
449 | } | ||
450 | } | ||
451 | |||
452 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); | ||
453 | return rtstatus; | ||
454 | } | ||
455 | |||
456 | bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw) | ||
457 | { | ||
458 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
459 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
460 | |||
461 | if (rtlphy->rf_type == RF_1T1R) | ||
462 | rtlphy->num_total_rfpath = 1; | ||
463 | else | ||
464 | rtlphy->num_total_rfpath = 2; | ||
465 | |||
466 | return rf6052_conf_para(hw); | ||
467 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h new file mode 100644 index 000000000000..a39a2a3dbcc9 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92C_RF_H__ | ||
31 | #define __RTL92C_RF_H__ | ||
32 | |||
33 | #define RF6052_MAX_TX_PWR 0x3F | ||
34 | #define RF6052_MAX_REG 0x3F | ||
35 | |||
36 | void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, | ||
37 | u8 bandwidth); | ||
38 | void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | ||
39 | u8 *ppowerlevel); | ||
40 | void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, | ||
41 | u8 *ppowerlevel_ofdm, | ||
42 | u8 *ppowerlevel_bw20, | ||
43 | u8 *ppowerlevel_bw40, u8 channel); | ||
44 | bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw); | ||
45 | |||
46 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c new file mode 100644 index 000000000000..c254693a1e6a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c | |||
@@ -0,0 +1,400 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../core.h" | ||
32 | #include "../pci.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "phy.h" | ||
36 | #include "dm.h" | ||
37 | #include "hw.h" | ||
38 | #include "sw.h" | ||
39 | #include "trx.h" | ||
40 | #include "led.h" | ||
41 | #include "table.h" | ||
42 | |||
43 | #include <linux/vmalloc.h> | ||
44 | #include <linux/module.h> | ||
45 | |||
46 | static void rtl88e_init_aspm_vars(struct ieee80211_hw *hw) | ||
47 | { | ||
48 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
49 | |||
50 | /*close ASPM for AMD defaultly */ | ||
51 | rtlpci->const_amdpci_aspm = 0; | ||
52 | |||
53 | /* ASPM PS mode. | ||
54 | * 0 - Disable ASPM, | ||
55 | * 1 - Enable ASPM without Clock Req, | ||
56 | * 2 - Enable ASPM with Clock Req, | ||
57 | * 3 - Alwyas Enable ASPM with Clock Req, | ||
58 | * 4 - Always Enable ASPM without Clock Req. | ||
59 | * set defult to RTL8192CE:3 RTL8192E:2 | ||
60 | */ | ||
61 | rtlpci->const_pci_aspm = 3; | ||
62 | |||
63 | /*Setting for PCI-E device */ | ||
64 | rtlpci->const_devicepci_aspm_setting = 0x03; | ||
65 | |||
66 | /*Setting for PCI-E bridge */ | ||
67 | rtlpci->const_hostpci_aspm_setting = 0x02; | ||
68 | |||
69 | /* In Hw/Sw Radio Off situation. | ||
70 | * 0 - Default, | ||
71 | * 1 - From ASPM setting without low Mac Pwr, | ||
72 | * 2 - From ASPM setting with low Mac Pwr, | ||
73 | * 3 - Bus D3 | ||
74 | * set default to RTL8192CE:0 RTL8192SE:2 | ||
75 | */ | ||
76 | rtlpci->const_hwsw_rfoff_d3 = 0; | ||
77 | |||
78 | /* This setting works for those device with | ||
79 | * backdoor ASPM setting such as EPHY setting. | ||
80 | * 0 - Not support ASPM, | ||
81 | * 1 - Support ASPM, | ||
82 | * 2 - According to chipset. | ||
83 | */ | ||
84 | rtlpci->const_support_pciaspm = 1; | ||
85 | } | ||
86 | |||
87 | int rtl88e_init_sw_vars(struct ieee80211_hw *hw) | ||
88 | { | ||
89 | int err = 0; | ||
90 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
91 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
92 | u8 tid; | ||
93 | |||
94 | rtl8188ee_bt_reg_init(hw); | ||
95 | |||
96 | rtlpriv->dm.dm_initialgain_enable = 1; | ||
97 | rtlpriv->dm.dm_flag = 0; | ||
98 | rtlpriv->dm.disable_framebursting = 0; | ||
99 | rtlpriv->dm.thermalvalue = 0; | ||
100 | rtlpci->transmit_config = CFENDFORM | BIT(15); | ||
101 | |||
102 | /* compatible 5G band 88ce just 2.4G band & smsp */ | ||
103 | rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; | ||
104 | rtlpriv->rtlhal.bandset = BAND_ON_2_4G; | ||
105 | rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; | ||
106 | |||
107 | rtlpci->receive_config = (RCR_APPFCS | | ||
108 | RCR_APP_MIC | | ||
109 | RCR_APP_ICV | | ||
110 | RCR_APP_PHYST_RXFF | | ||
111 | RCR_HTC_LOC_CTRL | | ||
112 | RCR_AMF | | ||
113 | RCR_ACF | | ||
114 | RCR_ADF | | ||
115 | RCR_AICV | | ||
116 | RCR_ACRC32 | | ||
117 | RCR_AB | | ||
118 | RCR_AM | | ||
119 | RCR_APM | | ||
120 | 0); | ||
121 | |||
122 | rtlpci->irq_mask[0] = | ||
123 | (u32) (IMR_PSTIMEOUT | | ||
124 | IMR_HSISR_IND_ON_INT | | ||
125 | IMR_C2HCMD | | ||
126 | IMR_HIGHDOK | | ||
127 | IMR_MGNTDOK | | ||
128 | IMR_BKDOK | | ||
129 | IMR_BEDOK | | ||
130 | IMR_VIDOK | | ||
131 | IMR_VODOK | | ||
132 | IMR_RDU | | ||
133 | IMR_ROK | | ||
134 | 0); | ||
135 | rtlpci->irq_mask[1] = (u32) (IMR_RXFOVW | 0); | ||
136 | rtlpci->sys_irq_mask = (u32) (HSIMR_PDN_INT_EN | HSIMR_RON_INT_EN); | ||
137 | |||
138 | /* for debug level */ | ||
139 | rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; | ||
140 | /* for LPS & IPS */ | ||
141 | rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; | ||
142 | rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; | ||
143 | rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; | ||
144 | if (!rtlpriv->psc.inactiveps) | ||
145 | pr_info("rtl8188ee: Power Save off (module option)\n"); | ||
146 | if (!rtlpriv->psc.fwctrl_lps) | ||
147 | pr_info("rtl8188ee: FW Power Save off (module option)\n"); | ||
148 | rtlpriv->psc.reg_fwctrl_lps = 3; | ||
149 | rtlpriv->psc.reg_max_lps_awakeintvl = 5; | ||
150 | /* for ASPM, you can close aspm through | ||
151 | * set const_support_pciaspm = 0 | ||
152 | */ | ||
153 | rtl88e_init_aspm_vars(hw); | ||
154 | |||
155 | if (rtlpriv->psc.reg_fwctrl_lps == 1) | ||
156 | rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; | ||
157 | else if (rtlpriv->psc.reg_fwctrl_lps == 2) | ||
158 | rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; | ||
159 | else if (rtlpriv->psc.reg_fwctrl_lps == 3) | ||
160 | rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; | ||
161 | |||
162 | /* for firmware buf */ | ||
163 | rtlpriv->rtlhal.pfirmware = vmalloc(0x8000); | ||
164 | if (!rtlpriv->rtlhal.pfirmware) { | ||
165 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
166 | "Can't alloc buffer for fw.\n"); | ||
167 | return 1; | ||
168 | } | ||
169 | |||
170 | rtlpriv->cfg->fw_name = "rtlwifi/rtl8188efw.bin"; | ||
171 | rtlpriv->max_fw_size = 0x8000; | ||
172 | pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); | ||
173 | err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, | ||
174 | rtlpriv->io.dev, GFP_KERNEL, hw, | ||
175 | rtl_fw_cb); | ||
176 | if (err) { | ||
177 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
178 | "Failed to request firmware!\n"); | ||
179 | return 1; | ||
180 | } | ||
181 | |||
182 | /* for early mode */ | ||
183 | rtlpriv->rtlhal.earlymode_enable = false; | ||
184 | rtlpriv->rtlhal.max_earlymode_num = 10; | ||
185 | for (tid = 0; tid < 8; tid++) | ||
186 | skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); | ||
187 | |||
188 | /*low power */ | ||
189 | rtlpriv->psc.low_power_enable = false; | ||
190 | if (rtlpriv->psc.low_power_enable) { | ||
191 | init_timer(&rtlpriv->works.fw_clockoff_timer); | ||
192 | setup_timer(&rtlpriv->works.fw_clockoff_timer, | ||
193 | rtl88ee_fw_clk_off_timer_callback, | ||
194 | (unsigned long)hw); | ||
195 | } | ||
196 | |||
197 | init_timer(&rtlpriv->works.fast_antenna_training_timer); | ||
198 | setup_timer(&rtlpriv->works.fast_antenna_training_timer, | ||
199 | rtl88e_dm_fast_antenna_training_callback, | ||
200 | (unsigned long)hw); | ||
201 | return err; | ||
202 | } | ||
203 | |||
204 | void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw) | ||
205 | { | ||
206 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
207 | |||
208 | if (rtlpriv->rtlhal.pfirmware) { | ||
209 | vfree(rtlpriv->rtlhal.pfirmware); | ||
210 | rtlpriv->rtlhal.pfirmware = NULL; | ||
211 | } | ||
212 | |||
213 | if (rtlpriv->psc.low_power_enable) | ||
214 | del_timer_sync(&rtlpriv->works.fw_clockoff_timer); | ||
215 | |||
216 | del_timer_sync(&rtlpriv->works.fast_antenna_training_timer); | ||
217 | } | ||
218 | |||
219 | static struct rtl_hal_ops rtl8188ee_hal_ops = { | ||
220 | .init_sw_vars = rtl88e_init_sw_vars, | ||
221 | .deinit_sw_vars = rtl88e_deinit_sw_vars, | ||
222 | .read_eeprom_info = rtl88ee_read_eeprom_info, | ||
223 | .interrupt_recognized = rtl88ee_interrupt_recognized,/*need check*/ | ||
224 | .hw_init = rtl88ee_hw_init, | ||
225 | .hw_disable = rtl88ee_card_disable, | ||
226 | .hw_suspend = rtl88ee_suspend, | ||
227 | .hw_resume = rtl88ee_resume, | ||
228 | .enable_interrupt = rtl88ee_enable_interrupt, | ||
229 | .disable_interrupt = rtl88ee_disable_interrupt, | ||
230 | .set_network_type = rtl88ee_set_network_type, | ||
231 | .set_chk_bssid = rtl88ee_set_check_bssid, | ||
232 | .set_qos = rtl88ee_set_qos, | ||
233 | .set_bcn_reg = rtl88ee_set_beacon_related_registers, | ||
234 | .set_bcn_intv = rtl88ee_set_beacon_interval, | ||
235 | .update_interrupt_mask = rtl88ee_update_interrupt_mask, | ||
236 | .get_hw_reg = rtl88ee_get_hw_reg, | ||
237 | .set_hw_reg = rtl88ee_set_hw_reg, | ||
238 | .update_rate_tbl = rtl88ee_update_hal_rate_tbl, | ||
239 | .fill_tx_desc = rtl88ee_tx_fill_desc, | ||
240 | .fill_tx_cmddesc = rtl88ee_tx_fill_cmddesc, | ||
241 | .query_rx_desc = rtl88ee_rx_query_desc, | ||
242 | .set_channel_access = rtl88ee_update_channel_access_setting, | ||
243 | .radio_onoff_checking = rtl88ee_gpio_radio_on_off_checking, | ||
244 | .set_bw_mode = rtl88e_phy_set_bw_mode, | ||
245 | .switch_channel = rtl88e_phy_sw_chnl, | ||
246 | .dm_watchdog = rtl88e_dm_watchdog, | ||
247 | .scan_operation_backup = rtl88e_phy_scan_operation_backup, | ||
248 | .set_rf_power_state = rtl88e_phy_set_rf_power_state, | ||
249 | .led_control = rtl88ee_led_control, | ||
250 | .set_desc = rtl88ee_set_desc, | ||
251 | .get_desc = rtl88ee_get_desc, | ||
252 | .tx_polling = rtl88ee_tx_polling, | ||
253 | .enable_hw_sec = rtl88ee_enable_hw_security_config, | ||
254 | .set_key = rtl88ee_set_key, | ||
255 | .init_sw_leds = rtl88ee_init_sw_leds, | ||
256 | .allow_all_destaddr = rtl88ee_allow_all_destaddr, | ||
257 | .get_bbreg = rtl88e_phy_query_bb_reg, | ||
258 | .set_bbreg = rtl88e_phy_set_bb_reg, | ||
259 | .get_rfreg = rtl88e_phy_query_rf_reg, | ||
260 | .set_rfreg = rtl88e_phy_set_rf_reg, | ||
261 | }; | ||
262 | |||
263 | static struct rtl_mod_params rtl88ee_mod_params = { | ||
264 | .sw_crypto = false, | ||
265 | .inactiveps = true, | ||
266 | .swctrl_lps = false, | ||
267 | .fwctrl_lps = true, | ||
268 | .debug = DBG_EMERG, | ||
269 | }; | ||
270 | |||
271 | static struct rtl_hal_cfg rtl88ee_hal_cfg = { | ||
272 | .bar_id = 2, | ||
273 | .write_readback = true, | ||
274 | .name = "rtl88e_pci", | ||
275 | .ops = &rtl8188ee_hal_ops, | ||
276 | .mod_params = &rtl88ee_mod_params, | ||
277 | |||
278 | .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, | ||
279 | .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, | ||
280 | .maps[SYS_CLK] = REG_SYS_CLKR, | ||
281 | .maps[MAC_RCR_AM] = AM, | ||
282 | .maps[MAC_RCR_AB] = AB, | ||
283 | .maps[MAC_RCR_ACRC32] = ACRC32, | ||
284 | .maps[MAC_RCR_ACF] = ACF, | ||
285 | .maps[MAC_RCR_AAP] = AAP, | ||
286 | |||
287 | .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS, | ||
288 | |||
289 | .maps[EFUSE_TEST] = REG_EFUSE_TEST, | ||
290 | .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, | ||
291 | .maps[EFUSE_CLK] = 0, | ||
292 | .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, | ||
293 | .maps[EFUSE_PWC_EV12V] = PWC_EV12V, | ||
294 | .maps[EFUSE_FEN_ELDR] = FEN_ELDR, | ||
295 | .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, | ||
296 | .maps[EFUSE_ANA8M] = ANA8M, | ||
297 | .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, | ||
298 | .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, | ||
299 | .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, | ||
300 | .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, | ||
301 | |||
302 | .maps[RWCAM] = REG_CAMCMD, | ||
303 | .maps[WCAMI] = REG_CAMWRITE, | ||
304 | .maps[RCAMO] = REG_CAMREAD, | ||
305 | .maps[CAMDBG] = REG_CAMDBG, | ||
306 | .maps[SECR] = REG_SECCFG, | ||
307 | .maps[SEC_CAM_NONE] = CAM_NONE, | ||
308 | .maps[SEC_CAM_WEP40] = CAM_WEP40, | ||
309 | .maps[SEC_CAM_TKIP] = CAM_TKIP, | ||
310 | .maps[SEC_CAM_AES] = CAM_AES, | ||
311 | .maps[SEC_CAM_WEP104] = CAM_WEP104, | ||
312 | |||
313 | .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, | ||
314 | .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, | ||
315 | .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, | ||
316 | .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, | ||
317 | .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, | ||
318 | .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, | ||
319 | /* .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, */ /*need check*/ | ||
320 | .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, | ||
321 | .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, | ||
322 | .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, | ||
323 | .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, | ||
324 | .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, | ||
325 | .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, | ||
326 | .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, | ||
327 | /* .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,*/ | ||
328 | /* .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,*/ | ||
329 | |||
330 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | ||
331 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | ||
332 | .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0, | ||
333 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | ||
334 | .maps[RTL_IMR_RDU] = IMR_RDU, | ||
335 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | ||
336 | .maps[RTL_IMR_BDOK] = IMR_BCNDOK0, | ||
337 | .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, | ||
338 | .maps[RTL_IMR_TBDER] = IMR_TBDER, | ||
339 | .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, | ||
340 | .maps[RTL_IMR_TBDOK] = IMR_TBDOK, | ||
341 | .maps[RTL_IMR_BKDOK] = IMR_BKDOK, | ||
342 | .maps[RTL_IMR_BEDOK] = IMR_BEDOK, | ||
343 | .maps[RTL_IMR_VIDOK] = IMR_VIDOK, | ||
344 | .maps[RTL_IMR_VODOK] = IMR_VODOK, | ||
345 | .maps[RTL_IMR_ROK] = IMR_ROK, | ||
346 | .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER), | ||
347 | |||
348 | .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, | ||
349 | .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, | ||
350 | .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, | ||
351 | .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, | ||
352 | .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, | ||
353 | .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, | ||
354 | .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, | ||
355 | .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, | ||
356 | .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, | ||
357 | .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, | ||
358 | .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, | ||
359 | .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, | ||
360 | |||
361 | .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, | ||
362 | .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, | ||
363 | }; | ||
364 | |||
365 | static DEFINE_PCI_DEVICE_TABLE(rtl88ee_pci_ids) = { | ||
366 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8179, rtl88ee_hal_cfg)}, | ||
367 | {}, | ||
368 | }; | ||
369 | |||
370 | MODULE_DEVICE_TABLE(pci, rtl88ee_pci_ids); | ||
371 | |||
372 | MODULE_AUTHOR("zhiyuan_yang <zhiyuan_yang@realsil.com.cn>"); | ||
373 | MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); | ||
374 | MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>"); | ||
375 | MODULE_LICENSE("GPL"); | ||
376 | MODULE_DESCRIPTION("Realtek 8188E 802.11n PCI wireless"); | ||
377 | MODULE_FIRMWARE("rtlwifi/rtl8188efw.bin"); | ||
378 | |||
379 | module_param_named(swenc, rtl88ee_mod_params.sw_crypto, bool, 0444); | ||
380 | module_param_named(debug, rtl88ee_mod_params.debug, int, 0444); | ||
381 | module_param_named(ips, rtl88ee_mod_params.inactiveps, bool, 0444); | ||
382 | module_param_named(swlps, rtl88ee_mod_params.swctrl_lps, bool, 0444); | ||
383 | module_param_named(fwlps, rtl88ee_mod_params.fwctrl_lps, bool, 0444); | ||
384 | MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); | ||
385 | MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); | ||
386 | MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); | ||
387 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); | ||
388 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); | ||
389 | |||
390 | static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); | ||
391 | |||
392 | static struct pci_driver rtl88ee_driver = { | ||
393 | .name = KBUILD_MODNAME, | ||
394 | .id_table = rtl88ee_pci_ids, | ||
395 | .probe = rtl_pci_probe, | ||
396 | .remove = rtl_pci_disconnect, | ||
397 | .driver.pm = &rtlwifi_pm_ops, | ||
398 | }; | ||
399 | |||
400 | module_pci_driver(rtl88ee_driver); | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h new file mode 100644 index 000000000000..85e02b3bdff8 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92CE_SW_H__ | ||
31 | #define __RTL92CE_SW_H__ | ||
32 | |||
33 | int rtl88e_init_sw_vars(struct ieee80211_hw *hw); | ||
34 | void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw); | ||
35 | |||
36 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.c b/drivers/net/wireless/rtlwifi/rtl8188ee/table.c new file mode 100644 index 000000000000..fad373f97b2c --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/table.c | |||
@@ -0,0 +1,643 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Created on 2010/ 5/18, 1:41 | ||
27 | * | ||
28 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
29 | * | ||
30 | *****************************************************************************/ | ||
31 | |||
32 | #include "table.h" | ||
33 | |||
34 | u32 RTL8188EEPHY_REG_1TARRAY[] = { | ||
35 | 0x800, 0x80040000, | ||
36 | 0x804, 0x00000003, | ||
37 | 0x808, 0x0000FC00, | ||
38 | 0x80C, 0x0000000A, | ||
39 | 0x810, 0x10001331, | ||
40 | 0x814, 0x020C3D10, | ||
41 | 0x818, 0x02200385, | ||
42 | 0x81C, 0x00000000, | ||
43 | 0x820, 0x01000100, | ||
44 | 0x824, 0x00390204, | ||
45 | 0x828, 0x00000000, | ||
46 | 0x82C, 0x00000000, | ||
47 | 0x830, 0x00000000, | ||
48 | 0x834, 0x00000000, | ||
49 | 0x838, 0x00000000, | ||
50 | 0x83C, 0x00000000, | ||
51 | 0x840, 0x00010000, | ||
52 | 0x844, 0x00000000, | ||
53 | 0x848, 0x00000000, | ||
54 | 0x84C, 0x00000000, | ||
55 | 0x850, 0x00000000, | ||
56 | 0x854, 0x00000000, | ||
57 | 0x858, 0x569A11A9, | ||
58 | 0x85C, 0x01000014, | ||
59 | 0x860, 0x66F60110, | ||
60 | 0x864, 0x061F0649, | ||
61 | 0x868, 0x00000000, | ||
62 | 0x86C, 0x27272700, | ||
63 | 0x870, 0x07000760, | ||
64 | 0x874, 0x25004000, | ||
65 | 0x878, 0x00000808, | ||
66 | 0x87C, 0x00000000, | ||
67 | 0x880, 0xB0000C1C, | ||
68 | 0x884, 0x00000001, | ||
69 | 0x888, 0x00000000, | ||
70 | 0x88C, 0xCCC000C0, | ||
71 | 0x890, 0x00000800, | ||
72 | 0x894, 0xFFFFFFFE, | ||
73 | 0x898, 0x40302010, | ||
74 | 0x89C, 0x00706050, | ||
75 | 0x900, 0x00000000, | ||
76 | 0x904, 0x00000023, | ||
77 | 0x908, 0x00000000, | ||
78 | 0x90C, 0x81121111, | ||
79 | 0x910, 0x00000002, | ||
80 | 0x914, 0x00000201, | ||
81 | 0xA00, 0x00D047C8, | ||
82 | 0xA04, 0x80FF000C, | ||
83 | 0xA08, 0x8C838300, | ||
84 | 0xA0C, 0x2E7F120F, | ||
85 | 0xA10, 0x9500BB78, | ||
86 | 0xA14, 0x1114D028, | ||
87 | 0xA18, 0x00881117, | ||
88 | 0xA1C, 0x89140F00, | ||
89 | 0xA20, 0x1A1B0000, | ||
90 | 0xA24, 0x090E1317, | ||
91 | 0xA28, 0x00000204, | ||
92 | 0xA2C, 0x00D30000, | ||
93 | 0xA70, 0x101FBF00, | ||
94 | 0xA74, 0x00000007, | ||
95 | 0xA78, 0x00000900, | ||
96 | 0xA7C, 0x225B0606, | ||
97 | 0xA80, 0x218075B1, | ||
98 | 0xB2C, 0x80000000, | ||
99 | 0xC00, 0x48071D40, | ||
100 | 0xC04, 0x03A05611, | ||
101 | 0xC08, 0x000000E4, | ||
102 | 0xC0C, 0x6C6C6C6C, | ||
103 | 0xC10, 0x08800000, | ||
104 | 0xC14, 0x40000100, | ||
105 | 0xC18, 0x08800000, | ||
106 | 0xC1C, 0x40000100, | ||
107 | 0xC20, 0x00000000, | ||
108 | 0xC24, 0x00000000, | ||
109 | 0xC28, 0x00000000, | ||
110 | 0xC2C, 0x00000000, | ||
111 | 0xC30, 0x69E9AC47, | ||
112 | 0xC34, 0x469652AF, | ||
113 | 0xC38, 0x49795994, | ||
114 | 0xC3C, 0x0A97971C, | ||
115 | 0xC40, 0x1F7C403F, | ||
116 | 0xC44, 0x000100B7, | ||
117 | 0xC48, 0xEC020107, | ||
118 | 0xC4C, 0x007F037F, | ||
119 | 0xC50, 0x69553420, | ||
120 | 0xC54, 0x43BC0094, | ||
121 | 0xC58, 0x00013169, | ||
122 | 0xC5C, 0x00250492, | ||
123 | 0xC60, 0x00000000, | ||
124 | 0xC64, 0x7112848B, | ||
125 | 0xC68, 0x47C00BFF, | ||
126 | 0xC6C, 0x00000036, | ||
127 | 0xC70, 0x2C7F000D, | ||
128 | 0xC74, 0x020610DB, | ||
129 | 0xC78, 0x0000001F, | ||
130 | 0xC7C, 0x00B91612, | ||
131 | 0xC80, 0x390000E4, | ||
132 | 0xC84, 0x20F60000, | ||
133 | 0xC88, 0x40000100, | ||
134 | 0xC8C, 0x20200000, | ||
135 | 0xC90, 0x00091521, | ||
136 | 0xC94, 0x00000000, | ||
137 | 0xC98, 0x00121820, | ||
138 | 0xC9C, 0x00007F7F, | ||
139 | 0xCA0, 0x00000000, | ||
140 | 0xCA4, 0x000300A0, | ||
141 | 0xCA8, 0x00000000, | ||
142 | 0xCAC, 0x00000000, | ||
143 | 0xCB0, 0x00000000, | ||
144 | 0xCB4, 0x00000000, | ||
145 | 0xCB8, 0x00000000, | ||
146 | 0xCBC, 0x28000000, | ||
147 | 0xCC0, 0x00000000, | ||
148 | 0xCC4, 0x00000000, | ||
149 | 0xCC8, 0x00000000, | ||
150 | 0xCCC, 0x00000000, | ||
151 | 0xCD0, 0x00000000, | ||
152 | 0xCD4, 0x00000000, | ||
153 | 0xCD8, 0x64B22427, | ||
154 | 0xCDC, 0x00766932, | ||
155 | 0xCE0, 0x00222222, | ||
156 | 0xCE4, 0x00000000, | ||
157 | 0xCE8, 0x37644302, | ||
158 | 0xCEC, 0x2F97D40C, | ||
159 | 0xD00, 0x00000740, | ||
160 | 0xD04, 0x00020401, | ||
161 | 0xD08, 0x0000907F, | ||
162 | 0xD0C, 0x20010201, | ||
163 | 0xD10, 0xA0633333, | ||
164 | 0xD14, 0x3333BC43, | ||
165 | 0xD18, 0x7A8F5B6F, | ||
166 | 0xD2C, 0xCC979975, | ||
167 | 0xD30, 0x00000000, | ||
168 | 0xD34, 0x80608000, | ||
169 | 0xD38, 0x00000000, | ||
170 | 0xD3C, 0x00127353, | ||
171 | 0xD40, 0x00000000, | ||
172 | 0xD44, 0x00000000, | ||
173 | 0xD48, 0x00000000, | ||
174 | 0xD4C, 0x00000000, | ||
175 | 0xD50, 0x6437140A, | ||
176 | 0xD54, 0x00000000, | ||
177 | 0xD58, 0x00000282, | ||
178 | 0xD5C, 0x30032064, | ||
179 | 0xD60, 0x4653DE68, | ||
180 | 0xD64, 0x04518A3C, | ||
181 | 0xD68, 0x00002101, | ||
182 | 0xD6C, 0x2A201C16, | ||
183 | 0xD70, 0x1812362E, | ||
184 | 0xD74, 0x322C2220, | ||
185 | 0xD78, 0x000E3C24, | ||
186 | 0xE00, 0x2D2D2D2D, | ||
187 | 0xE04, 0x2D2D2D2D, | ||
188 | 0xE08, 0x0390272D, | ||
189 | 0xE10, 0x2D2D2D2D, | ||
190 | 0xE14, 0x2D2D2D2D, | ||
191 | 0xE18, 0x2D2D2D2D, | ||
192 | 0xE1C, 0x2D2D2D2D, | ||
193 | 0xE28, 0x00000000, | ||
194 | 0xE30, 0x1000DC1F, | ||
195 | 0xE34, 0x10008C1F, | ||
196 | 0xE38, 0x02140102, | ||
197 | 0xE3C, 0x681604C2, | ||
198 | 0xE40, 0x01007C00, | ||
199 | 0xE44, 0x01004800, | ||
200 | 0xE48, 0xFB000000, | ||
201 | 0xE4C, 0x000028D1, | ||
202 | 0xE50, 0x1000DC1F, | ||
203 | 0xE54, 0x10008C1F, | ||
204 | 0xE58, 0x02140102, | ||
205 | 0xE5C, 0x28160D05, | ||
206 | 0xE60, 0x00000008, | ||
207 | 0xE68, 0x001B25A4, | ||
208 | 0xE6C, 0x00C00014, | ||
209 | 0xE70, 0x00C00014, | ||
210 | 0xE74, 0x01000014, | ||
211 | 0xE78, 0x01000014, | ||
212 | 0xE7C, 0x01000014, | ||
213 | 0xE80, 0x01000014, | ||
214 | 0xE84, 0x00C00014, | ||
215 | 0xE88, 0x01000014, | ||
216 | 0xE8C, 0x00C00014, | ||
217 | 0xED0, 0x00C00014, | ||
218 | 0xED4, 0x00C00014, | ||
219 | 0xED8, 0x00C00014, | ||
220 | 0xEDC, 0x00000014, | ||
221 | 0xEE0, 0x00000014, | ||
222 | 0xEEC, 0x01C00014, | ||
223 | 0xF14, 0x00000003, | ||
224 | 0xF4C, 0x00000000, | ||
225 | 0xF00, 0x00000300, | ||
226 | |||
227 | }; | ||
228 | |||
229 | u32 RTL8188EEPHY_REG_ARRAY_PG[] = { | ||
230 | 0xE00, 0xFFFFFFFF, 0x06070809, | ||
231 | 0xE04, 0xFFFFFFFF, 0x02020405, | ||
232 | 0xE08, 0x0000FF00, 0x00000006, | ||
233 | 0x86C, 0xFFFFFF00, 0x00020400, | ||
234 | 0xE10, 0xFFFFFFFF, 0x08090A0B, | ||
235 | 0xE14, 0xFFFFFFFF, 0x01030607, | ||
236 | 0xE18, 0xFFFFFFFF, 0x08090A0B, | ||
237 | 0xE1C, 0xFFFFFFFF, 0x01030607, | ||
238 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
239 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
240 | 0xE08, 0x0000FF00, 0x00000000, | ||
241 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
242 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
243 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
244 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
245 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
246 | 0xE00, 0xFFFFFFFF, 0x02020202, | ||
247 | 0xE04, 0xFFFFFFFF, 0x00020202, | ||
248 | 0xE08, 0x0000FF00, 0x00000000, | ||
249 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
250 | 0xE10, 0xFFFFFFFF, 0x04040404, | ||
251 | 0xE14, 0xFFFFFFFF, 0x00020404, | ||
252 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
253 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
254 | 0xE00, 0xFFFFFFFF, 0x02020202, | ||
255 | 0xE04, 0xFFFFFFFF, 0x00020202, | ||
256 | 0xE08, 0x0000FF00, 0x00000000, | ||
257 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
258 | 0xE10, 0xFFFFFFFF, 0x04040404, | ||
259 | 0xE14, 0xFFFFFFFF, 0x00020404, | ||
260 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
261 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
262 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
263 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
264 | 0xE08, 0x0000FF00, 0x00000000, | ||
265 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
266 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
267 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
268 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
269 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
270 | 0xE00, 0xFFFFFFFF, 0x02020202, | ||
271 | 0xE04, 0xFFFFFFFF, 0x00020202, | ||
272 | 0xE08, 0x0000FF00, 0x00000000, | ||
273 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
274 | 0xE10, 0xFFFFFFFF, 0x04040404, | ||
275 | 0xE14, 0xFFFFFFFF, 0x00020404, | ||
276 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
277 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
278 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
279 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
280 | 0xE08, 0x0000FF00, 0x00000000, | ||
281 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
282 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
283 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
284 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
285 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
286 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
287 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
288 | 0xE08, 0x0000FF00, 0x00000000, | ||
289 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
290 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
291 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
292 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
293 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
294 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
295 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
296 | 0xE08, 0x0000FF00, 0x00000000, | ||
297 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
298 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
299 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
300 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
301 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
302 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
303 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
304 | 0xE08, 0x0000FF00, 0x00000000, | ||
305 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
306 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
307 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
308 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
309 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
310 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
311 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
312 | 0xE08, 0x0000FF00, 0x00000000, | ||
313 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
314 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
315 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
316 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
317 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
318 | |||
319 | }; | ||
320 | |||
321 | u32 RTL8188EE_RADIOA_1TARRAY[] = { | ||
322 | 0x000, 0x00030000, | ||
323 | 0x008, 0x00084000, | ||
324 | 0x018, 0x00000407, | ||
325 | 0x019, 0x00000012, | ||
326 | 0x01E, 0x00080009, | ||
327 | 0x01F, 0x00000880, | ||
328 | 0x02F, 0x0001A060, | ||
329 | 0x03F, 0x00000000, | ||
330 | 0x042, 0x000060C0, | ||
331 | 0x057, 0x000D0000, | ||
332 | 0x058, 0x000BE180, | ||
333 | 0x067, 0x00001552, | ||
334 | 0x083, 0x00000000, | ||
335 | 0x0B0, 0x000FF8FC, | ||
336 | 0x0B1, 0x00054400, | ||
337 | 0x0B2, 0x000CCC19, | ||
338 | 0x0B4, 0x00043003, | ||
339 | 0x0B6, 0x0004953E, | ||
340 | 0x0B7, 0x0001C718, | ||
341 | 0x0B8, 0x000060FF, | ||
342 | 0x0B9, 0x00080001, | ||
343 | 0x0BA, 0x00040000, | ||
344 | 0x0BB, 0x00000400, | ||
345 | 0x0BF, 0x000C0000, | ||
346 | 0x0C2, 0x00002400, | ||
347 | 0x0C3, 0x00000009, | ||
348 | 0x0C4, 0x00040C91, | ||
349 | 0x0C5, 0x00099999, | ||
350 | 0x0C6, 0x000000A3, | ||
351 | 0x0C7, 0x00088820, | ||
352 | 0x0C8, 0x00076C06, | ||
353 | 0x0C9, 0x00000000, | ||
354 | 0x0CA, 0x00080000, | ||
355 | 0x0DF, 0x00000180, | ||
356 | 0x0EF, 0x000001A0, | ||
357 | 0x051, 0x0006B27D, | ||
358 | 0x052, 0x0007E49D, | ||
359 | 0x053, 0x00000073, | ||
360 | 0x056, 0x00051FF3, | ||
361 | 0x035, 0x00000086, | ||
362 | 0x035, 0x00000186, | ||
363 | 0x035, 0x00000286, | ||
364 | 0x036, 0x00001C25, | ||
365 | 0x036, 0x00009C25, | ||
366 | 0x036, 0x00011C25, | ||
367 | 0x036, 0x00019C25, | ||
368 | 0x0B6, 0x00048538, | ||
369 | 0x018, 0x00000C07, | ||
370 | 0x05A, 0x0004BD00, | ||
371 | 0x019, 0x000739D0, | ||
372 | 0x034, 0x0000ADF3, | ||
373 | 0x034, 0x00009DF0, | ||
374 | 0x034, 0x00008DED, | ||
375 | 0x034, 0x00007DEA, | ||
376 | 0x034, 0x00006DE7, | ||
377 | 0x034, 0x000054EE, | ||
378 | 0x034, 0x000044EB, | ||
379 | 0x034, 0x000034E8, | ||
380 | 0x034, 0x0000246B, | ||
381 | 0x034, 0x00001468, | ||
382 | 0x034, 0x0000006D, | ||
383 | 0x000, 0x00030159, | ||
384 | 0x084, 0x00068200, | ||
385 | 0x086, 0x000000CE, | ||
386 | 0x087, 0x00048A00, | ||
387 | 0x08E, 0x00065540, | ||
388 | 0x08F, 0x00088000, | ||
389 | 0x0EF, 0x000020A0, | ||
390 | 0x03B, 0x000F02B0, | ||
391 | 0x03B, 0x000EF7B0, | ||
392 | 0x03B, 0x000D4FB0, | ||
393 | 0x03B, 0x000CF060, | ||
394 | 0x03B, 0x000B0090, | ||
395 | 0x03B, 0x000A0080, | ||
396 | 0x03B, 0x00090080, | ||
397 | 0x03B, 0x0008F780, | ||
398 | 0x03B, 0x000722B0, | ||
399 | 0x03B, 0x0006F7B0, | ||
400 | 0x03B, 0x00054FB0, | ||
401 | 0x03B, 0x0004F060, | ||
402 | 0x03B, 0x00030090, | ||
403 | 0x03B, 0x00020080, | ||
404 | 0x03B, 0x00010080, | ||
405 | 0x03B, 0x0000F780, | ||
406 | 0x0EF, 0x000000A0, | ||
407 | 0x000, 0x00010159, | ||
408 | 0x018, 0x0000F407, | ||
409 | 0xFFE, 0x00000000, | ||
410 | 0xFFE, 0x00000000, | ||
411 | 0x01F, 0x00080003, | ||
412 | 0xFFE, 0x00000000, | ||
413 | 0xFFE, 0x00000000, | ||
414 | 0x01E, 0x00000001, | ||
415 | 0x01F, 0x00080000, | ||
416 | 0x000, 0x00033E60, | ||
417 | |||
418 | }; | ||
419 | |||
420 | u32 RTL8188EEMAC_1T_ARRAY[] = { | ||
421 | 0x026, 0x00000041, | ||
422 | 0x027, 0x00000035, | ||
423 | 0x428, 0x0000000A, | ||
424 | 0x429, 0x00000010, | ||
425 | 0x430, 0x00000000, | ||
426 | 0x431, 0x00000001, | ||
427 | 0x432, 0x00000002, | ||
428 | 0x433, 0x00000004, | ||
429 | 0x434, 0x00000005, | ||
430 | 0x435, 0x00000006, | ||
431 | 0x436, 0x00000007, | ||
432 | 0x437, 0x00000008, | ||
433 | 0x438, 0x00000000, | ||
434 | 0x439, 0x00000000, | ||
435 | 0x43A, 0x00000001, | ||
436 | 0x43B, 0x00000002, | ||
437 | 0x43C, 0x00000004, | ||
438 | 0x43D, 0x00000005, | ||
439 | 0x43E, 0x00000006, | ||
440 | 0x43F, 0x00000007, | ||
441 | 0x440, 0x0000005D, | ||
442 | 0x441, 0x00000001, | ||
443 | 0x442, 0x00000000, | ||
444 | 0x444, 0x00000015, | ||
445 | 0x445, 0x000000F0, | ||
446 | 0x446, 0x0000000F, | ||
447 | 0x447, 0x00000000, | ||
448 | 0x458, 0x00000041, | ||
449 | 0x459, 0x000000A8, | ||
450 | 0x45A, 0x00000072, | ||
451 | 0x45B, 0x000000B9, | ||
452 | 0x460, 0x00000066, | ||
453 | 0x461, 0x00000066, | ||
454 | 0x480, 0x00000008, | ||
455 | 0x4C8, 0x000000FF, | ||
456 | 0x4C9, 0x00000008, | ||
457 | 0x4CC, 0x000000FF, | ||
458 | 0x4CD, 0x000000FF, | ||
459 | 0x4CE, 0x00000001, | ||
460 | 0x4D3, 0x00000001, | ||
461 | 0x500, 0x00000026, | ||
462 | 0x501, 0x000000A2, | ||
463 | 0x502, 0x0000002F, | ||
464 | 0x503, 0x00000000, | ||
465 | 0x504, 0x00000028, | ||
466 | 0x505, 0x000000A3, | ||
467 | 0x506, 0x0000005E, | ||
468 | 0x507, 0x00000000, | ||
469 | 0x508, 0x0000002B, | ||
470 | 0x509, 0x000000A4, | ||
471 | 0x50A, 0x0000005E, | ||
472 | 0x50B, 0x00000000, | ||
473 | 0x50C, 0x0000004F, | ||
474 | 0x50D, 0x000000A4, | ||
475 | 0x50E, 0x00000000, | ||
476 | 0x50F, 0x00000000, | ||
477 | 0x512, 0x0000001C, | ||
478 | 0x514, 0x0000000A, | ||
479 | 0x516, 0x0000000A, | ||
480 | 0x525, 0x0000004F, | ||
481 | 0x550, 0x00000010, | ||
482 | 0x551, 0x00000010, | ||
483 | 0x559, 0x00000002, | ||
484 | 0x55D, 0x000000FF, | ||
485 | 0x605, 0x00000030, | ||
486 | 0x608, 0x0000000E, | ||
487 | 0x609, 0x0000002A, | ||
488 | 0x620, 0x000000FF, | ||
489 | 0x621, 0x000000FF, | ||
490 | 0x622, 0x000000FF, | ||
491 | 0x623, 0x000000FF, | ||
492 | 0x624, 0x000000FF, | ||
493 | 0x625, 0x000000FF, | ||
494 | 0x626, 0x000000FF, | ||
495 | 0x627, 0x000000FF, | ||
496 | 0x652, 0x00000020, | ||
497 | 0x63C, 0x0000000A, | ||
498 | 0x63D, 0x0000000A, | ||
499 | 0x63E, 0x0000000E, | ||
500 | 0x63F, 0x0000000E, | ||
501 | 0x640, 0x00000040, | ||
502 | 0x66E, 0x00000005, | ||
503 | 0x700, 0x00000021, | ||
504 | 0x701, 0x00000043, | ||
505 | 0x702, 0x00000065, | ||
506 | 0x703, 0x00000087, | ||
507 | 0x708, 0x00000021, | ||
508 | 0x709, 0x00000043, | ||
509 | 0x70A, 0x00000065, | ||
510 | 0x70B, 0x00000087, | ||
511 | |||
512 | }; | ||
513 | |||
514 | u32 RTL8188EEAGCTAB_1TARRAY[] = { | ||
515 | 0xC78, 0xFB000001, | ||
516 | 0xC78, 0xFB010001, | ||
517 | 0xC78, 0xFB020001, | ||
518 | 0xC78, 0xFB030001, | ||
519 | 0xC78, 0xFB040001, | ||
520 | 0xC78, 0xFB050001, | ||
521 | 0xC78, 0xFA060001, | ||
522 | 0xC78, 0xF9070001, | ||
523 | 0xC78, 0xF8080001, | ||
524 | 0xC78, 0xF7090001, | ||
525 | 0xC78, 0xF60A0001, | ||
526 | 0xC78, 0xF50B0001, | ||
527 | 0xC78, 0xF40C0001, | ||
528 | 0xC78, 0xF30D0001, | ||
529 | 0xC78, 0xF20E0001, | ||
530 | 0xC78, 0xF10F0001, | ||
531 | 0xC78, 0xF0100001, | ||
532 | 0xC78, 0xEF110001, | ||
533 | 0xC78, 0xEE120001, | ||
534 | 0xC78, 0xED130001, | ||
535 | 0xC78, 0xEC140001, | ||
536 | 0xC78, 0xEB150001, | ||
537 | 0xC78, 0xEA160001, | ||
538 | 0xC78, 0xE9170001, | ||
539 | 0xC78, 0xE8180001, | ||
540 | 0xC78, 0xE7190001, | ||
541 | 0xC78, 0xE61A0001, | ||
542 | 0xC78, 0xE51B0001, | ||
543 | 0xC78, 0xE41C0001, | ||
544 | 0xC78, 0xE31D0001, | ||
545 | 0xC78, 0xE21E0001, | ||
546 | 0xC78, 0xE11F0001, | ||
547 | 0xC78, 0x8A200001, | ||
548 | 0xC78, 0x89210001, | ||
549 | 0xC78, 0x88220001, | ||
550 | 0xC78, 0x87230001, | ||
551 | 0xC78, 0x86240001, | ||
552 | 0xC78, 0x85250001, | ||
553 | 0xC78, 0x84260001, | ||
554 | 0xC78, 0x83270001, | ||
555 | 0xC78, 0x82280001, | ||
556 | 0xC78, 0x6B290001, | ||
557 | 0xC78, 0x6A2A0001, | ||
558 | 0xC78, 0x692B0001, | ||
559 | 0xC78, 0x682C0001, | ||
560 | 0xC78, 0x672D0001, | ||
561 | 0xC78, 0x662E0001, | ||
562 | 0xC78, 0x652F0001, | ||
563 | 0xC78, 0x64300001, | ||
564 | 0xC78, 0x63310001, | ||
565 | 0xC78, 0x62320001, | ||
566 | 0xC78, 0x61330001, | ||
567 | 0xC78, 0x46340001, | ||
568 | 0xC78, 0x45350001, | ||
569 | 0xC78, 0x44360001, | ||
570 | 0xC78, 0x43370001, | ||
571 | 0xC78, 0x42380001, | ||
572 | 0xC78, 0x41390001, | ||
573 | 0xC78, 0x403A0001, | ||
574 | 0xC78, 0x403B0001, | ||
575 | 0xC78, 0x403C0001, | ||
576 | 0xC78, 0x403D0001, | ||
577 | 0xC78, 0x403E0001, | ||
578 | 0xC78, 0x403F0001, | ||
579 | 0xC78, 0xFB400001, | ||
580 | 0xC78, 0xFB410001, | ||
581 | 0xC78, 0xFB420001, | ||
582 | 0xC78, 0xFB430001, | ||
583 | 0xC78, 0xFB440001, | ||
584 | 0xC78, 0xFB450001, | ||
585 | 0xC78, 0xFB460001, | ||
586 | 0xC78, 0xFB470001, | ||
587 | 0xC78, 0xFB480001, | ||
588 | 0xC78, 0xFA490001, | ||
589 | 0xC78, 0xF94A0001, | ||
590 | 0xC78, 0xF84B0001, | ||
591 | 0xC78, 0xF74C0001, | ||
592 | 0xC78, 0xF64D0001, | ||
593 | 0xC78, 0xF54E0001, | ||
594 | 0xC78, 0xF44F0001, | ||
595 | 0xC78, 0xF3500001, | ||
596 | 0xC78, 0xF2510001, | ||
597 | 0xC78, 0xF1520001, | ||
598 | 0xC78, 0xF0530001, | ||
599 | 0xC78, 0xEF540001, | ||
600 | 0xC78, 0xEE550001, | ||
601 | 0xC78, 0xED560001, | ||
602 | 0xC78, 0xEC570001, | ||
603 | 0xC78, 0xEB580001, | ||
604 | 0xC78, 0xEA590001, | ||
605 | 0xC78, 0xE95A0001, | ||
606 | 0xC78, 0xE85B0001, | ||
607 | 0xC78, 0xE75C0001, | ||
608 | 0xC78, 0xE65D0001, | ||
609 | 0xC78, 0xE55E0001, | ||
610 | 0xC78, 0xE45F0001, | ||
611 | 0xC78, 0xE3600001, | ||
612 | 0xC78, 0xE2610001, | ||
613 | 0xC78, 0xC3620001, | ||
614 | 0xC78, 0xC2630001, | ||
615 | 0xC78, 0xC1640001, | ||
616 | 0xC78, 0x8B650001, | ||
617 | 0xC78, 0x8A660001, | ||
618 | 0xC78, 0x89670001, | ||
619 | 0xC78, 0x88680001, | ||
620 | 0xC78, 0x87690001, | ||
621 | 0xC78, 0x866A0001, | ||
622 | 0xC78, 0x856B0001, | ||
623 | 0xC78, 0x846C0001, | ||
624 | 0xC78, 0x676D0001, | ||
625 | 0xC78, 0x666E0001, | ||
626 | 0xC78, 0x656F0001, | ||
627 | 0xC78, 0x64700001, | ||
628 | 0xC78, 0x63710001, | ||
629 | 0xC78, 0x62720001, | ||
630 | 0xC78, 0x61730001, | ||
631 | 0xC78, 0x60740001, | ||
632 | 0xC78, 0x46750001, | ||
633 | 0xC78, 0x45760001, | ||
634 | 0xC78, 0x44770001, | ||
635 | 0xC78, 0x43780001, | ||
636 | 0xC78, 0x42790001, | ||
637 | 0xC78, 0x417A0001, | ||
638 | 0xC78, 0x407B0001, | ||
639 | 0xC78, 0x407C0001, | ||
640 | 0xC78, 0x407D0001, | ||
641 | 0xC78, 0x407E0001, | ||
642 | 0xC78, 0x407F0001, | ||
643 | }; | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.h b/drivers/net/wireless/rtlwifi/rtl8188ee/table.h new file mode 100644 index 000000000000..c1218e835129 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/table.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Created on 2010/ 5/18, 1:41 | ||
27 | * | ||
28 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
29 | * | ||
30 | *****************************************************************************/ | ||
31 | |||
32 | #ifndef __RTL92CE_TABLE__H_ | ||
33 | #define __RTL92CE_TABLE__H_ | ||
34 | |||
35 | #include <linux/types.h> | ||
36 | #define RTL8188EEPHY_REG_1TARRAYLEN 382 | ||
37 | extern u32 RTL8188EEPHY_REG_1TARRAY[]; | ||
38 | #define RTL8188EEPHY_REG_ARRAY_PGLEN 264 | ||
39 | extern u32 RTL8188EEPHY_REG_ARRAY_PG[]; | ||
40 | #define RTL8188EE_RADIOA_1TARRAYLEN 190 | ||
41 | extern u32 RTL8188EE_RADIOA_1TARRAY[]; | ||
42 | #define RTL8188EEMAC_1T_ARRAYLEN 180 | ||
43 | extern u32 RTL8188EEMAC_1T_ARRAY[]; | ||
44 | #define RTL8188EEAGCTAB_1TARRAYLEN 256 | ||
45 | extern u32 RTL8188EEAGCTAB_1TARRAY[]; | ||
46 | |||
47 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c new file mode 100644 index 000000000000..a8871d66d56a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c | |||
@@ -0,0 +1,817 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "../base.h" | ||
33 | #include "../stats.h" | ||
34 | #include "reg.h" | ||
35 | #include "def.h" | ||
36 | #include "phy.h" | ||
37 | #include "trx.h" | ||
38 | #include "led.h" | ||
39 | #include "dm.h" | ||
40 | |||
41 | static u8 _rtl88ee_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) | ||
42 | { | ||
43 | __le16 fc = rtl_get_fc(skb); | ||
44 | |||
45 | if (unlikely(ieee80211_is_beacon(fc))) | ||
46 | return QSLT_BEACON; | ||
47 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) | ||
48 | return QSLT_MGNT; | ||
49 | |||
50 | return skb->priority; | ||
51 | } | ||
52 | |||
53 | static void _rtl88ee_query_rxphystatus(struct ieee80211_hw *hw, | ||
54 | struct rtl_stats *pstatus, u8 *pdesc, | ||
55 | struct rx_fwinfo_88e *p_drvinfo, | ||
56 | bool bpacket_match_bssid, | ||
57 | bool bpacket_toself, bool packet_beacon) | ||
58 | { | ||
59 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
60 | struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); | ||
61 | struct phy_sts_cck_8192s_t *cck_buf; | ||
62 | struct phy_status_rpt *phystrpt = (struct phy_status_rpt *)p_drvinfo; | ||
63 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
64 | char rx_pwr_all = 0, rx_pwr[4]; | ||
65 | u8 rf_rx_num = 0, evm, pwdb_all; | ||
66 | u8 i, max_spatial_stream; | ||
67 | u32 rssi, total_rssi = 0; | ||
68 | bool is_cck = pstatus->is_cck; | ||
69 | u8 lan_idx, vga_idx; | ||
70 | |||
71 | /* Record it for next packet processing */ | ||
72 | pstatus->packet_matchbssid = bpacket_match_bssid; | ||
73 | pstatus->packet_toself = bpacket_toself; | ||
74 | pstatus->packet_beacon = packet_beacon; | ||
75 | pstatus->rx_mimo_sig_qual[0] = -1; | ||
76 | pstatus->rx_mimo_sig_qual[1] = -1; | ||
77 | |||
78 | if (is_cck) { | ||
79 | u8 cck_hipwr; | ||
80 | u8 cck_agc_rpt; | ||
81 | /* CCK Driver info Structure is not the same as OFDM packet. */ | ||
82 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; | ||
83 | cck_agc_rpt = cck_buf->cck_agc_rpt; | ||
84 | |||
85 | /* (1)Hardware does not provide RSSI for CCK | ||
86 | * (2)PWDB, Average PWDB cacluated by | ||
87 | * hardware (for rate adaptive) | ||
88 | */ | ||
89 | if (ppsc->rfpwr_state == ERFON) | ||
90 | cck_hipwr = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, | ||
91 | BIT(9)); | ||
92 | else | ||
93 | cck_hipwr = false; | ||
94 | |||
95 | lan_idx = ((cck_agc_rpt & 0xE0) >> 5); | ||
96 | vga_idx = (cck_agc_rpt & 0x1f); | ||
97 | switch (lan_idx) { | ||
98 | case 7: | ||
99 | if (vga_idx <= 27) | ||
100 | rx_pwr_all = -100 + 2 * (27 - vga_idx); | ||
101 | else | ||
102 | rx_pwr_all = -100; | ||
103 | break; | ||
104 | case 6: | ||
105 | rx_pwr_all = -48 + 2 * (2 - vga_idx); /*VGA_idx = 2~0*/ | ||
106 | break; | ||
107 | case 5: | ||
108 | rx_pwr_all = -42 + 2 * (7 - vga_idx); /*VGA_idx = 7~5*/ | ||
109 | break; | ||
110 | case 4: | ||
111 | rx_pwr_all = -36 + 2 * (7 - vga_idx); /*VGA_idx = 7~4*/ | ||
112 | break; | ||
113 | case 3: | ||
114 | rx_pwr_all = -24 + 2 * (7 - vga_idx); /*VGA_idx = 7~0*/ | ||
115 | break; | ||
116 | case 2: | ||
117 | if (cck_hipwr) | ||
118 | rx_pwr_all = -12 + 2 * (5 - vga_idx); | ||
119 | else | ||
120 | rx_pwr_all = -6 + 2 * (5 - vga_idx); | ||
121 | break; | ||
122 | case 1: | ||
123 | rx_pwr_all = 8 - 2 * vga_idx; | ||
124 | break; | ||
125 | case 0: | ||
126 | rx_pwr_all = 14 - 2 * vga_idx; | ||
127 | break; | ||
128 | default: | ||
129 | break; | ||
130 | } | ||
131 | rx_pwr_all += 6; | ||
132 | pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); | ||
133 | /* CCK gain is smaller than OFDM/MCS gain, | ||
134 | * so we add gain diff by experiences, | ||
135 | * the val is 6 | ||
136 | */ | ||
137 | pwdb_all += 6; | ||
138 | if (pwdb_all > 100) | ||
139 | pwdb_all = 100; | ||
140 | /* modify the offset to make the same | ||
141 | * gain index with OFDM. | ||
142 | */ | ||
143 | if (pwdb_all > 34 && pwdb_all <= 42) | ||
144 | pwdb_all -= 2; | ||
145 | else if (pwdb_all > 26 && pwdb_all <= 34) | ||
146 | pwdb_all -= 6; | ||
147 | else if (pwdb_all > 14 && pwdb_all <= 26) | ||
148 | pwdb_all -= 8; | ||
149 | else if (pwdb_all > 4 && pwdb_all <= 14) | ||
150 | pwdb_all -= 4; | ||
151 | if (cck_hipwr == false) { | ||
152 | if (pwdb_all >= 80) | ||
153 | pwdb_all = ((pwdb_all - 80)<<1) + | ||
154 | ((pwdb_all - 80)>>1) + 80; | ||
155 | else if ((pwdb_all <= 78) && (pwdb_all >= 20)) | ||
156 | pwdb_all += 3; | ||
157 | if (pwdb_all > 100) | ||
158 | pwdb_all = 100; | ||
159 | } | ||
160 | |||
161 | pstatus->rx_pwdb_all = pwdb_all; | ||
162 | pstatus->recvsignalpower = rx_pwr_all; | ||
163 | |||
164 | /* (3) Get Signal Quality (EVM) */ | ||
165 | if (bpacket_match_bssid) { | ||
166 | u8 sq; | ||
167 | |||
168 | if (pstatus->rx_pwdb_all > 40) { | ||
169 | sq = 100; | ||
170 | } else { | ||
171 | sq = cck_buf->sq_rpt; | ||
172 | if (sq > 64) | ||
173 | sq = 0; | ||
174 | else if (sq < 20) | ||
175 | sq = 100; | ||
176 | else | ||
177 | sq = ((64 - sq) * 100) / 44; | ||
178 | } | ||
179 | |||
180 | pstatus->signalquality = sq; | ||
181 | pstatus->rx_mimo_sig_qual[0] = sq; | ||
182 | pstatus->rx_mimo_sig_qual[1] = -1; | ||
183 | } | ||
184 | } else { | ||
185 | rtlpriv->dm.rfpath_rxenable[0] = | ||
186 | rtlpriv->dm.rfpath_rxenable[1] = true; | ||
187 | |||
188 | /* (1)Get RSSI for HT rate */ | ||
189 | for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { | ||
190 | /* we will judge RF RX path now. */ | ||
191 | if (rtlpriv->dm.rfpath_rxenable[i]) | ||
192 | rf_rx_num++; | ||
193 | |||
194 | rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2)-110; | ||
195 | |||
196 | /* Translate DBM to percentage. */ | ||
197 | rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); | ||
198 | total_rssi += rssi; | ||
199 | |||
200 | /* Get Rx snr value in DB */ | ||
201 | rtlpriv->stats.rx_snr_db[i] = p_drvinfo->rxsnr[i] / 2; | ||
202 | |||
203 | /* Record Signal Strength for next packet */ | ||
204 | if (bpacket_match_bssid) | ||
205 | pstatus->rx_mimo_signalstrength[i] = (u8) rssi; | ||
206 | } | ||
207 | |||
208 | /* (2)PWDB, Average PWDB cacluated by | ||
209 | * hardware (for rate adaptive) | ||
210 | */ | ||
211 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; | ||
212 | |||
213 | pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); | ||
214 | pstatus->rx_pwdb_all = pwdb_all; | ||
215 | pstatus->rxpower = rx_pwr_all; | ||
216 | pstatus->recvsignalpower = rx_pwr_all; | ||
217 | |||
218 | /* (3)EVM of HT rate */ | ||
219 | if (pstatus->is_ht && pstatus->rate >= DESC92C_RATEMCS8 && | ||
220 | pstatus->rate <= DESC92C_RATEMCS15) | ||
221 | max_spatial_stream = 2; | ||
222 | else | ||
223 | max_spatial_stream = 1; | ||
224 | |||
225 | for (i = 0; i < max_spatial_stream; i++) { | ||
226 | evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]); | ||
227 | |||
228 | if (bpacket_match_bssid) { | ||
229 | /* Fill value in RFD, Get the first | ||
230 | * spatial stream only | ||
231 | */ | ||
232 | if (i == 0) | ||
233 | pstatus->signalquality = evm & 0xff; | ||
234 | pstatus->rx_mimo_sig_qual[i] = evm & 0xff; | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | |||
239 | /* UI BSS List signal strength(in percentage), | ||
240 | * make it good looking, from 0~100. | ||
241 | */ | ||
242 | if (is_cck) | ||
243 | pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, | ||
244 | pwdb_all)); | ||
245 | else if (rf_rx_num != 0) | ||
246 | pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, | ||
247 | total_rssi /= rf_rx_num)); | ||
248 | /*HW antenna diversity*/ | ||
249 | rtldm->fat_table.antsel_rx_keep_0 = phystrpt->ant_sel; | ||
250 | rtldm->fat_table.antsel_rx_keep_1 = phystrpt->ant_sel_b; | ||
251 | rtldm->fat_table.antsel_rx_keep_2 = phystrpt->antsel_rx_keep_2; | ||
252 | } | ||
253 | |||
254 | static void _rtl88ee_smart_antenna(struct ieee80211_hw *hw, | ||
255 | struct rtl_stats *pstatus) | ||
256 | { | ||
257 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
258 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
259 | u8 ant_mux; | ||
260 | struct fast_ant_training *pfat = &(rtldm->fat_table); | ||
261 | |||
262 | if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) { | ||
263 | if (pfat->fat_state == FAT_TRAINING_STATE) { | ||
264 | if (pstatus->packet_toself) { | ||
265 | ant_mux = (pfat->antsel_rx_keep_2 << 2) | | ||
266 | (pfat->antsel_rx_keep_1 << 1) | | ||
267 | pfat->antsel_rx_keep_0; | ||
268 | pfat->ant_sum[ant_mux] += pstatus->rx_pwdb_all; | ||
269 | pfat->ant_cnt[ant_mux]++; | ||
270 | } | ||
271 | } | ||
272 | } else if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || | ||
273 | (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)) { | ||
274 | if (pstatus->packet_toself || pstatus->packet_matchbssid) { | ||
275 | ant_mux = (pfat->antsel_rx_keep_2 << 2) | | ||
276 | (pfat->antsel_rx_keep_1 << 1) | | ||
277 | pfat->antsel_rx_keep_0; | ||
278 | rtl88e_dm_ant_sel_statistics(hw, ant_mux, 0, | ||
279 | pstatus->rx_pwdb_all); | ||
280 | } | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, | ||
285 | struct sk_buff *skb, struct rtl_stats *pstatus, | ||
286 | u8 *pdesc, struct rx_fwinfo_88e *p_drvinfo) | ||
287 | { | ||
288 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
289 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
290 | struct ieee80211_hdr *hdr; | ||
291 | u8 *tmp_buf; | ||
292 | u8 *praddr; | ||
293 | u8 *psaddr; | ||
294 | __le16 fc; | ||
295 | u16 type, ufc; | ||
296 | bool match_bssid, packet_toself, packet_beacon, addr; | ||
297 | |||
298 | tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; | ||
299 | |||
300 | hdr = (struct ieee80211_hdr *)tmp_buf; | ||
301 | fc = hdr->frame_control; | ||
302 | ufc = le16_to_cpu(fc); | ||
303 | type = WLAN_FC_GET_TYPE(fc); | ||
304 | praddr = hdr->addr1; | ||
305 | psaddr = ieee80211_get_SA(hdr); | ||
306 | memcpy(pstatus->psaddr, psaddr, ETH_ALEN); | ||
307 | |||
308 | addr = (!compare_ether_addr(mac->bssid, (ufc & IEEE80211_FCTL_TODS) ? | ||
309 | hdr->addr1 : (ufc & IEEE80211_FCTL_FROMDS) ? | ||
310 | hdr->addr2 : hdr->addr3)); | ||
311 | match_bssid = ((IEEE80211_FTYPE_CTL != type) && (!pstatus->hwerror) && | ||
312 | (!pstatus->crc) && (!pstatus->icv)) && addr; | ||
313 | |||
314 | addr = (!compare_ether_addr(praddr, rtlefuse->dev_addr)); | ||
315 | packet_toself = match_bssid && addr; | ||
316 | |||
317 | if (ieee80211_is_beacon(fc)) | ||
318 | packet_beacon = true; | ||
319 | |||
320 | _rtl88ee_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, | ||
321 | match_bssid, packet_toself, packet_beacon); | ||
322 | _rtl88ee_smart_antenna(hw, pstatus); | ||
323 | rtl_process_phyinfo(hw, tmp_buf, pstatus); | ||
324 | } | ||
325 | |||
326 | static void insert_em(struct rtl_tcb_desc *ptcb_desc, u8 *virtualaddress) | ||
327 | { | ||
328 | u32 dwtmp = 0; | ||
329 | |||
330 | memset(virtualaddress, 0, 8); | ||
331 | |||
332 | SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); | ||
333 | if (ptcb_desc->empkt_num == 1) { | ||
334 | dwtmp = ptcb_desc->empkt_len[0]; | ||
335 | } else { | ||
336 | dwtmp = ptcb_desc->empkt_len[0]; | ||
337 | dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; | ||
338 | dwtmp += ptcb_desc->empkt_len[1]; | ||
339 | } | ||
340 | SET_EARLYMODE_LEN0(virtualaddress, dwtmp); | ||
341 | |||
342 | if (ptcb_desc->empkt_num <= 3) { | ||
343 | dwtmp = ptcb_desc->empkt_len[2]; | ||
344 | } else { | ||
345 | dwtmp = ptcb_desc->empkt_len[2]; | ||
346 | dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; | ||
347 | dwtmp += ptcb_desc->empkt_len[3]; | ||
348 | } | ||
349 | SET_EARLYMODE_LEN1(virtualaddress, dwtmp); | ||
350 | if (ptcb_desc->empkt_num <= 5) { | ||
351 | dwtmp = ptcb_desc->empkt_len[4]; | ||
352 | } else { | ||
353 | dwtmp = ptcb_desc->empkt_len[4]; | ||
354 | dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; | ||
355 | dwtmp += ptcb_desc->empkt_len[5]; | ||
356 | } | ||
357 | SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); | ||
358 | SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); | ||
359 | if (ptcb_desc->empkt_num <= 7) { | ||
360 | dwtmp = ptcb_desc->empkt_len[6]; | ||
361 | } else { | ||
362 | dwtmp = ptcb_desc->empkt_len[6]; | ||
363 | dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; | ||
364 | dwtmp += ptcb_desc->empkt_len[7]; | ||
365 | } | ||
366 | SET_EARLYMODE_LEN3(virtualaddress, dwtmp); | ||
367 | if (ptcb_desc->empkt_num <= 9) { | ||
368 | dwtmp = ptcb_desc->empkt_len[8]; | ||
369 | } else { | ||
370 | dwtmp = ptcb_desc->empkt_len[8]; | ||
371 | dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; | ||
372 | dwtmp += ptcb_desc->empkt_len[9]; | ||
373 | } | ||
374 | SET_EARLYMODE_LEN4(virtualaddress, dwtmp); | ||
375 | } | ||
376 | |||
377 | bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, | ||
378 | struct rtl_stats *status, | ||
379 | struct ieee80211_rx_status *rx_status, | ||
380 | u8 *pdesc, struct sk_buff *skb) | ||
381 | { | ||
382 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
383 | struct rx_fwinfo_88e *p_drvinfo; | ||
384 | struct ieee80211_hdr *hdr; | ||
385 | |||
386 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); | ||
387 | status->packet_report_type = (u8)GET_RX_STATUS_DESC_RPT_SEL(pdesc); | ||
388 | if (status->packet_report_type == TX_REPORT2) | ||
389 | status->length = (u16) GET_RX_RPT2_DESC_PKT_LEN(pdesc); | ||
390 | else | ||
391 | status->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); | ||
392 | status->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * | ||
393 | RX_DRV_INFO_SIZE_UNIT; | ||
394 | status->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); | ||
395 | status->icv = (u16) GET_RX_DESC_ICV(pdesc); | ||
396 | status->crc = (u16) GET_RX_DESC_CRC32(pdesc); | ||
397 | status->hwerror = (status->crc | status->icv); | ||
398 | status->decrypted = !GET_RX_DESC_SWDEC(pdesc); | ||
399 | status->rate = (u8) GET_RX_DESC_RXMCS(pdesc); | ||
400 | status->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); | ||
401 | status->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); | ||
402 | status->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) && | ||
403 | (GET_RX_DESC_FAGGR(pdesc) == 1)); | ||
404 | if (status->packet_report_type == NORMAL_RX) | ||
405 | status->timestamp_low = GET_RX_DESC_TSFL(pdesc); | ||
406 | status->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); | ||
407 | status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); | ||
408 | |||
409 | status->is_cck = RTL8188_RX_HAL_IS_CCK_RATE(status->rate); | ||
410 | |||
411 | status->macid = GET_RX_DESC_MACID(pdesc); | ||
412 | if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) | ||
413 | status->wake_match = BIT(2); | ||
414 | else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) | ||
415 | status->wake_match = BIT(1); | ||
416 | else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) | ||
417 | status->wake_match = BIT(0); | ||
418 | else | ||
419 | status->wake_match = 0; | ||
420 | if (status->wake_match) | ||
421 | RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, | ||
422 | "Get Wakeup Packet!! WakeMatch =%d\n", | ||
423 | status->wake_match); | ||
424 | rx_status->freq = hw->conf.chandef.chan->center_freq; | ||
425 | rx_status->band = hw->conf.chandef.chan->band; | ||
426 | |||
427 | if (status->crc) | ||
428 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
429 | |||
430 | if (status->rx_is40Mhzpacket) | ||
431 | rx_status->flag |= RX_FLAG_40MHZ; | ||
432 | |||
433 | if (status->is_ht) | ||
434 | rx_status->flag |= RX_FLAG_HT; | ||
435 | |||
436 | rx_status->flag |= RX_FLAG_MACTIME_START; | ||
437 | |||
438 | /* hw will set status->decrypted true, if it finds the | ||
439 | * frame is open data frame or mgmt frame. | ||
440 | * So hw will not decryption robust managment frame | ||
441 | * for IEEE80211w but still set status->decrypted | ||
442 | * true, so here we should set it back to undecrypted | ||
443 | * for IEEE80211w frame, and mac80211 sw will help | ||
444 | * to decrypt it | ||
445 | */ | ||
446 | if (status->decrypted) { | ||
447 | hdr = (struct ieee80211_hdr *)(skb->data + | ||
448 | status->rx_drvinfo_size + status->rx_bufshift); | ||
449 | |||
450 | if (!hdr) { | ||
451 | /* During testing, hdr was NULL */ | ||
452 | return false; | ||
453 | } | ||
454 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | ||
455 | (ieee80211_has_protected(hdr->frame_control))) | ||
456 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | ||
457 | else | ||
458 | rx_status->flag |= RX_FLAG_DECRYPTED; | ||
459 | } | ||
460 | |||
461 | /* rate_idx: index of data rate into band's | ||
462 | * supported rates or MCS index if HT rates | ||
463 | * are use (RX_FLAG_HT) | ||
464 | * Notice: this is diff with windows define | ||
465 | */ | ||
466 | rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, | ||
467 | status->rate, false); | ||
468 | |||
469 | rx_status->mactime = status->timestamp_low; | ||
470 | if (phystatus == true) { | ||
471 | p_drvinfo = (struct rx_fwinfo_88e *)(skb->data + | ||
472 | status->rx_bufshift); | ||
473 | |||
474 | _rtl88ee_translate_rx_signal_stuff(hw, skb, status, pdesc, | ||
475 | p_drvinfo); | ||
476 | } | ||
477 | |||
478 | /*rx_status->qual = status->signal; */ | ||
479 | rx_status->signal = status->recvsignalpower + 10; | ||
480 | /*rx_status->noise = -status->noise; */ | ||
481 | if (status->packet_report_type == TX_REPORT2) { | ||
482 | status->macid_valid_entry[0] = | ||
483 | GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); | ||
484 | status->macid_valid_entry[1] = | ||
485 | GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); | ||
486 | } | ||
487 | return true; | ||
488 | } | ||
489 | |||
490 | void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, | ||
491 | struct ieee80211_hdr *hdr, u8 *pdesc_tx, | ||
492 | struct ieee80211_tx_info *info, | ||
493 | struct ieee80211_sta *sta, | ||
494 | struct sk_buff *skb, | ||
495 | u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) | ||
496 | { | ||
497 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
498 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
499 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
500 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | ||
501 | u8 *pdesc = (u8 *)pdesc_tx; | ||
502 | u16 seq_number; | ||
503 | __le16 fc = hdr->frame_control; | ||
504 | unsigned int buf_len = 0; | ||
505 | unsigned int skb_len = skb->len; | ||
506 | u8 fw_qsel = _rtl88ee_map_hwqueue_to_fwqueue(skb, hw_queue); | ||
507 | bool firstseg = ((hdr->seq_ctrl & | ||
508 | cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); | ||
509 | bool lastseg = ((hdr->frame_control & | ||
510 | cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); | ||
511 | dma_addr_t mapping; | ||
512 | u8 bw_40 = 0; | ||
513 | u8 short_gi = 0; | ||
514 | |||
515 | if (mac->opmode == NL80211_IFTYPE_STATION) { | ||
516 | bw_40 = mac->bw_40; | ||
517 | } else if (mac->opmode == NL80211_IFTYPE_AP || | ||
518 | mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
519 | if (sta) | ||
520 | bw_40 = sta->ht_cap.cap & | ||
521 | IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
522 | } | ||
523 | seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; | ||
524 | rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); | ||
525 | /* reserve 8 byte for AMPDU early mode */ | ||
526 | if (rtlhal->earlymode_enable) { | ||
527 | skb_push(skb, EM_HDR_LEN); | ||
528 | memset(skb->data, 0, EM_HDR_LEN); | ||
529 | } | ||
530 | buf_len = skb->len; | ||
531 | mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, | ||
532 | PCI_DMA_TODEVICE); | ||
533 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
534 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
535 | "DMA mapping error"); | ||
536 | return; | ||
537 | } | ||
538 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_88e)); | ||
539 | if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { | ||
540 | firstseg = true; | ||
541 | lastseg = true; | ||
542 | } | ||
543 | if (firstseg) { | ||
544 | if (rtlhal->earlymode_enable) { | ||
545 | SET_TX_DESC_PKT_OFFSET(pdesc, 1); | ||
546 | SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + | ||
547 | EM_HDR_LEN); | ||
548 | if (ptcb_desc->empkt_num) { | ||
549 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
550 | "Insert 8 byte.pTcb->EMPktNum:%d\n", | ||
551 | ptcb_desc->empkt_num); | ||
552 | insert_em(ptcb_desc, (u8 *)(skb->data)); | ||
553 | } | ||
554 | } else { | ||
555 | SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); | ||
556 | } | ||
557 | |||
558 | ptcb_desc->use_driver_rate = true; | ||
559 | SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); | ||
560 | if (ptcb_desc->hw_rate > DESC92C_RATEMCS0) | ||
561 | short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; | ||
562 | else | ||
563 | short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; | ||
564 | SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi); | ||
565 | |||
566 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
567 | SET_TX_DESC_AGG_ENABLE(pdesc, 1); | ||
568 | SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); | ||
569 | } | ||
570 | SET_TX_DESC_SEQ(pdesc, seq_number); | ||
571 | SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && | ||
572 | !ptcb_desc->cts_enable) ? 1 : 0)); | ||
573 | SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); | ||
574 | SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); | ||
575 | SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); | ||
576 | |||
577 | SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); | ||
578 | SET_TX_DESC_RTS_BW(pdesc, 0); | ||
579 | SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); | ||
580 | SET_TX_DESC_RTS_SHORT(pdesc, | ||
581 | ((ptcb_desc->rts_rate <= DESC92C_RATE54M) ? | ||
582 | (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : | ||
583 | (ptcb_desc->rts_use_shortgi ? 1 : 0))); | ||
584 | |||
585 | if (ptcb_desc->btx_enable_sw_calc_duration) | ||
586 | SET_TX_DESC_NAV_USE_HDR(pdesc, 1); | ||
587 | |||
588 | if (bw_40) { | ||
589 | if (ptcb_desc->packet_bw) { | ||
590 | SET_TX_DESC_DATA_BW(pdesc, 1); | ||
591 | SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); | ||
592 | } else { | ||
593 | SET_TX_DESC_DATA_BW(pdesc, 0); | ||
594 | SET_TX_DESC_TX_SUB_CARRIER(pdesc, | ||
595 | mac->cur_40_prime_sc); | ||
596 | } | ||
597 | } else { | ||
598 | SET_TX_DESC_DATA_BW(pdesc, 0); | ||
599 | SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); | ||
600 | } | ||
601 | |||
602 | SET_TX_DESC_LINIP(pdesc, 0); | ||
603 | SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len); | ||
604 | if (sta) { | ||
605 | u8 ampdu_density = sta->ht_cap.ampdu_density; | ||
606 | SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); | ||
607 | } | ||
608 | if (info->control.hw_key) { | ||
609 | struct ieee80211_key_conf *keyconf; | ||
610 | keyconf = info->control.hw_key; | ||
611 | switch (keyconf->cipher) { | ||
612 | case WLAN_CIPHER_SUITE_WEP40: | ||
613 | case WLAN_CIPHER_SUITE_WEP104: | ||
614 | case WLAN_CIPHER_SUITE_TKIP: | ||
615 | SET_TX_DESC_SEC_TYPE(pdesc, 0x1); | ||
616 | break; | ||
617 | case WLAN_CIPHER_SUITE_CCMP: | ||
618 | SET_TX_DESC_SEC_TYPE(pdesc, 0x3); | ||
619 | break; | ||
620 | default: | ||
621 | SET_TX_DESC_SEC_TYPE(pdesc, 0x0); | ||
622 | break; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); | ||
627 | SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); | ||
628 | SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); | ||
629 | SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? | ||
630 | 1 : 0); | ||
631 | SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); | ||
632 | |||
633 | /* Set TxRate and RTSRate in TxDesc */ | ||
634 | /* This prevent Tx initial rate of new-coming packets */ | ||
635 | /* from being overwritten by retried packet rate.*/ | ||
636 | if (!ptcb_desc->use_driver_rate) { | ||
637 | /*SET_TX_DESC_RTS_RATE(pdesc, 0x08); */ | ||
638 | /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ | ||
639 | } | ||
640 | if (ieee80211_is_data_qos(fc)) { | ||
641 | if (mac->rdg_en) { | ||
642 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
643 | "Enable RDG function.\n"); | ||
644 | SET_TX_DESC_RDG_ENABLE(pdesc, 1); | ||
645 | SET_TX_DESC_HTC(pdesc, 1); | ||
646 | } | ||
647 | } | ||
648 | } | ||
649 | |||
650 | SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); | ||
651 | SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); | ||
652 | SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len); | ||
653 | SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); | ||
654 | if (rtlpriv->dm.useramask) { | ||
655 | SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); | ||
656 | SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); | ||
657 | } else { | ||
658 | SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); | ||
659 | SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); | ||
660 | } | ||
661 | if (ieee80211_is_data_qos(fc)) | ||
662 | SET_TX_DESC_QOS(pdesc, 1); | ||
663 | |||
664 | if (!ieee80211_is_data_qos(fc)) | ||
665 | SET_TX_DESC_HWSEQ_EN(pdesc, 1); | ||
666 | SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); | ||
667 | if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || | ||
668 | is_broadcast_ether_addr(ieee80211_get_DA(hdr))) | ||
669 | SET_TX_DESC_BMC(pdesc, 1); | ||
670 | |||
671 | rtl88e_dm_set_tx_ant_by_tx_info(hw, pdesc, ptcb_desc->mac_id); | ||
672 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); | ||
673 | } | ||
674 | |||
675 | void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, | ||
676 | u8 *pdesc, bool firstseg, | ||
677 | bool lastseg, struct sk_buff *skb) | ||
678 | { | ||
679 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
680 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
681 | u8 fw_queue = QSLT_BEACON; | ||
682 | |||
683 | dma_addr_t mapping = pci_map_single(rtlpci->pdev, | ||
684 | skb->data, skb->len, | ||
685 | PCI_DMA_TODEVICE); | ||
686 | |||
687 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); | ||
688 | __le16 fc = hdr->frame_control; | ||
689 | |||
690 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
691 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
692 | "DMA mapping error"); | ||
693 | return; | ||
694 | } | ||
695 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); | ||
696 | |||
697 | if (firstseg) | ||
698 | SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); | ||
699 | |||
700 | SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); | ||
701 | |||
702 | SET_TX_DESC_SEQ(pdesc, 0); | ||
703 | |||
704 | SET_TX_DESC_LINIP(pdesc, 0); | ||
705 | |||
706 | SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); | ||
707 | |||
708 | SET_TX_DESC_FIRST_SEG(pdesc, 1); | ||
709 | SET_TX_DESC_LAST_SEG(pdesc, 1); | ||
710 | |||
711 | SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); | ||
712 | |||
713 | SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); | ||
714 | |||
715 | SET_TX_DESC_RATE_ID(pdesc, 7); | ||
716 | SET_TX_DESC_MACID(pdesc, 0); | ||
717 | |||
718 | SET_TX_DESC_OWN(pdesc, 1); | ||
719 | |||
720 | SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); | ||
721 | |||
722 | SET_TX_DESC_FIRST_SEG(pdesc, 1); | ||
723 | SET_TX_DESC_LAST_SEG(pdesc, 1); | ||
724 | |||
725 | SET_TX_DESC_OFFSET(pdesc, 0x20); | ||
726 | |||
727 | SET_TX_DESC_USE_RATE(pdesc, 1); | ||
728 | |||
729 | if (!ieee80211_is_data_qos(fc)) | ||
730 | SET_TX_DESC_HWSEQ_EN(pdesc, 1); | ||
731 | |||
732 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, | ||
733 | "H2C Tx Cmd Content\n", | ||
734 | pdesc, TX_DESC_SIZE); | ||
735 | } | ||
736 | |||
737 | void rtl88ee_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val) | ||
738 | { | ||
739 | if (istx == true) { | ||
740 | switch (desc_name) { | ||
741 | case HW_DESC_OWN: | ||
742 | SET_TX_DESC_OWN(pdesc, 1); | ||
743 | break; | ||
744 | case HW_DESC_TX_NEXTDESC_ADDR: | ||
745 | SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); | ||
746 | break; | ||
747 | default: | ||
748 | RT_ASSERT(false, "ERR txdesc :%d not processed\n", | ||
749 | desc_name); | ||
750 | break; | ||
751 | } | ||
752 | } else { | ||
753 | switch (desc_name) { | ||
754 | case HW_DESC_RXOWN: | ||
755 | SET_RX_DESC_OWN(pdesc, 1); | ||
756 | break; | ||
757 | case HW_DESC_RXBUFF_ADDR: | ||
758 | SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *)val); | ||
759 | break; | ||
760 | case HW_DESC_RXPKT_LEN: | ||
761 | SET_RX_DESC_PKT_LEN(pdesc, *(u32 *)val); | ||
762 | break; | ||
763 | case HW_DESC_RXERO: | ||
764 | SET_RX_DESC_EOR(pdesc, 1); | ||
765 | break; | ||
766 | default: | ||
767 | RT_ASSERT(false, "ERR rxdesc :%d not processed\n", | ||
768 | desc_name); | ||
769 | break; | ||
770 | } | ||
771 | } | ||
772 | } | ||
773 | |||
774 | u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name) | ||
775 | { | ||
776 | u32 ret = 0; | ||
777 | |||
778 | if (istx == true) { | ||
779 | switch (desc_name) { | ||
780 | case HW_DESC_OWN: | ||
781 | ret = GET_TX_DESC_OWN(pdesc); | ||
782 | break; | ||
783 | case HW_DESC_TXBUFF_ADDR: | ||
784 | ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); | ||
785 | break; | ||
786 | default: | ||
787 | RT_ASSERT(false, "ERR txdesc :%d not processed\n", | ||
788 | desc_name); | ||
789 | break; | ||
790 | } | ||
791 | } else { | ||
792 | switch (desc_name) { | ||
793 | case HW_DESC_OWN: | ||
794 | ret = GET_RX_DESC_OWN(pdesc); | ||
795 | break; | ||
796 | case HW_DESC_RXPKT_LEN: | ||
797 | ret = GET_RX_DESC_PKT_LEN(pdesc); | ||
798 | break; | ||
799 | default: | ||
800 | RT_ASSERT(false, "ERR rxdesc :%d not processed\n", | ||
801 | desc_name); | ||
802 | break; | ||
803 | } | ||
804 | } | ||
805 | return ret; | ||
806 | } | ||
807 | |||
808 | void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) | ||
809 | { | ||
810 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
811 | if (hw_queue == BEACON_QUEUE) { | ||
812 | rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); | ||
813 | } else { | ||
814 | rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, | ||
815 | BIT(0) << (hw_queue)); | ||
816 | } | ||
817 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h new file mode 100644 index 000000000000..d3a02e73f53a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h | |||
@@ -0,0 +1,795 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92CE_TRX_H__ | ||
31 | #define __RTL92CE_TRX_H__ | ||
32 | |||
33 | #define TX_DESC_SIZE 64 | ||
34 | #define TX_DESC_AGGR_SUBFRAME_SIZE 32 | ||
35 | |||
36 | #define RX_DESC_SIZE 32 | ||
37 | #define RX_DRV_INFO_SIZE_UNIT 8 | ||
38 | |||
39 | #define TX_DESC_NEXT_DESC_OFFSET 40 | ||
40 | #define USB_HWDESC_HEADER_LEN 32 | ||
41 | #define CRCLENGTH 4 | ||
42 | |||
43 | #define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ | ||
44 | SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) | ||
45 | #define SET_TX_DESC_OFFSET(__pdesc, __val) \ | ||
46 | SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) | ||
47 | #define SET_TX_DESC_BMC(__pdesc, __val) \ | ||
48 | SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) | ||
49 | #define SET_TX_DESC_HTC(__pdesc, __val) \ | ||
50 | SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) | ||
51 | #define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ | ||
52 | SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) | ||
53 | #define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ | ||
54 | SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) | ||
55 | #define SET_TX_DESC_LINIP(__pdesc, __val) \ | ||
56 | SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) | ||
57 | #define SET_TX_DESC_NO_ACM(__pdesc, __val) \ | ||
58 | SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) | ||
59 | #define SET_TX_DESC_GF(__pdesc, __val) \ | ||
60 | SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) | ||
61 | #define SET_TX_DESC_OWN(__pdesc, __val) \ | ||
62 | SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) | ||
63 | |||
64 | #define GET_TX_DESC_PKT_SIZE(__pdesc) \ | ||
65 | LE_BITS_TO_4BYTE(__pdesc, 0, 16) | ||
66 | #define GET_TX_DESC_OFFSET(__pdesc) \ | ||
67 | LE_BITS_TO_4BYTE(__pdesc, 16, 8) | ||
68 | #define GET_TX_DESC_BMC(__pdesc) \ | ||
69 | LE_BITS_TO_4BYTE(__pdesc, 24, 1) | ||
70 | #define GET_TX_DESC_HTC(__pdesc) \ | ||
71 | LE_BITS_TO_4BYTE(__pdesc, 25, 1) | ||
72 | #define GET_TX_DESC_LAST_SEG(__pdesc) \ | ||
73 | LE_BITS_TO_4BYTE(__pdesc, 26, 1) | ||
74 | #define GET_TX_DESC_FIRST_SEG(__pdesc) \ | ||
75 | LE_BITS_TO_4BYTE(__pdesc, 27, 1) | ||
76 | #define GET_TX_DESC_LINIP(__pdesc) \ | ||
77 | LE_BITS_TO_4BYTE(__pdesc, 28, 1) | ||
78 | #define GET_TX_DESC_NO_ACM(__pdesc) \ | ||
79 | LE_BITS_TO_4BYTE(__pdesc, 29, 1) | ||
80 | #define GET_TX_DESC_GF(__pdesc) \ | ||
81 | LE_BITS_TO_4BYTE(__pdesc, 30, 1) | ||
82 | #define GET_TX_DESC_OWN(__pdesc) \ | ||
83 | LE_BITS_TO_4BYTE(__pdesc, 31, 1) | ||
84 | |||
85 | #define SET_TX_DESC_MACID(__pdesc, __val) \ | ||
86 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 6, __val) | ||
87 | #define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ | ||
88 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) | ||
89 | #define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ | ||
90 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) | ||
91 | #define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ | ||
92 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) | ||
93 | #define SET_TX_DESC_PIFS(__pdesc, __val) \ | ||
94 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) | ||
95 | #define SET_TX_DESC_RATE_ID(__pdesc, __val) \ | ||
96 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val) | ||
97 | #define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ | ||
98 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val) | ||
99 | #define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ | ||
100 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) | ||
101 | #define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ | ||
102 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) | ||
103 | #define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ | ||
104 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 26, 5, __val) | ||
105 | #define SET_TX_DESC_PADDING_LEN(__pdesc, __val) \ | ||
106 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val) | ||
107 | |||
108 | #define GET_TX_DESC_MACID(__pdesc) \ | ||
109 | LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) | ||
110 | #define GET_TX_DESC_AGG_ENABLE(__pdesc) \ | ||
111 | LE_BITS_TO_4BYTE(__pdesc+4, 5, 1) | ||
112 | #define GET_TX_DESC_AGG_BREAK(__pdesc) \ | ||
113 | LE_BITS_TO_4BYTE(__pdesc+4, 6, 1) | ||
114 | #define GET_TX_DESC_RDG_ENABLE(__pdesc) \ | ||
115 | LE_BITS_TO_4BYTE(__pdesc+4, 7, 1) | ||
116 | #define GET_TX_DESC_QUEUE_SEL(__pdesc) \ | ||
117 | LE_BITS_TO_4BYTE(__pdesc+4, 8, 5) | ||
118 | #define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ | ||
119 | LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) | ||
120 | #define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ | ||
121 | LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) | ||
122 | #define GET_TX_DESC_PIFS(__pdesc) \ | ||
123 | LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) | ||
124 | #define GET_TX_DESC_RATE_ID(__pdesc) \ | ||
125 | LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) | ||
126 | #define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ | ||
127 | LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) | ||
128 | #define GET_TX_DESC_EN_DESC_ID(__pdesc) \ | ||
129 | LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) | ||
130 | #define GET_TX_DESC_SEC_TYPE(__pdesc) \ | ||
131 | LE_BITS_TO_4BYTE(__pdesc+4, 22, 2) | ||
132 | #define GET_TX_DESC_PKT_OFFSET(__pdesc) \ | ||
133 | LE_BITS_TO_4BYTE(__pdesc+4, 24, 8) | ||
134 | |||
135 | #define SET_TX_DESC_RTS_RC(__pdesc, __val) \ | ||
136 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val) | ||
137 | #define SET_TX_DESC_DATA_RC(__pdesc, __val) \ | ||
138 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val) | ||
139 | #define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ | ||
140 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) | ||
141 | #define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ | ||
142 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) | ||
143 | #define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ | ||
144 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) | ||
145 | #define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ | ||
146 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) | ||
147 | #define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ | ||
148 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) | ||
149 | #define SET_TX_DESC_RAW(__pdesc, __val) \ | ||
150 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) | ||
151 | #define SET_TX_DESC_CCX(__pdesc, __val) \ | ||
152 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) | ||
153 | #define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ | ||
154 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) | ||
155 | #define SET_TX_DESC_BT_INT(__pdesc, __val) \ | ||
156 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) | ||
157 | #define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ | ||
158 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val) | ||
159 | #define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ | ||
160 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val) | ||
161 | #define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ | ||
162 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val) | ||
163 | #define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ | ||
164 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val) | ||
165 | #define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ | ||
166 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val) | ||
167 | |||
168 | #define GET_TX_DESC_RTS_RC(__pdesc) \ | ||
169 | LE_BITS_TO_4BYTE(__pdesc+8, 0, 6) | ||
170 | #define GET_TX_DESC_DATA_RC(__pdesc) \ | ||
171 | LE_BITS_TO_4BYTE(__pdesc+8, 6, 6) | ||
172 | #define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ | ||
173 | LE_BITS_TO_4BYTE(__pdesc+8, 14, 2) | ||
174 | #define GET_TX_DESC_MORE_FRAG(__pdesc) \ | ||
175 | LE_BITS_TO_4BYTE(__pdesc+8, 17, 1) | ||
176 | #define GET_TX_DESC_RAW(__pdesc) \ | ||
177 | LE_BITS_TO_4BYTE(__pdesc+8, 18, 1) | ||
178 | #define GET_TX_DESC_CCX(__pdesc) \ | ||
179 | LE_BITS_TO_4BYTE(__pdesc+8, 19, 1) | ||
180 | #define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ | ||
181 | LE_BITS_TO_4BYTE(__pdesc+8, 20, 3) | ||
182 | #define GET_TX_DESC_ANTSEL_A(__pdesc) \ | ||
183 | LE_BITS_TO_4BYTE(__pdesc+8, 24, 1) | ||
184 | #define GET_TX_DESC_ANTSEL_B(__pdesc) \ | ||
185 | LE_BITS_TO_4BYTE(__pdesc+8, 25, 1) | ||
186 | #define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ | ||
187 | LE_BITS_TO_4BYTE(__pdesc+8, 26, 2) | ||
188 | #define GET_TX_DESC_TX_ANTL(__pdesc) \ | ||
189 | LE_BITS_TO_4BYTE(__pdesc+8, 28, 2) | ||
190 | #define GET_TX_DESC_TX_ANT_HT(__pdesc) \ | ||
191 | LE_BITS_TO_4BYTE(__pdesc+8, 30, 2) | ||
192 | |||
193 | #define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ | ||
194 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val) | ||
195 | #define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ | ||
196 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val) | ||
197 | #define SET_TX_DESC_SEQ(__pdesc, __val) \ | ||
198 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val) | ||
199 | #define SET_TX_DESC_CPU_HANDLE(__pdesc, __val) \ | ||
200 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 1, __val) | ||
201 | #define SET_TX_DESC_TAG1(__pdesc, __val) \ | ||
202 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 29, 1, __val) | ||
203 | #define SET_TX_DESC_TRIGGER_INT(__pdesc, __val) \ | ||
204 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val) | ||
205 | #define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ | ||
206 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val) | ||
207 | |||
208 | |||
209 | #define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ | ||
210 | LE_BITS_TO_4BYTE(__pdesc+12, 0, 8) | ||
211 | #define GET_TX_DESC_TAIL_PAGE(__pdesc) \ | ||
212 | LE_BITS_TO_4BYTE(__pdesc+12, 8, 8) | ||
213 | #define GET_TX_DESC_SEQ(__pdesc) \ | ||
214 | LE_BITS_TO_4BYTE(__pdesc+12, 16, 12) | ||
215 | |||
216 | |||
217 | #define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ | ||
218 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val) | ||
219 | #define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ | ||
220 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val) | ||
221 | #define SET_TX_DESC_QOS(__pdesc, __val) \ | ||
222 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val) | ||
223 | #define SET_TX_DESC_HWSEQ_SSN(__pdesc, __val) \ | ||
224 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val) | ||
225 | #define SET_TX_DESC_USE_RATE(__pdesc, __val) \ | ||
226 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val) | ||
227 | #define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ | ||
228 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val) | ||
229 | #define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ | ||
230 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val) | ||
231 | #define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ | ||
232 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val) | ||
233 | #define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ | ||
234 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val) | ||
235 | #define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ | ||
236 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val) | ||
237 | #define SET_TX_DESC_PORT_ID(__pdesc, __val) \ | ||
238 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val) | ||
239 | #define SET_TX_DESC_PWR_STATUS(__pdesc, __val) \ | ||
240 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 15, 3, __val) | ||
241 | #define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ | ||
242 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val) | ||
243 | #define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ | ||
244 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val) | ||
245 | #define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ | ||
246 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val) | ||
247 | #define SET_TX_DESC_TX_STBC(__pdesc, __val) \ | ||
248 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val) | ||
249 | #define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ | ||
250 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val) | ||
251 | #define SET_TX_DESC_DATA_BW(__pdesc, __val) \ | ||
252 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val) | ||
253 | #define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ | ||
254 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val) | ||
255 | #define SET_TX_DESC_RTS_BW(__pdesc, __val) \ | ||
256 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val) | ||
257 | #define SET_TX_DESC_RTS_SC(__pdesc, __val) \ | ||
258 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val) | ||
259 | #define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ | ||
260 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) | ||
261 | |||
262 | #define GET_TX_DESC_RTS_RATE(__pdesc) \ | ||
263 | LE_BITS_TO_4BYTE(__pdesc+16, 0, 5) | ||
264 | #define GET_TX_DESC_AP_DCFE(__pdesc) \ | ||
265 | LE_BITS_TO_4BYTE(__pdesc+16, 5, 1) | ||
266 | #define GET_TX_DESC_QOS(__pdesc) \ | ||
267 | LE_BITS_TO_4BYTE(__pdesc+16, 6, 1) | ||
268 | #define GET_TX_DESC_HWSEQ_EN(__pdesc) \ | ||
269 | LE_BITS_TO_4BYTE(__pdesc+16, 7, 1) | ||
270 | #define GET_TX_DESC_USE_RATE(__pdesc) \ | ||
271 | LE_BITS_TO_4BYTE(__pdesc+16, 8, 1) | ||
272 | #define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ | ||
273 | LE_BITS_TO_4BYTE(__pdesc+16, 9, 1) | ||
274 | #define GET_TX_DESC_DISABLE_FB(__pdesc) \ | ||
275 | LE_BITS_TO_4BYTE(__pdesc+16, 10, 1) | ||
276 | #define GET_TX_DESC_CTS2SELF(__pdesc) \ | ||
277 | LE_BITS_TO_4BYTE(__pdesc+16, 11, 1) | ||
278 | #define GET_TX_DESC_RTS_ENABLE(__pdesc) \ | ||
279 | LE_BITS_TO_4BYTE(__pdesc+16, 12, 1) | ||
280 | #define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ | ||
281 | LE_BITS_TO_4BYTE(__pdesc+16, 13, 1) | ||
282 | #define GET_TX_DESC_PORT_ID(__pdesc) \ | ||
283 | LE_BITS_TO_4BYTE(__pdesc+16, 14, 1) | ||
284 | #define GET_TX_DESC_WAIT_DCTS(__pdesc) \ | ||
285 | LE_BITS_TO_4BYTE(__pdesc+16, 18, 1) | ||
286 | #define GET_TX_DESC_CTS2AP_EN(__pdesc) \ | ||
287 | LE_BITS_TO_4BYTE(__pdesc+16, 19, 1) | ||
288 | #define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ | ||
289 | LE_BITS_TO_4BYTE(__pdesc+16, 20, 2) | ||
290 | #define GET_TX_DESC_TX_STBC(__pdesc) \ | ||
291 | LE_BITS_TO_4BYTE(__pdesc+16, 22, 2) | ||
292 | #define GET_TX_DESC_DATA_SHORT(__pdesc) \ | ||
293 | LE_BITS_TO_4BYTE(__pdesc+16, 24, 1) | ||
294 | #define GET_TX_DESC_DATA_BW(__pdesc) \ | ||
295 | LE_BITS_TO_4BYTE(__pdesc+16, 25, 1) | ||
296 | #define GET_TX_DESC_RTS_SHORT(__pdesc) \ | ||
297 | LE_BITS_TO_4BYTE(__pdesc+16, 26, 1) | ||
298 | #define GET_TX_DESC_RTS_BW(__pdesc) \ | ||
299 | LE_BITS_TO_4BYTE(__pdesc+16, 27, 1) | ||
300 | #define GET_TX_DESC_RTS_SC(__pdesc) \ | ||
301 | LE_BITS_TO_4BYTE(__pdesc+16, 28, 2) | ||
302 | #define GET_TX_DESC_RTS_STBC(__pdesc) \ | ||
303 | LE_BITS_TO_4BYTE(__pdesc+16, 30, 2) | ||
304 | |||
305 | #define SET_TX_DESC_TX_RATE(__pdesc, __val) \ | ||
306 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val) | ||
307 | #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ | ||
308 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val) | ||
309 | #define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ | ||
310 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) | ||
311 | #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ | ||
312 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val) | ||
313 | #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ | ||
314 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) | ||
315 | #define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ | ||
316 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val) | ||
317 | #define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ | ||
318 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val) | ||
319 | #define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ | ||
320 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val) | ||
321 | |||
322 | #define GET_TX_DESC_TX_RATE(__pdesc) \ | ||
323 | LE_BITS_TO_4BYTE(__pdesc+20, 0, 6) | ||
324 | #define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ | ||
325 | LE_BITS_TO_4BYTE(__pdesc+20, 6, 1) | ||
326 | #define GET_TX_DESC_CCX_TAG(__pdesc) \ | ||
327 | LE_BITS_TO_4BYTE(__pdesc+20, 7, 1) | ||
328 | #define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ | ||
329 | LE_BITS_TO_4BYTE(__pdesc+20, 8, 5) | ||
330 | #define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ | ||
331 | LE_BITS_TO_4BYTE(__pdesc+20, 13, 4) | ||
332 | #define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ | ||
333 | LE_BITS_TO_4BYTE(__pdesc+20, 17, 1) | ||
334 | #define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ | ||
335 | LE_BITS_TO_4BYTE(__pdesc+20, 18, 6) | ||
336 | #define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ | ||
337 | LE_BITS_TO_4BYTE(__pdesc+20, 24, 8) | ||
338 | |||
339 | #define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ | ||
340 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val) | ||
341 | #define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ | ||
342 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val) | ||
343 | #define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ | ||
344 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val) | ||
345 | #define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ | ||
346 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val) | ||
347 | #define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ | ||
348 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val) | ||
349 | #define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ | ||
350 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val) | ||
351 | #define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ | ||
352 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val) | ||
353 | #define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ | ||
354 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val) | ||
355 | |||
356 | #define GET_TX_DESC_TXAGC_A(__pdesc) \ | ||
357 | LE_BITS_TO_4BYTE(__pdesc+24, 0, 5) | ||
358 | #define GET_TX_DESC_TXAGC_B(__pdesc) \ | ||
359 | LE_BITS_TO_4BYTE(__pdesc+24, 5, 5) | ||
360 | #define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ | ||
361 | LE_BITS_TO_4BYTE(__pdesc+24, 10, 1) | ||
362 | #define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ | ||
363 | LE_BITS_TO_4BYTE(__pdesc+24, 11, 5) | ||
364 | #define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ | ||
365 | LE_BITS_TO_4BYTE(__pdesc+24, 16, 4) | ||
366 | #define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ | ||
367 | LE_BITS_TO_4BYTE(__pdesc+24, 20, 4) | ||
368 | #define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ | ||
369 | LE_BITS_TO_4BYTE(__pdesc+24, 24, 4) | ||
370 | #define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ | ||
371 | LE_BITS_TO_4BYTE(__pdesc+24, 28, 4) | ||
372 | |||
373 | #define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ | ||
374 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) | ||
375 | #define SET_TX_DESC_SW_OFFSET30(__pdesc, __val) \ | ||
376 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 8, __val) | ||
377 | #define SET_TX_DESC_SW_OFFSET31(__pdesc, __val) \ | ||
378 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val) | ||
379 | #define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \ | ||
380 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 29, 1, __val) | ||
381 | #define SET_TX_DESC_NULL_0(__pdesc, __val) \ | ||
382 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val) | ||
383 | #define SET_TX_DESC_NULL_1(__pdesc, __val) \ | ||
384 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val) | ||
385 | |||
386 | #define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ | ||
387 | LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) | ||
388 | |||
389 | |||
390 | #define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ | ||
391 | SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val) | ||
392 | #define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ | ||
393 | SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val) | ||
394 | |||
395 | #define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ | ||
396 | LE_BITS_TO_4BYTE(__pdesc+32, 0, 32) | ||
397 | #define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ | ||
398 | LE_BITS_TO_4BYTE(__pdesc+36, 0, 32) | ||
399 | |||
400 | #define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ | ||
401 | SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) | ||
402 | #define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ | ||
403 | SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val) | ||
404 | |||
405 | #define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ | ||
406 | LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) | ||
407 | #define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ | ||
408 | LE_BITS_TO_4BYTE(__pdesc+44, 0, 32) | ||
409 | |||
410 | #define GET_RX_DESC_PKT_LEN(__pdesc) \ | ||
411 | LE_BITS_TO_4BYTE(__pdesc, 0, 14) | ||
412 | #define GET_RX_DESC_CRC32(__pdesc) \ | ||
413 | LE_BITS_TO_4BYTE(__pdesc, 14, 1) | ||
414 | #define GET_RX_DESC_ICV(__pdesc) \ | ||
415 | LE_BITS_TO_4BYTE(__pdesc, 15, 1) | ||
416 | #define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ | ||
417 | LE_BITS_TO_4BYTE(__pdesc, 16, 4) | ||
418 | #define GET_RX_DESC_SECURITY(__pdesc) \ | ||
419 | LE_BITS_TO_4BYTE(__pdesc, 20, 3) | ||
420 | #define GET_RX_DESC_QOS(__pdesc) \ | ||
421 | LE_BITS_TO_4BYTE(__pdesc, 23, 1) | ||
422 | #define GET_RX_DESC_SHIFT(__pdesc) \ | ||
423 | LE_BITS_TO_4BYTE(__pdesc, 24, 2) | ||
424 | #define GET_RX_DESC_PHYST(__pdesc) \ | ||
425 | LE_BITS_TO_4BYTE(__pdesc, 26, 1) | ||
426 | #define GET_RX_DESC_SWDEC(__pdesc) \ | ||
427 | LE_BITS_TO_4BYTE(__pdesc, 27, 1) | ||
428 | #define GET_RX_DESC_LS(__pdesc) \ | ||
429 | LE_BITS_TO_4BYTE(__pdesc, 28, 1) | ||
430 | #define GET_RX_DESC_FS(__pdesc) \ | ||
431 | LE_BITS_TO_4BYTE(__pdesc, 29, 1) | ||
432 | #define GET_RX_DESC_EOR(__pdesc) \ | ||
433 | LE_BITS_TO_4BYTE(__pdesc, 30, 1) | ||
434 | #define GET_RX_DESC_OWN(__pdesc) \ | ||
435 | LE_BITS_TO_4BYTE(__pdesc, 31, 1) | ||
436 | |||
437 | #define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ | ||
438 | SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) | ||
439 | #define SET_RX_DESC_EOR(__pdesc, __val) \ | ||
440 | SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) | ||
441 | #define SET_RX_DESC_OWN(__pdesc, __val) \ | ||
442 | SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) | ||
443 | |||
444 | #define GET_RX_DESC_MACID(__pdesc) \ | ||
445 | LE_BITS_TO_4BYTE(__pdesc+4, 0, 6) | ||
446 | #define GET_RX_DESC_PAGGR(__pdesc) \ | ||
447 | LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) | ||
448 | #define GET_RX_DESC_FAGGR(__pdesc) \ | ||
449 | LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) | ||
450 | #define GET_RX_DESC_A1_FIT(__pdesc) \ | ||
451 | LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) | ||
452 | #define GET_RX_DESC_A2_FIT(__pdesc) \ | ||
453 | LE_BITS_TO_4BYTE(__pdesc+4, 20, 4) | ||
454 | #define GET_RX_DESC_PAM(__pdesc) \ | ||
455 | LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) | ||
456 | #define GET_RX_DESC_PWR(__pdesc) \ | ||
457 | LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) | ||
458 | #define GET_RX_DESC_MD(__pdesc) \ | ||
459 | LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) | ||
460 | #define GET_RX_DESC_MF(__pdesc) \ | ||
461 | LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) | ||
462 | #define GET_RX_DESC_TYPE(__pdesc) \ | ||
463 | LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) | ||
464 | #define GET_RX_DESC_MC(__pdesc) \ | ||
465 | LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) | ||
466 | #define GET_RX_DESC_BC(__pdesc) \ | ||
467 | LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) | ||
468 | #define GET_RX_DESC_SEQ(__pdesc) \ | ||
469 | LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) | ||
470 | #define GET_RX_DESC_FRAG(__pdesc) \ | ||
471 | LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) | ||
472 | |||
473 | #define GET_RX_DESC_RXMCS(__pdesc) \ | ||
474 | LE_BITS_TO_4BYTE(__pdesc+12, 0, 6) | ||
475 | #define GET_RX_DESC_RXHT(__pdesc) \ | ||
476 | LE_BITS_TO_4BYTE(__pdesc+12, 6, 1) | ||
477 | #define GET_RX_STATUS_DESC_RX_GF(__pdesc) \ | ||
478 | LE_BITS_TO_4BYTE(__pdesc+12, 7, 1) | ||
479 | #define GET_RX_DESC_SPLCP(__pdesc) \ | ||
480 | LE_BITS_TO_4BYTE(__pdesc+12, 8, 1) | ||
481 | #define GET_RX_DESC_BW(__pdesc) \ | ||
482 | LE_BITS_TO_4BYTE(__pdesc+12, 9, 1) | ||
483 | #define GET_RX_DESC_HTC(__pdesc) \ | ||
484 | LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) | ||
485 | #define GET_RX_STATUS_DESC_EOSP(__pdesc) \ | ||
486 | LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) | ||
487 | #define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ | ||
488 | LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) | ||
489 | #define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ | ||
490 | LE_BITS_TO_4BYTE(__pdesc+12, 14, 2) | ||
491 | |||
492 | #define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ | ||
493 | LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) | ||
494 | #define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ | ||
495 | LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) | ||
496 | #define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ | ||
497 | LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) | ||
498 | |||
499 | #define GET_RX_DESC_IV1(__pdesc) \ | ||
500 | LE_BITS_TO_4BYTE(__pdesc+16, 0, 32) | ||
501 | #define GET_RX_DESC_TSFL(__pdesc) \ | ||
502 | LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) | ||
503 | |||
504 | #define GET_RX_DESC_BUFF_ADDR(__pdesc) \ | ||
505 | LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) | ||
506 | #define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ | ||
507 | LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) | ||
508 | |||
509 | #define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ | ||
510 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) | ||
511 | #define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ | ||
512 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) | ||
513 | |||
514 | /* TX report 2 format in Rx desc*/ | ||
515 | |||
516 | #define GET_RX_RPT2_DESC_PKT_LEN(__status) \ | ||
517 | LE_BITS_TO_4BYTE(__status, 0, 9) | ||
518 | #define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \ | ||
519 | LE_BITS_TO_4BYTE(__status+16, 0, 32) | ||
520 | #define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \ | ||
521 | LE_BITS_TO_4BYTE(__status+20, 0, 32) | ||
522 | |||
523 | #define SET_EARLYMODE_PKTNUM(__paddr, __value) \ | ||
524 | SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value) | ||
525 | #define SET_EARLYMODE_LEN0(__paddr, __value) \ | ||
526 | SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value) | ||
527 | #define SET_EARLYMODE_LEN1(__paddr, __value) \ | ||
528 | SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value) | ||
529 | #define SET_EARLYMODE_LEN2_1(__paddr, __value) \ | ||
530 | SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value) | ||
531 | #define SET_EARLYMODE_LEN2_2(__paddr, __value) \ | ||
532 | SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value) | ||
533 | #define SET_EARLYMODE_LEN3(__paddr, __value) \ | ||
534 | SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value) | ||
535 | #define SET_EARLYMODE_LEN4(__paddr, __value) \ | ||
536 | SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value) | ||
537 | |||
538 | #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ | ||
539 | do { \ | ||
540 | if (_size > TX_DESC_NEXT_DESC_OFFSET) \ | ||
541 | memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ | ||
542 | else \ | ||
543 | memset(__pdesc, 0, _size); \ | ||
544 | } while (0) | ||
545 | |||
546 | #define RTL8188_RX_HAL_IS_CCK_RATE(rxmcs)\ | ||
547 | (rxmcs == DESC92C_RATE1M ||\ | ||
548 | rxmcs == DESC92C_RATE2M ||\ | ||
549 | rxmcs == DESC92C_RATE5_5M ||\ | ||
550 | rxmcs == DESC92C_RATE11M) | ||
551 | |||
552 | struct phy_rx_agc_info_t { | ||
553 | #if __LITTLE_ENDIAN | ||
554 | u8 gain:7, trsw:1; | ||
555 | #else | ||
556 | u8 trsw:1, gain:7; | ||
557 | #endif | ||
558 | }; | ||
559 | struct phy_status_rpt { | ||
560 | struct phy_rx_agc_info_t path_agc[2]; | ||
561 | u8 ch_corr[2]; | ||
562 | u8 cck_sig_qual_ofdm_pwdb_all; | ||
563 | u8 cck_agc_rpt_ofdm_cfosho_a; | ||
564 | u8 cck_rpt_b_ofdm_cfosho_b; | ||
565 | u8 rsvd_1; | ||
566 | u8 noise_power_db_msb; | ||
567 | u8 path_cfotail[2]; | ||
568 | u8 pcts_mask[2]; | ||
569 | u8 stream_rxevm[2]; | ||
570 | u8 path_rxsnr[2]; | ||
571 | u8 noise_power_db_lsb; | ||
572 | u8 rsvd_2[3]; | ||
573 | u8 stream_csi[2]; | ||
574 | u8 stream_target_csi[2]; | ||
575 | u8 sig_evm; | ||
576 | u8 rsvd_3; | ||
577 | #if __LITTLE_ENDIAN | ||
578 | u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ | ||
579 | u8 sgi_en:1; | ||
580 | u8 rxsc:2; | ||
581 | u8 idle_long:1; | ||
582 | u8 r_ant_train_en:1; | ||
583 | u8 ant_sel_b:1; | ||
584 | u8 ant_sel:1; | ||
585 | #else /* _BIG_ENDIAN_ */ | ||
586 | u8 ant_sel:1; | ||
587 | u8 ant_sel_b:1; | ||
588 | u8 r_ant_train_en:1; | ||
589 | u8 idle_long:1; | ||
590 | u8 rxsc:2; | ||
591 | u8 sgi_en:1; | ||
592 | u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ | ||
593 | #endif | ||
594 | } __packed; | ||
595 | |||
596 | struct rx_fwinfo_88e { | ||
597 | u8 gain_trsw[4]; | ||
598 | u8 pwdb_all; | ||
599 | u8 cfosho[4]; | ||
600 | u8 cfotail[4]; | ||
601 | char rxevm[2]; | ||
602 | char rxsnr[4]; | ||
603 | u8 pdsnr[2]; | ||
604 | u8 csi_current[2]; | ||
605 | u8 csi_target[2]; | ||
606 | u8 sigevm; | ||
607 | u8 max_ex_pwr; | ||
608 | u8 ex_intf_flag:1; | ||
609 | u8 sgi_en:1; | ||
610 | u8 rxsc:2; | ||
611 | u8 reserve:4; | ||
612 | } __packed; | ||
613 | |||
614 | struct tx_desc_88e { | ||
615 | u32 pktsize:16; | ||
616 | u32 offset:8; | ||
617 | u32 bmc:1; | ||
618 | u32 htc:1; | ||
619 | u32 lastseg:1; | ||
620 | u32 firstseg:1; | ||
621 | u32 linip:1; | ||
622 | u32 noacm:1; | ||
623 | u32 gf:1; | ||
624 | u32 own:1; | ||
625 | |||
626 | u32 macid:6; | ||
627 | u32 rsvd0:2; | ||
628 | u32 queuesel:5; | ||
629 | u32 rd_nav_ext:1; | ||
630 | u32 lsig_txop_en:1; | ||
631 | u32 pifs:1; | ||
632 | u32 rateid:4; | ||
633 | u32 nav_usehdr:1; | ||
634 | u32 en_descid:1; | ||
635 | u32 sectype:2; | ||
636 | u32 pktoffset:8; | ||
637 | |||
638 | u32 rts_rc:6; | ||
639 | u32 data_rc:6; | ||
640 | u32 agg_en:1; | ||
641 | u32 rdg_en:1; | ||
642 | u32 bar_retryht:2; | ||
643 | u32 agg_break:1; | ||
644 | u32 morefrag:1; | ||
645 | u32 raw:1; | ||
646 | u32 ccx:1; | ||
647 | u32 ampdudensity:3; | ||
648 | u32 bt_int:1; | ||
649 | u32 ant_sela:1; | ||
650 | u32 ant_selb:1; | ||
651 | u32 txant_cck:2; | ||
652 | u32 txant_l:2; | ||
653 | u32 txant_ht:2; | ||
654 | |||
655 | u32 nextheadpage:8; | ||
656 | u32 tailpage:8; | ||
657 | u32 seq:12; | ||
658 | u32 cpu_handle:1; | ||
659 | u32 tag1:1; | ||
660 | u32 trigger_int:1; | ||
661 | u32 hwseq_en:1; | ||
662 | |||
663 | u32 rtsrate:5; | ||
664 | u32 apdcfe:1; | ||
665 | u32 qos:1; | ||
666 | u32 hwseq_ssn:1; | ||
667 | u32 userrate:1; | ||
668 | u32 dis_rtsfb:1; | ||
669 | u32 dis_datafb:1; | ||
670 | u32 cts2self:1; | ||
671 | u32 rts_en:1; | ||
672 | u32 hwrts_en:1; | ||
673 | u32 portid:1; | ||
674 | u32 pwr_status:3; | ||
675 | u32 waitdcts:1; | ||
676 | u32 cts2ap_en:1; | ||
677 | u32 txsc:2; | ||
678 | u32 stbc:2; | ||
679 | u32 txshort:1; | ||
680 | u32 txbw:1; | ||
681 | u32 rtsshort:1; | ||
682 | u32 rtsbw:1; | ||
683 | u32 rtssc:2; | ||
684 | u32 rtsstbc:2; | ||
685 | |||
686 | u32 txrate:6; | ||
687 | u32 shortgi:1; | ||
688 | u32 ccxt:1; | ||
689 | u32 txrate_fb_lmt:5; | ||
690 | u32 rtsrate_fb_lmt:4; | ||
691 | u32 retrylmt_en:1; | ||
692 | u32 txretrylmt:6; | ||
693 | u32 usb_txaggnum:8; | ||
694 | |||
695 | u32 txagca:5; | ||
696 | u32 txagcb:5; | ||
697 | u32 usemaxlen:1; | ||
698 | u32 maxaggnum:5; | ||
699 | u32 mcsg1maxlen:4; | ||
700 | u32 mcsg2maxlen:4; | ||
701 | u32 mcsg3maxlen:4; | ||
702 | u32 mcs7sgimaxlen:4; | ||
703 | |||
704 | u32 txbuffersize:16; | ||
705 | u32 sw_offset30:8; | ||
706 | u32 sw_offset31:4; | ||
707 | u32 rsvd1:1; | ||
708 | u32 antsel_c:1; | ||
709 | u32 null_0:1; | ||
710 | u32 null_1:1; | ||
711 | |||
712 | u32 txbuffaddr; | ||
713 | u32 txbufferaddr64; | ||
714 | u32 nextdescaddress; | ||
715 | u32 nextdescaddress64; | ||
716 | |||
717 | u32 reserve_pass_pcie_mm_limit[4]; | ||
718 | } __packed; | ||
719 | |||
720 | struct rx_desc_88e { | ||
721 | u32 length:14; | ||
722 | u32 crc32:1; | ||
723 | u32 icverror:1; | ||
724 | u32 drv_infosize:4; | ||
725 | u32 security:3; | ||
726 | u32 qos:1; | ||
727 | u32 shift:2; | ||
728 | u32 phystatus:1; | ||
729 | u32 swdec:1; | ||
730 | u32 lastseg:1; | ||
731 | u32 firstseg:1; | ||
732 | u32 eor:1; | ||
733 | u32 own:1; | ||
734 | |||
735 | u32 macid:6; | ||
736 | u32 tid:4; | ||
737 | u32 hwrsvd:5; | ||
738 | u32 paggr:1; | ||
739 | u32 faggr:1; | ||
740 | u32 a1_fit:4; | ||
741 | u32 a2_fit:4; | ||
742 | u32 pam:1; | ||
743 | u32 pwr:1; | ||
744 | u32 moredata:1; | ||
745 | u32 morefrag:1; | ||
746 | u32 type:2; | ||
747 | u32 mc:1; | ||
748 | u32 bc:1; | ||
749 | |||
750 | u32 seq:12; | ||
751 | u32 frag:4; | ||
752 | u32 nextpktlen:14; | ||
753 | u32 nextind:1; | ||
754 | u32 rsvd:1; | ||
755 | |||
756 | u32 rxmcs:6; | ||
757 | u32 rxht:1; | ||
758 | u32 amsdu:1; | ||
759 | u32 splcp:1; | ||
760 | u32 bandwidth:1; | ||
761 | u32 htc:1; | ||
762 | u32 tcpchk_rpt:1; | ||
763 | u32 ipcchk_rpt:1; | ||
764 | u32 tcpchk_valid:1; | ||
765 | u32 hwpcerr:1; | ||
766 | u32 hwpcind:1; | ||
767 | u32 iv0:16; | ||
768 | |||
769 | u32 iv1; | ||
770 | |||
771 | u32 tsfl; | ||
772 | |||
773 | u32 bufferaddress; | ||
774 | u32 bufferaddress64; | ||
775 | |||
776 | } __packed; | ||
777 | |||
778 | void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, | ||
779 | struct ieee80211_hdr *hdr, u8 *pdesc_tx, | ||
780 | struct ieee80211_tx_info *info, | ||
781 | struct ieee80211_sta *sta, | ||
782 | struct sk_buff *skb, | ||
783 | u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); | ||
784 | bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, | ||
785 | struct rtl_stats *status, | ||
786 | struct ieee80211_rx_status *rx_status, | ||
787 | u8 *pdesc, struct sk_buff *skb); | ||
788 | void rtl88ee_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); | ||
789 | u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name); | ||
790 | void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); | ||
791 | void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, | ||
792 | bool b_firstseg, bool b_lastseg, | ||
793 | struct sk_buff *skb); | ||
794 | |||
795 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index b793a659a465..926e2a34c766 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | |||
@@ -174,8 +174,8 @@ static void rtl92c_dm_diginit(struct ieee80211_hw *hw) | |||
174 | dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; | 174 | dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; |
175 | dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; | 175 | dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; |
176 | dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; | 176 | dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; |
177 | dm_digtable->rx_gain_range_max = DM_DIG_MAX; | 177 | dm_digtable->rx_gain_max = DM_DIG_MAX; |
178 | dm_digtable->rx_gain_range_min = DM_DIG_MIN; | 178 | dm_digtable->rx_gain_min = DM_DIG_MIN; |
179 | dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; | 179 | dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; |
180 | dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; | 180 | dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; |
181 | dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; | 181 | dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; |
@@ -300,11 +300,11 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) | |||
300 | } | 300 | } |
301 | 301 | ||
302 | if ((digtable->rssi_val_min + 10 - digtable->back_val) > | 302 | if ((digtable->rssi_val_min + 10 - digtable->back_val) > |
303 | digtable->rx_gain_range_max) | 303 | digtable->rx_gain_max) |
304 | digtable->cur_igvalue = digtable->rx_gain_range_max; | 304 | digtable->cur_igvalue = digtable->rx_gain_max; |
305 | else if ((digtable->rssi_val_min + 10 - | 305 | else if ((digtable->rssi_val_min + 10 - |
306 | digtable->back_val) < digtable->rx_gain_range_min) | 306 | digtable->back_val) < digtable->rx_gain_min) |
307 | digtable->cur_igvalue = digtable->rx_gain_range_min; | 307 | digtable->cur_igvalue = digtable->rx_gain_min; |
308 | else | 308 | else |
309 | digtable->cur_igvalue = digtable->rssi_val_min + 10 - | 309 | digtable->cur_igvalue = digtable->rssi_val_min + 10 - |
310 | digtable->back_val; | 310 | digtable->back_val; |
@@ -1147,75 +1147,6 @@ void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) | |||
1147 | } | 1147 | } |
1148 | EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask); | 1148 | EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask); |
1149 | 1149 | ||
1150 | static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) | ||
1151 | { | ||
1152 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1153 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1154 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1155 | struct rate_adaptive *p_ra = &(rtlpriv->ra); | ||
1156 | u32 low_rssi_thresh, high_rssi_thresh; | ||
1157 | struct ieee80211_sta *sta = NULL; | ||
1158 | |||
1159 | if (is_hal_stop(rtlhal)) { | ||
1160 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1161 | "<---- driver is going to unload\n"); | ||
1162 | return; | ||
1163 | } | ||
1164 | |||
1165 | if (!rtlpriv->dm.useramask) { | ||
1166 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1167 | "<---- driver does not control rate adaptive mask\n"); | ||
1168 | return; | ||
1169 | } | ||
1170 | |||
1171 | if (mac->link_state == MAC80211_LINKED && | ||
1172 | mac->opmode == NL80211_IFTYPE_STATION) { | ||
1173 | switch (p_ra->pre_ratr_state) { | ||
1174 | case DM_RATR_STA_HIGH: | ||
1175 | high_rssi_thresh = 50; | ||
1176 | low_rssi_thresh = 20; | ||
1177 | break; | ||
1178 | case DM_RATR_STA_MIDDLE: | ||
1179 | high_rssi_thresh = 55; | ||
1180 | low_rssi_thresh = 20; | ||
1181 | break; | ||
1182 | case DM_RATR_STA_LOW: | ||
1183 | high_rssi_thresh = 50; | ||
1184 | low_rssi_thresh = 25; | ||
1185 | break; | ||
1186 | default: | ||
1187 | high_rssi_thresh = 50; | ||
1188 | low_rssi_thresh = 20; | ||
1189 | break; | ||
1190 | } | ||
1191 | |||
1192 | if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) | ||
1193 | p_ra->ratr_state = DM_RATR_STA_HIGH; | ||
1194 | else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi_thresh) | ||
1195 | p_ra->ratr_state = DM_RATR_STA_MIDDLE; | ||
1196 | else | ||
1197 | p_ra->ratr_state = DM_RATR_STA_LOW; | ||
1198 | |||
1199 | if (p_ra->pre_ratr_state != p_ra->ratr_state) { | ||
1200 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, "RSSI = %ld\n", | ||
1201 | rtlpriv->dm.undec_sm_pwdb); | ||
1202 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1203 | "RSSI_LEVEL = %d\n", p_ra->ratr_state); | ||
1204 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1205 | "PreState = %d, CurState = %d\n", | ||
1206 | p_ra->pre_ratr_state, p_ra->ratr_state); | ||
1207 | |||
1208 | rcu_read_lock(); | ||
1209 | sta = ieee80211_find_sta(mac->vif, mac->bssid); | ||
1210 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | ||
1211 | p_ra->ratr_state); | ||
1212 | |||
1213 | p_ra->pre_ratr_state = p_ra->ratr_state; | ||
1214 | rcu_read_unlock(); | ||
1215 | } | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1219 | static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) | 1150 | static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) |
1220 | { | 1151 | { |
1221 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1152 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -1437,6 +1368,9 @@ void rtl92c_dm_watchdog(struct ieee80211_hw *hw) | |||
1437 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, | 1368 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, |
1438 | (u8 *) (&fw_ps_awake)); | 1369 | (u8 *) (&fw_ps_awake)); |
1439 | 1370 | ||
1371 | if (ppsc->p2p_ps_info.p2p_ps_mode) | ||
1372 | fw_ps_awake = false; | ||
1373 | |||
1440 | if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && | 1374 | if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && |
1441 | fw_ps_awake) | 1375 | fw_ps_awake) |
1442 | && (!ppsc->rfchange_inprogress)) { | 1376 | && (!ppsc->rfchange_inprogress)) { |
@@ -1446,7 +1380,7 @@ void rtl92c_dm_watchdog(struct ieee80211_hw *hw) | |||
1446 | rtl92c_dm_dynamic_bb_powersaving(hw); | 1380 | rtl92c_dm_dynamic_bb_powersaving(hw); |
1447 | rtl92c_dm_dynamic_txpower(hw); | 1381 | rtl92c_dm_dynamic_txpower(hw); |
1448 | rtl92c_dm_check_txpower_tracking(hw); | 1382 | rtl92c_dm_check_txpower_tracking(hw); |
1449 | rtl92c_dm_refresh_rate_adaptive_mask(hw); | 1383 | /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */ |
1450 | rtl92c_dm_bt_coexist(hw); | 1384 | rtl92c_dm_bt_coexist(hw); |
1451 | rtl92c_dm_check_edca_turbo(hw); | 1385 | rtl92c_dm_check_edca_turbo(hw); |
1452 | } | 1386 | } |
@@ -1651,7 +1585,7 @@ static void rtl92c_bt_set_normal(struct ieee80211_hw *hw) | |||
1651 | } | 1585 | } |
1652 | } | 1586 | } |
1653 | 1587 | ||
1654 | static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw) | 1588 | static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte) |
1655 | { | 1589 | { |
1656 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1590 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1657 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); | 1591 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); |
@@ -1673,9 +1607,9 @@ static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw) | |||
1673 | BT_RSSI_STATE_SPECIAL_LOW)) { | 1607 | BT_RSSI_STATE_SPECIAL_LOW)) { |
1674 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); | 1608 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); |
1675 | } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) { | 1609 | } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) { |
1676 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); | 1610 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); |
1677 | } else { | 1611 | } else { |
1678 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); | 1612 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); |
1679 | } | 1613 | } |
1680 | } | 1614 | } |
1681 | 1615 | ||
@@ -1726,12 +1660,17 @@ static void rtl92c_check_bt_change(struct ieee80211_hw *hw) | |||
1726 | { | 1660 | { |
1727 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1661 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1728 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); | 1662 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); |
1663 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1664 | u8 tmp1byte = 0; | ||
1729 | 1665 | ||
1666 | if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version) && | ||
1667 | rtlpcipriv->bt_coexist.bt_coexistence) | ||
1668 | tmp1byte |= BIT(5); | ||
1730 | if (rtlpcipriv->bt_coexist.bt_cur_state) { | 1669 | if (rtlpcipriv->bt_coexist.bt_cur_state) { |
1731 | if (rtlpcipriv->bt_coexist.bt_ant_isolation) | 1670 | if (rtlpcipriv->bt_coexist.bt_ant_isolation) |
1732 | rtl92c_bt_ant_isolation(hw); | 1671 | rtl92c_bt_ant_isolation(hw, tmp1byte); |
1733 | } else { | 1672 | } else { |
1734 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); | 1673 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); |
1735 | rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0, | 1674 | rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0, |
1736 | rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); | 1675 | rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); |
1737 | 1676 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 883f23ae9519..04a41628ceed 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | |||
@@ -552,7 +552,9 @@ void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) | |||
552 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); | 552 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); |
553 | 553 | ||
554 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); | 554 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); |
555 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1); | 555 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, |
556 | (rtlpriv->mac80211.p2p) ? | ||
557 | ppsc->smart_ps : 1); | ||
556 | SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, | 558 | SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, |
557 | ppsc->reg_max_lps_awakeintvl); | 559 | ppsc->reg_max_lps_awakeintvl); |
558 | 560 | ||
@@ -808,3 +810,98 @@ void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) | |||
808 | rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); | 810 | rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); |
809 | } | 811 | } |
810 | EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd); | 812 | EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd); |
813 | |||
814 | static void rtl92c_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) | ||
815 | { | ||
816 | u8 u1_ctwindow_period[1] = {ctwindow}; | ||
817 | |||
818 | rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); | ||
819 | } | ||
820 | |||
821 | void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | ||
822 | { | ||
823 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
824 | struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); | ||
825 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
826 | struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); | ||
827 | struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; | ||
828 | u8 i; | ||
829 | u16 ctwindow; | ||
830 | u32 start_time, tsf_low; | ||
831 | |||
832 | switch (p2p_ps_state) { | ||
833 | case P2P_PS_DISABLE: | ||
834 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); | ||
835 | memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t)); | ||
836 | break; | ||
837 | case P2P_PS_ENABLE: | ||
838 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); | ||
839 | /* update CTWindow value. */ | ||
840 | if (p2pinfo->ctwindow > 0) { | ||
841 | p2p_ps_offload->ctwindow_en = 1; | ||
842 | ctwindow = p2pinfo->ctwindow; | ||
843 | rtl92c_set_p2p_ctw_period_cmd(hw, ctwindow); | ||
844 | } | ||
845 | /* hw only support 2 set of NoA */ | ||
846 | for (i = 0; i < p2pinfo->noa_num; i++) { | ||
847 | /* To control the register setting for which NOA*/ | ||
848 | rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); | ||
849 | if (i == 0) | ||
850 | p2p_ps_offload->noa0_en = 1; | ||
851 | else | ||
852 | p2p_ps_offload->noa1_en = 1; | ||
853 | |||
854 | /* config P2P NoA Descriptor Register */ | ||
855 | rtl_write_dword(rtlpriv, 0x5E0, | ||
856 | p2pinfo->noa_duration[i]); | ||
857 | rtl_write_dword(rtlpriv, 0x5E4, | ||
858 | p2pinfo->noa_interval[i]); | ||
859 | |||
860 | /*Get Current TSF value */ | ||
861 | tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); | ||
862 | |||
863 | start_time = p2pinfo->noa_start_time[i]; | ||
864 | if (p2pinfo->noa_count_type[i] != 1) { | ||
865 | while (start_time <= (tsf_low+(50*1024))) { | ||
866 | start_time += p2pinfo->noa_interval[i]; | ||
867 | if (p2pinfo->noa_count_type[i] != 255) | ||
868 | p2pinfo->noa_count_type[i]--; | ||
869 | } | ||
870 | } | ||
871 | rtl_write_dword(rtlpriv, 0x5E8, start_time); | ||
872 | rtl_write_dword(rtlpriv, 0x5EC, | ||
873 | p2pinfo->noa_count_type[i]); | ||
874 | } | ||
875 | |||
876 | if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { | ||
877 | /* rst p2p circuit */ | ||
878 | rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); | ||
879 | |||
880 | p2p_ps_offload->offload_en = 1; | ||
881 | |||
882 | if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { | ||
883 | p2p_ps_offload->role = 1; | ||
884 | p2p_ps_offload->allstasleep = 0; | ||
885 | } else { | ||
886 | p2p_ps_offload->role = 0; | ||
887 | } | ||
888 | |||
889 | p2p_ps_offload->discovery = 0; | ||
890 | } | ||
891 | break; | ||
892 | case P2P_PS_SCAN: | ||
893 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); | ||
894 | p2p_ps_offload->discovery = 1; | ||
895 | break; | ||
896 | case P2P_PS_SCAN_DONE: | ||
897 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); | ||
898 | p2p_ps_offload->discovery = 0; | ||
899 | p2pinfo->p2p_ps_state = P2P_PS_ENABLE; | ||
900 | break; | ||
901 | default: | ||
902 | break; | ||
903 | } | ||
904 | |||
905 | rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); | ||
906 | } | ||
907 | EXPORT_SYMBOL_GPL(rtl92c_set_p2p_ps_offload_cmd); | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h index 780ea5b1e24c..15b2055e6212 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h | |||
@@ -67,6 +67,9 @@ enum rtl8192c_h2c_cmd { | |||
67 | H2C_RSVDPAGE = 3, | 67 | H2C_RSVDPAGE = 3, |
68 | H2C_RSSI_REPORT = 5, | 68 | H2C_RSSI_REPORT = 5, |
69 | H2C_RA_MASK = 6, | 69 | H2C_RA_MASK = 6, |
70 | H2C_MACID_PS_MODE = 7, | ||
71 | H2C_P2P_PS_OFFLOAD = 8, | ||
72 | H2C_P2P_PS_CTW_CMD = 32, | ||
70 | MAX_H2CCMD | 73 | MAX_H2CCMD |
71 | }; | 74 | }; |
72 | 75 | ||
@@ -95,5 +98,6 @@ void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); | |||
95 | void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); | 98 | void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); |
96 | void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); | 99 | void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); |
97 | void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len); | 100 | void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len); |
101 | void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); | ||
98 | 102 | ||
99 | #endif | 103 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 1b65db7fd651..a82b30a1996c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | |||
@@ -475,6 +475,9 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
475 | 475 | ||
476 | break; | 476 | break; |
477 | } | 477 | } |
478 | case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: | ||
479 | rtl92c_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); | ||
480 | break; | ||
478 | case HW_VAR_AID:{ | 481 | case HW_VAR_AID:{ |
479 | u16 u2btmp; | 482 | u16 u2btmp; |
480 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); | 483 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); |
@@ -505,6 +508,40 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
505 | break; | 508 | break; |
506 | 509 | ||
507 | } | 510 | } |
511 | case HW_VAR_FW_LPS_ACTION: { | ||
512 | bool enter_fwlps = *((bool *)val); | ||
513 | u8 rpwm_val, fw_pwrmode; | ||
514 | bool fw_current_inps; | ||
515 | |||
516 | if (enter_fwlps) { | ||
517 | rpwm_val = 0x02; /* RF off */ | ||
518 | fw_current_inps = true; | ||
519 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
520 | HW_VAR_FW_PSMODE_STATUS, | ||
521 | (u8 *)(&fw_current_inps)); | ||
522 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
523 | HW_VAR_H2C_FW_PWRMODE, | ||
524 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
525 | |||
526 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
527 | HW_VAR_SET_RPWM, | ||
528 | (u8 *)(&rpwm_val)); | ||
529 | } else { | ||
530 | rpwm_val = 0x0C; /* RF on */ | ||
531 | fw_pwrmode = FW_PS_ACTIVE_MODE; | ||
532 | fw_current_inps = false; | ||
533 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
534 | HW_VAR_SET_RPWM, | ||
535 | (u8 *)(&rpwm_val)); | ||
536 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
537 | HW_VAR_H2C_FW_PWRMODE, | ||
538 | (u8 *)(&fw_pwrmode)); | ||
539 | |||
540 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
541 | HW_VAR_FW_PSMODE_STATUS, | ||
542 | (u8 *)(&fw_current_inps)); | ||
543 | } | ||
544 | break; } | ||
508 | default: | 545 | default: |
509 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 546 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
510 | "switch case not processed\n"); | 547 | "switch case not processed\n"); |
@@ -1105,7 +1142,8 @@ static int _rtl92ce_set_media_status(struct ieee80211_hw *hw, | |||
1105 | type == NL80211_IFTYPE_STATION) { | 1142 | type == NL80211_IFTYPE_STATION) { |
1106 | _rtl92ce_stop_tx_beacon(hw); | 1143 | _rtl92ce_stop_tx_beacon(hw); |
1107 | _rtl92ce_enable_bcn_sub_func(hw); | 1144 | _rtl92ce_enable_bcn_sub_func(hw); |
1108 | } else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP) { | 1145 | } else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP || |
1146 | type == NL80211_IFTYPE_MESH_POINT) { | ||
1109 | _rtl92ce_resume_tx_beacon(hw); | 1147 | _rtl92ce_resume_tx_beacon(hw); |
1110 | _rtl92ce_disable_bcn_sub_func(hw); | 1148 | _rtl92ce_disable_bcn_sub_func(hw); |
1111 | } else { | 1149 | } else { |
@@ -1137,6 +1175,11 @@ static int _rtl92ce_set_media_status(struct ieee80211_hw *hw, | |||
1137 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | 1175 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
1138 | "Set Network type to AP!\n"); | 1176 | "Set Network type to AP!\n"); |
1139 | break; | 1177 | break; |
1178 | case NL80211_IFTYPE_MESH_POINT: | ||
1179 | bt_msr |= MSR_ADHOC; | ||
1180 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1181 | "Set Network type to Mesh Point!\n"); | ||
1182 | break; | ||
1140 | default: | 1183 | default: |
1141 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 1184 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
1142 | "Network type %d not supported!\n", type); | 1185 | "Network type %d not supported!\n", type); |
@@ -1184,7 +1227,8 @@ int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | |||
1184 | return -EOPNOTSUPP; | 1227 | return -EOPNOTSUPP; |
1185 | 1228 | ||
1186 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { | 1229 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { |
1187 | if (type != NL80211_IFTYPE_AP) | 1230 | if (type != NL80211_IFTYPE_AP && |
1231 | type != NL80211_IFTYPE_MESH_POINT) | ||
1188 | rtl92ce_set_check_bssid(hw, true); | 1232 | rtl92ce_set_check_bssid(hw, true); |
1189 | } else { | 1233 | } else { |
1190 | rtl92ce_set_check_bssid(hw, false); | 1234 | rtl92ce_set_check_bssid(hw, false); |
@@ -1459,7 +1503,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1459 | } | 1503 | } |
1460 | 1504 | ||
1461 | for (i = 0; i < 14; i++) { | 1505 | for (i = 0; i < 14; i++) { |
1462 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1506 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1463 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", | 1507 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", |
1464 | rf_path, i, | 1508 | rf_path, i, |
1465 | rtlefuse->txpwrlevel_cck[rf_path][i], | 1509 | rtlefuse->txpwrlevel_cck[rf_path][i], |
@@ -1500,11 +1544,11 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1500 | & 0xf0) >> 4); | 1544 | & 0xf0) >> 4); |
1501 | } | 1545 | } |
1502 | 1546 | ||
1503 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1547 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1504 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", | 1548 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", |
1505 | rf_path, i, | 1549 | rf_path, i, |
1506 | rtlefuse->pwrgroup_ht20[rf_path][i]); | 1550 | rtlefuse->pwrgroup_ht20[rf_path][i]); |
1507 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1551 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1508 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", | 1552 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", |
1509 | rf_path, i, | 1553 | rf_path, i, |
1510 | rtlefuse->pwrgroup_ht40[rf_path][i]); | 1554 | rtlefuse->pwrgroup_ht40[rf_path][i]); |
@@ -1545,19 +1589,19 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1545 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; | 1589 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; |
1546 | 1590 | ||
1547 | for (i = 0; i < 14; i++) | 1591 | for (i = 0; i < 14; i++) |
1548 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1592 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1549 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", | 1593 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", |
1550 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); | 1594 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); |
1551 | for (i = 0; i < 14; i++) | 1595 | for (i = 0; i < 14; i++) |
1552 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1596 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1553 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", | 1597 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", |
1554 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); | 1598 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); |
1555 | for (i = 0; i < 14; i++) | 1599 | for (i = 0; i < 14; i++) |
1556 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1600 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1557 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", | 1601 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", |
1558 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); | 1602 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); |
1559 | for (i = 0; i < 14; i++) | 1603 | for (i = 0; i < 14; i++) |
1560 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1604 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1561 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", | 1605 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", |
1562 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); | 1606 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); |
1563 | 1607 | ||
@@ -1565,7 +1609,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1565 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); | 1609 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); |
1566 | else | 1610 | else |
1567 | rtlefuse->eeprom_regulatory = 0; | 1611 | rtlefuse->eeprom_regulatory = 0; |
1568 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1612 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1569 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | 1613 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); |
1570 | 1614 | ||
1571 | if (!autoload_fail) { | 1615 | if (!autoload_fail) { |
@@ -1575,7 +1619,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1575 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; | 1619 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; |
1576 | rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; | 1620 | rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; |
1577 | } | 1621 | } |
1578 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", | 1622 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", |
1579 | rtlefuse->eeprom_tssi[RF90_PATH_A], | 1623 | rtlefuse->eeprom_tssi[RF90_PATH_A], |
1580 | rtlefuse->eeprom_tssi[RF90_PATH_B]); | 1624 | rtlefuse->eeprom_tssi[RF90_PATH_B]); |
1581 | 1625 | ||
@@ -1589,7 +1633,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1589 | rtlefuse->apk_thermalmeterignore = true; | 1633 | rtlefuse->apk_thermalmeterignore = true; |
1590 | 1634 | ||
1591 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; | 1635 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; |
1592 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1636 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1593 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | 1637 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); |
1594 | } | 1638 | } |
1595 | 1639 | ||
@@ -1629,6 +1673,21 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) | |||
1629 | if (rtlefuse->autoload_failflag) | 1673 | if (rtlefuse->autoload_failflag) |
1630 | return; | 1674 | return; |
1631 | 1675 | ||
1676 | rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; | ||
1677 | rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; | ||
1678 | rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; | ||
1679 | rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; | ||
1680 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1681 | "EEPROMId = 0x%4x\n", eeprom_id); | ||
1682 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1683 | "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); | ||
1684 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1685 | "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); | ||
1686 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1687 | "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); | ||
1688 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1689 | "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); | ||
1690 | |||
1632 | for (i = 0; i < 6; i += 2) { | 1691 | for (i = 0; i < 6; i += 2) { |
1633 | usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; | 1692 | usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; |
1634 | *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; | 1693 | *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; |
@@ -1766,6 +1825,9 @@ static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, | |||
1766 | ratr_value = sta->supp_rates[1] << 4; | 1825 | ratr_value = sta->supp_rates[1] << 4; |
1767 | else | 1826 | else |
1768 | ratr_value = sta->supp_rates[0]; | 1827 | ratr_value = sta->supp_rates[0]; |
1828 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
1829 | ratr_value = 0xfff; | ||
1830 | |||
1769 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | 1831 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | |
1770 | sta->ht_cap.mcs.rx_mask[0] << 12); | 1832 | sta->ht_cap.mcs.rx_mask[0] << 12); |
1771 | switch (wirelessmode) { | 1833 | switch (wirelessmode) { |
@@ -1860,7 +1922,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, | |||
1860 | 1922 | ||
1861 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; | 1923 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
1862 | wirelessmode = sta_entry->wireless_mode; | 1924 | wirelessmode = sta_entry->wireless_mode; |
1863 | if (mac->opmode == NL80211_IFTYPE_STATION) | 1925 | if (mac->opmode == NL80211_IFTYPE_STATION || |
1926 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
1864 | curtxbw_40mhz = mac->bw_40; | 1927 | curtxbw_40mhz = mac->bw_40; |
1865 | else if (mac->opmode == NL80211_IFTYPE_AP || | 1928 | else if (mac->opmode == NL80211_IFTYPE_AP || |
1866 | mac->opmode == NL80211_IFTYPE_ADHOC) | 1929 | mac->opmode == NL80211_IFTYPE_ADHOC) |
@@ -1870,6 +1933,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, | |||
1870 | ratr_bitmap = sta->supp_rates[1] << 4; | 1933 | ratr_bitmap = sta->supp_rates[1] << 4; |
1871 | else | 1934 | else |
1872 | ratr_bitmap = sta->supp_rates[0]; | 1935 | ratr_bitmap = sta->supp_rates[0]; |
1936 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
1937 | ratr_bitmap = 0xfff; | ||
1873 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | 1938 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | |
1874 | sta->ht_cap.mcs.rx_mask[0] << 12); | 1939 | sta->ht_cap.mcs.rx_mask[0] << 12); |
1875 | switch (wirelessmode) { | 1940 | switch (wirelessmode) { |
@@ -2135,7 +2200,8 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, | |||
2135 | macaddr = cam_const_broad; | 2200 | macaddr = cam_const_broad; |
2136 | entry_id = key_index; | 2201 | entry_id = key_index; |
2137 | } else { | 2202 | } else { |
2138 | if (mac->opmode == NL80211_IFTYPE_AP) { | 2203 | if (mac->opmode == NL80211_IFTYPE_AP || |
2204 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
2139 | entry_id = rtl_cam_get_free_entry(hw, | 2205 | entry_id = rtl_cam_get_free_entry(hw, |
2140 | p_macaddr); | 2206 | p_macaddr); |
2141 | if (entry_id >= TOTAL_CAM_ENTRY) { | 2207 | if (entry_id >= TOTAL_CAM_ENTRY) { |
@@ -2157,7 +2223,8 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, | |||
2157 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 2223 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
2158 | "delete one entry, entry_id is %d\n", | 2224 | "delete one entry, entry_id is %d\n", |
2159 | entry_id); | 2225 | entry_id); |
2160 | if (mac->opmode == NL80211_IFTYPE_AP) | 2226 | if (mac->opmode == NL80211_IFTYPE_AP || |
2227 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
2161 | rtl_cam_del_entry(hw, p_macaddr); | 2228 | rtl_cam_del_entry(hw, p_macaddr); |
2162 | rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); | 2229 | rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); |
2163 | } else { | 2230 | } else { |
@@ -2338,3 +2405,24 @@ void rtl92ce_suspend(struct ieee80211_hw *hw) | |||
2338 | void rtl92ce_resume(struct ieee80211_hw *hw) | 2405 | void rtl92ce_resume(struct ieee80211_hw *hw) |
2339 | { | 2406 | { |
2340 | } | 2407 | } |
2408 | |||
2409 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
2410 | void rtl92ce_allow_all_destaddr(struct ieee80211_hw *hw, | ||
2411 | bool allow_all_da, bool write_into_reg) | ||
2412 | { | ||
2413 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2414 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
2415 | |||
2416 | if (allow_all_da) {/* Set BIT0 */ | ||
2417 | rtlpci->receive_config |= RCR_AAP; | ||
2418 | } else {/* Clear BIT0 */ | ||
2419 | rtlpci->receive_config &= ~RCR_AAP; | ||
2420 | } | ||
2421 | |||
2422 | if (write_into_reg) | ||
2423 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
2424 | |||
2425 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
2426 | "receive_config=0x%08X, write_into_reg=%d\n", | ||
2427 | rtlpci->receive_config, write_into_reg); | ||
2428 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h index 52a3aea9b3de..2d063b0c7760 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h | |||
@@ -61,6 +61,8 @@ void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, | |||
61 | void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); | 61 | void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); |
62 | void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, | 62 | void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, |
63 | struct ieee80211_sta *sta, u8 rssi_level); | 63 | struct ieee80211_sta *sta, u8 rssi_level); |
64 | void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, | ||
65 | struct ieee80211_sta *sta, u8 rssi_level); | ||
64 | void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); | 66 | void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); |
65 | bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); | 67 | bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); |
66 | void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); | 68 | void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); |
@@ -74,5 +76,7 @@ void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw); | |||
74 | void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); | 76 | void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); |
75 | void rtl92ce_suspend(struct ieee80211_hw *hw); | 77 | void rtl92ce_suspend(struct ieee80211_hw *hw); |
76 | void rtl92ce_resume(struct ieee80211_hw *hw); | 78 | void rtl92ce_resume(struct ieee80211_hw *hw); |
79 | void rtl92ce_allow_all_destaddr(struct ieee80211_hw *hw, | ||
80 | bool allow_all_da, bool write_into_reg); | ||
77 | 81 | ||
78 | #endif | 82 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h index e4d738f6166d..bd4aef74c056 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h | |||
@@ -544,6 +544,7 @@ | |||
544 | #define IMR_WLANOFF BIT(0) | 544 | #define IMR_WLANOFF BIT(0) |
545 | 545 | ||
546 | #define EFUSE_REAL_CONTENT_LEN 512 | 546 | #define EFUSE_REAL_CONTENT_LEN 512 |
547 | #define EFUSE_OOB_PROTECT_BYTES 15 | ||
547 | 548 | ||
548 | #define EEPROM_DEFAULT_TSSI 0x0 | 549 | #define EEPROM_DEFAULT_TSSI 0x0 |
549 | #define EEPROM_DEFAULT_TXPOWERDIFF 0x0 | 550 | #define EEPROM_DEFAULT_TXPOWERDIFF 0x0 |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 49f663bd93ff..14203561b6ee 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | |||
@@ -228,6 +228,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { | |||
228 | .enable_hw_sec = rtl92ce_enable_hw_security_config, | 228 | .enable_hw_sec = rtl92ce_enable_hw_security_config, |
229 | .set_key = rtl92ce_set_key, | 229 | .set_key = rtl92ce_set_key, |
230 | .init_sw_leds = rtl92ce_init_sw_leds, | 230 | .init_sw_leds = rtl92ce_init_sw_leds, |
231 | .allow_all_destaddr = rtl92ce_allow_all_destaddr, | ||
231 | .get_bbreg = rtl92c_phy_query_bb_reg, | 232 | .get_bbreg = rtl92c_phy_query_bb_reg, |
232 | .set_bbreg = rtl92c_phy_set_bb_reg, | 233 | .set_bbreg = rtl92c_phy_set_bb_reg, |
233 | .set_rfreg = rtl92ce_phy_set_rf_reg, | 234 | .set_rfreg = rtl92ce_phy_set_rf_reg, |
@@ -278,6 +279,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { | |||
278 | .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, | 279 | .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, |
279 | .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, | 280 | .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, |
280 | .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, | 281 | .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, |
282 | .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, | ||
281 | 283 | ||
282 | .maps[RWCAM] = REG_CAMCMD, | 284 | .maps[RWCAM] = REG_CAMCMD, |
283 | .maps[WCAMI] = REG_CAMWRITE, | 285 | .maps[WCAMI] = REG_CAMWRITE, |
@@ -309,7 +311,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { | |||
309 | 311 | ||
310 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | 312 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, |
311 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | 313 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, |
312 | .maps[RTL_IMR_BcnInt] = IMR_BCNINT, | 314 | .maps[RTL_IMR_BCNINT] = IMR_BCNINT, |
313 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | 315 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, |
314 | .maps[RTL_IMR_RDU] = IMR_RDU, | 316 | .maps[RTL_IMR_RDU] = IMR_RDU, |
315 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | 317 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 27e4ebd51091..6ad23b413eb3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "../wifi.h" | 30 | #include "../wifi.h" |
31 | #include "../pci.h" | 31 | #include "../pci.h" |
32 | #include "../base.h" | 32 | #include "../base.h" |
33 | #include "../stats.h" | ||
33 | #include "reg.h" | 34 | #include "reg.h" |
34 | #include "def.h" | 35 | #include "def.h" |
35 | #include "phy.h" | 36 | #include "phy.h" |
@@ -42,7 +43,7 @@ static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) | |||
42 | 43 | ||
43 | if (unlikely(ieee80211_is_beacon(fc))) | 44 | if (unlikely(ieee80211_is_beacon(fc))) |
44 | return QSLT_BEACON; | 45 | return QSLT_BEACON; |
45 | if (ieee80211_is_mgmt(fc)) | 46 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) |
46 | return QSLT_MGNT; | 47 | return QSLT_MGNT; |
47 | 48 | ||
48 | return skb->priority; | 49 | return skb->priority; |
@@ -78,16 +79,6 @@ static u8 _rtl92c_evm_db_to_percentage(char value) | |||
78 | return ret_val; | 79 | return ret_val; |
79 | } | 80 | } |
80 | 81 | ||
81 | static long _rtl92ce_translate_todbm(struct ieee80211_hw *hw, | ||
82 | u8 signal_strength_index) | ||
83 | { | ||
84 | long signal_power; | ||
85 | |||
86 | signal_power = (long)((signal_strength_index + 1) >> 1); | ||
87 | signal_power -= 95; | ||
88 | return signal_power; | ||
89 | } | ||
90 | |||
91 | static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw, | 82 | static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw, |
92 | long currsig) | 83 | long currsig) |
93 | { | 84 | { |
@@ -139,7 +130,6 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
139 | pstats->packet_toself = packet_toself; | 130 | pstats->packet_toself = packet_toself; |
140 | pstats->is_cck = is_cck_rate; | 131 | pstats->is_cck = is_cck_rate; |
141 | pstats->packet_beacon = packet_beacon; | 132 | pstats->packet_beacon = packet_beacon; |
142 | pstats->is_cck = is_cck_rate; | ||
143 | pstats->rx_mimo_sig_qual[0] = -1; | 133 | pstats->rx_mimo_sig_qual[0] = -1; |
144 | pstats->rx_mimo_sig_qual[1] = -1; | 134 | pstats->rx_mimo_sig_qual[1] = -1; |
145 | 135 | ||
@@ -192,10 +182,30 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
192 | } | 182 | } |
193 | } | 183 | } |
194 | 184 | ||
195 | pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); | 185 | pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); |
186 | /* CCK gain is smaller than OFDM/MCS gain, | ||
187 | * so we add gain diff by experiences, | ||
188 | * the val is 6 | ||
189 | */ | ||
190 | pwdb_all += 6; | ||
191 | if (pwdb_all > 100) | ||
192 | pwdb_all = 100; | ||
193 | /* modify the offset to make the same | ||
194 | * gain index with OFDM. | ||
195 | */ | ||
196 | if (pwdb_all > 34 && pwdb_all <= 42) | ||
197 | pwdb_all -= 2; | ||
198 | else if (pwdb_all > 26 && pwdb_all <= 34) | ||
199 | pwdb_all -= 6; | ||
200 | else if (pwdb_all > 14 && pwdb_all <= 26) | ||
201 | pwdb_all -= 8; | ||
202 | else if (pwdb_all > 4 && pwdb_all <= 14) | ||
203 | pwdb_all -= 4; | ||
204 | |||
196 | pstats->rx_pwdb_all = pwdb_all; | 205 | pstats->rx_pwdb_all = pwdb_all; |
197 | pstats->recvsignalpower = rx_pwr_all; | 206 | pstats->recvsignalpower = rx_pwr_all; |
198 | 207 | ||
208 | /* (3) Get Signal Quality (EVM) */ | ||
199 | if (packet_match_bssid) { | 209 | if (packet_match_bssid) { |
200 | u8 sq; | 210 | u8 sq; |
201 | if (pstats->rx_pwdb_all > 40) | 211 | if (pstats->rx_pwdb_all > 40) |
@@ -217,29 +227,38 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
217 | } else { | 227 | } else { |
218 | rtlpriv->dm.rfpath_rxenable[0] = | 228 | rtlpriv->dm.rfpath_rxenable[0] = |
219 | rtlpriv->dm.rfpath_rxenable[1] = true; | 229 | rtlpriv->dm.rfpath_rxenable[1] = true; |
230 | /* (1)Get RSSI for HT rate */ | ||
220 | for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { | 231 | for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { |
232 | /* we will judge RF RX path now. */ | ||
221 | if (rtlpriv->dm.rfpath_rxenable[i]) | 233 | if (rtlpriv->dm.rfpath_rxenable[i]) |
222 | rf_rx_num++; | 234 | rf_rx_num++; |
223 | 235 | ||
224 | rx_pwr[i] = | 236 | rx_pwr[i] = |
225 | ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; | 237 | ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; |
238 | /* Translate DBM to percentage. */ | ||
226 | rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); | 239 | rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); |
227 | total_rssi += rssi; | 240 | total_rssi += rssi; |
241 | /* Get Rx snr value in DB */ | ||
228 | rtlpriv->stats.rx_snr_db[i] = | 242 | rtlpriv->stats.rx_snr_db[i] = |
229 | (long)(p_drvinfo->rxsnr[i] / 2); | 243 | (long)(p_drvinfo->rxsnr[i] / 2); |
230 | 244 | ||
245 | /* Record Signal Strength for next packet */ | ||
231 | if (packet_match_bssid) | 246 | if (packet_match_bssid) |
232 | pstats->rx_mimo_signalstrength[i] = (u8) rssi; | 247 | pstats->rx_mimo_signalstrength[i] = (u8) rssi; |
233 | } | 248 | } |
234 | 249 | ||
250 | /* (2)PWDB, Average PWDB cacluated by | ||
251 | * hardware (for rate adaptive) | ||
252 | */ | ||
235 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; | 253 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; |
236 | pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); | 254 | pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); |
237 | pstats->rx_pwdb_all = pwdb_all; | 255 | pstats->rx_pwdb_all = pwdb_all; |
238 | pstats->rxpower = rx_pwr_all; | 256 | pstats->rxpower = rx_pwr_all; |
239 | pstats->recvsignalpower = rx_pwr_all; | 257 | pstats->recvsignalpower = rx_pwr_all; |
240 | 258 | ||
241 | if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 && | 259 | /* (3)EVM of HT rate */ |
242 | pdesc->rxmcs <= DESC92_RATEMCS15) | 260 | if (pstats->is_ht && pstats->rate >= DESC92_RATEMCS8 && |
261 | pstats->rate <= DESC92_RATEMCS15) | ||
243 | max_spatial_stream = 2; | 262 | max_spatial_stream = 2; |
244 | else | 263 | else |
245 | max_spatial_stream = 1; | 264 | max_spatial_stream = 1; |
@@ -248,6 +267,9 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
248 | evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); | 267 | evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); |
249 | 268 | ||
250 | if (packet_match_bssid) { | 269 | if (packet_match_bssid) { |
270 | /* Fill value in RFD, Get the first | ||
271 | * spatial stream only | ||
272 | */ | ||
251 | if (i == 0) | 273 | if (i == 0) |
252 | pstats->signalquality = | 274 | pstats->signalquality = |
253 | (u8) (evm & 0xff); | 275 | (u8) (evm & 0xff); |
@@ -256,6 +278,9 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
256 | } | 278 | } |
257 | } | 279 | } |
258 | 280 | ||
281 | /* UI BSS List signal strength(in percentage), | ||
282 | * make it good looking, from 0~100. | ||
283 | */ | ||
259 | if (is_cck_rate) | 284 | if (is_cck_rate) |
260 | pstats->signalstrength = | 285 | pstats->signalstrength = |
261 | (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all)); | 286 | (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all)); |
@@ -265,215 +290,6 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
265 | (hw, total_rssi /= rf_rx_num)); | 290 | (hw, total_rssi /= rf_rx_num)); |
266 | } | 291 | } |
267 | 292 | ||
268 | static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw, | ||
269 | struct rtl_stats *pstats) | ||
270 | { | ||
271 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
272 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
273 | u8 rfpath; | ||
274 | u32 last_rssi, tmpval; | ||
275 | |||
276 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
277 | rtlpriv->stats.rssi_calculate_cnt++; | ||
278 | |||
279 | if (rtlpriv->stats.ui_rssi.total_num++ >= | ||
280 | PHY_RSSI_SLID_WIN_MAX) { | ||
281 | |||
282 | rtlpriv->stats.ui_rssi.total_num = | ||
283 | PHY_RSSI_SLID_WIN_MAX; | ||
284 | last_rssi = | ||
285 | rtlpriv->stats.ui_rssi.elements[rtlpriv-> | ||
286 | stats.ui_rssi.index]; | ||
287 | rtlpriv->stats.ui_rssi.total_val -= last_rssi; | ||
288 | } | ||
289 | |||
290 | rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; | ||
291 | rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi. | ||
292 | index++] = | ||
293 | pstats->signalstrength; | ||
294 | |||
295 | if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) | ||
296 | rtlpriv->stats.ui_rssi.index = 0; | ||
297 | |||
298 | tmpval = rtlpriv->stats.ui_rssi.total_val / | ||
299 | rtlpriv->stats.ui_rssi.total_num; | ||
300 | rtlpriv->stats.signal_strength = | ||
301 | _rtl92ce_translate_todbm(hw, (u8) tmpval); | ||
302 | pstats->rssi = rtlpriv->stats.signal_strength; | ||
303 | } | ||
304 | |||
305 | if (!pstats->is_cck && pstats->packet_toself) { | ||
306 | for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; | ||
307 | rfpath++) { | ||
308 | if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { | ||
309 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
310 | pstats->rx_mimo_signalstrength[rfpath]; | ||
311 | |||
312 | } | ||
313 | |||
314 | if (pstats->rx_mimo_signalstrength[rfpath] > | ||
315 | rtlpriv->stats.rx_rssi_percentage[rfpath]) { | ||
316 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
317 | ((rtlpriv->stats. | ||
318 | rx_rssi_percentage[rfpath] * | ||
319 | (RX_SMOOTH_FACTOR - 1)) + | ||
320 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
321 | (RX_SMOOTH_FACTOR); | ||
322 | |||
323 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
324 | rtlpriv->stats.rx_rssi_percentage[rfpath] + | ||
325 | 1; | ||
326 | } else { | ||
327 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
328 | ((rtlpriv->stats. | ||
329 | rx_rssi_percentage[rfpath] * | ||
330 | (RX_SMOOTH_FACTOR - 1)) + | ||
331 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
332 | (RX_SMOOTH_FACTOR); | ||
333 | } | ||
334 | |||
335 | } | ||
336 | } | ||
337 | } | ||
338 | |||
339 | static void _rtl92ce_update_rxsignalstatistics(struct ieee80211_hw *hw, | ||
340 | struct rtl_stats *pstats) | ||
341 | { | ||
342 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
343 | int weighting = 0; | ||
344 | |||
345 | if (rtlpriv->stats.recv_signal_power == 0) | ||
346 | rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; | ||
347 | |||
348 | if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) | ||
349 | weighting = 5; | ||
350 | |||
351 | else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) | ||
352 | weighting = (-5); | ||
353 | |||
354 | rtlpriv->stats.recv_signal_power = | ||
355 | (rtlpriv->stats.recv_signal_power * 5 + | ||
356 | pstats->recvsignalpower + weighting) / 6; | ||
357 | } | ||
358 | |||
359 | static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw, | ||
360 | struct rtl_stats *pstats) | ||
361 | { | ||
362 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
363 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
364 | long undec_sm_pwdb; | ||
365 | |||
366 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
367 | return; | ||
368 | } else { | ||
369 | undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | ||
370 | } | ||
371 | |||
372 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
373 | if (undec_sm_pwdb < 0) | ||
374 | undec_sm_pwdb = pstats->rx_pwdb_all; | ||
375 | |||
376 | if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { | ||
377 | undec_sm_pwdb = (((undec_sm_pwdb) * | ||
378 | (RX_SMOOTH_FACTOR - 1)) + | ||
379 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
380 | |||
381 | undec_sm_pwdb += 1; | ||
382 | } else { | ||
383 | undec_sm_pwdb = (((undec_sm_pwdb) * | ||
384 | (RX_SMOOTH_FACTOR - 1)) + | ||
385 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
386 | } | ||
387 | |||
388 | rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; | ||
389 | _rtl92ce_update_rxsignalstatistics(hw, pstats); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw, | ||
394 | struct rtl_stats *pstats) | ||
395 | { | ||
396 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
397 | u32 last_evm, n_spatialstream, tmpval; | ||
398 | |||
399 | if (pstats->signalquality != 0) { | ||
400 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
401 | |||
402 | if (rtlpriv->stats.ui_link_quality.total_num++ >= | ||
403 | PHY_LINKQUALITY_SLID_WIN_MAX) { | ||
404 | rtlpriv->stats.ui_link_quality.total_num = | ||
405 | PHY_LINKQUALITY_SLID_WIN_MAX; | ||
406 | last_evm = | ||
407 | rtlpriv->stats. | ||
408 | ui_link_quality.elements[rtlpriv-> | ||
409 | stats.ui_link_quality. | ||
410 | index]; | ||
411 | rtlpriv->stats.ui_link_quality.total_val -= | ||
412 | last_evm; | ||
413 | } | ||
414 | |||
415 | rtlpriv->stats.ui_link_quality.total_val += | ||
416 | pstats->signalquality; | ||
417 | rtlpriv->stats.ui_link_quality.elements[rtlpriv->stats. | ||
418 | ui_link_quality. | ||
419 | index++] = | ||
420 | pstats->signalquality; | ||
421 | |||
422 | if (rtlpriv->stats.ui_link_quality.index >= | ||
423 | PHY_LINKQUALITY_SLID_WIN_MAX) | ||
424 | rtlpriv->stats.ui_link_quality.index = 0; | ||
425 | |||
426 | tmpval = rtlpriv->stats.ui_link_quality.total_val / | ||
427 | rtlpriv->stats.ui_link_quality.total_num; | ||
428 | rtlpriv->stats.signal_quality = tmpval; | ||
429 | |||
430 | rtlpriv->stats.last_sigstrength_inpercent = tmpval; | ||
431 | |||
432 | for (n_spatialstream = 0; n_spatialstream < 2; | ||
433 | n_spatialstream++) { | ||
434 | if (pstats-> | ||
435 | rx_mimo_sig_qual[n_spatialstream] != -1) { | ||
436 | if (rtlpriv->stats. | ||
437 | rx_evm_percentage[n_spatialstream] | ||
438 | == 0) { | ||
439 | rtlpriv->stats. | ||
440 | rx_evm_percentage | ||
441 | [n_spatialstream] = | ||
442 | pstats->rx_mimo_sig_qual | ||
443 | [n_spatialstream]; | ||
444 | } | ||
445 | |||
446 | rtlpriv->stats. | ||
447 | rx_evm_percentage[n_spatialstream] = | ||
448 | ((rtlpriv-> | ||
449 | stats.rx_evm_percentage | ||
450 | [n_spatialstream] * | ||
451 | (RX_SMOOTH_FACTOR - 1)) + | ||
452 | (pstats->rx_mimo_sig_qual | ||
453 | [n_spatialstream] * 1)) / | ||
454 | (RX_SMOOTH_FACTOR); | ||
455 | } | ||
456 | } | ||
457 | } | ||
458 | } else { | ||
459 | ; | ||
460 | } | ||
461 | } | ||
462 | |||
463 | static void _rtl92ce_process_phyinfo(struct ieee80211_hw *hw, | ||
464 | u8 *buffer, | ||
465 | struct rtl_stats *pcurrent_stats) | ||
466 | { | ||
467 | |||
468 | if (!pcurrent_stats->packet_matchbssid && | ||
469 | !pcurrent_stats->packet_beacon) | ||
470 | return; | ||
471 | |||
472 | _rtl92ce_process_ui_rssi(hw, pcurrent_stats); | ||
473 | _rtl92ce_process_pwdb(hw, pcurrent_stats); | ||
474 | _rtl92ce_process_ui_link_quality(hw, pcurrent_stats); | ||
475 | } | ||
476 | |||
477 | static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, | 293 | static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, |
478 | struct sk_buff *skb, | 294 | struct sk_buff *skb, |
479 | struct rtl_stats *pstats, | 295 | struct rtl_stats *pstats, |
@@ -516,7 +332,7 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, | |||
516 | packet_matchbssid, packet_toself, | 332 | packet_matchbssid, packet_toself, |
517 | packet_beacon); | 333 | packet_beacon); |
518 | 334 | ||
519 | _rtl92ce_process_phyinfo(hw, tmp_buf, pstats); | 335 | rtl_process_phyinfo(hw, tmp_buf, pstats); |
520 | } | 336 | } |
521 | 337 | ||
522 | bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | 338 | bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, |
@@ -526,7 +342,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | |||
526 | { | 342 | { |
527 | struct rx_fwinfo_92c *p_drvinfo; | 343 | struct rx_fwinfo_92c *p_drvinfo; |
528 | struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; | 344 | struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; |
529 | 345 | struct ieee80211_hdr *hdr; | |
530 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); | 346 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); |
531 | stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); | 347 | stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); |
532 | stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * | 348 | stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * |
@@ -539,37 +355,60 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | |||
539 | stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); | 355 | stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); |
540 | stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); | 356 | stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); |
541 | stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); | 357 | stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); |
542 | stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) | 358 | stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) |
543 | && (GET_RX_DESC_FAGGR(pdesc) == 1)); | 359 | && (GET_RX_DESC_FAGGR(pdesc) == 1)); |
544 | stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); | 360 | stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); |
545 | stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); | 361 | stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); |
362 | stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); | ||
363 | |||
364 | stats->is_cck = RX_HAL_IS_CCK_RATE(pdesc); | ||
546 | 365 | ||
547 | rx_status->freq = hw->conf.chandef.chan->center_freq; | 366 | rx_status->freq = hw->conf.chandef.chan->center_freq; |
548 | rx_status->band = hw->conf.chandef.chan->band; | 367 | rx_status->band = hw->conf.chandef.chan->band; |
549 | 368 | ||
550 | if (GET_RX_DESC_CRC32(pdesc)) | 369 | hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size |
551 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | 370 | + stats->rx_bufshift); |
552 | 371 | ||
553 | if (!GET_RX_DESC_SWDEC(pdesc)) | 372 | if (stats->crc) |
554 | rx_status->flag |= RX_FLAG_DECRYPTED; | 373 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
555 | 374 | ||
556 | if (GET_RX_DESC_BW(pdesc)) | 375 | if (stats->rx_is40Mhzpacket) |
557 | rx_status->flag |= RX_FLAG_40MHZ; | 376 | rx_status->flag |= RX_FLAG_40MHZ; |
558 | 377 | ||
559 | if (GET_RX_DESC_RXHT(pdesc)) | 378 | if (stats->is_ht) |
560 | rx_status->flag |= RX_FLAG_HT; | 379 | rx_status->flag |= RX_FLAG_HT; |
561 | 380 | ||
562 | rx_status->flag |= RX_FLAG_MACTIME_START; | 381 | rx_status->flag |= RX_FLAG_MACTIME_START; |
563 | 382 | ||
564 | if (stats->decrypted) | 383 | /* hw will set stats->decrypted true, if it finds the |
565 | rx_status->flag |= RX_FLAG_DECRYPTED; | 384 | * frame is open data frame or mgmt frame. |
566 | 385 | * So hw will not decryption robust managment frame | |
386 | * for IEEE80211w but still set status->decrypted | ||
387 | * true, so here we should set it back to undecrypted | ||
388 | * for IEEE80211w frame, and mac80211 sw will help | ||
389 | * to decrypt it | ||
390 | */ | ||
391 | if (stats->decrypted) { | ||
392 | if (!hdr) { | ||
393 | /* In testing, hdr was NULL here */ | ||
394 | return false; | ||
395 | } | ||
396 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | ||
397 | (ieee80211_has_protected(hdr->frame_control))) | ||
398 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | ||
399 | else | ||
400 | rx_status->flag |= RX_FLAG_DECRYPTED; | ||
401 | } | ||
402 | /* rate_idx: index of data rate into band's | ||
403 | * supported rates or MCS index if HT rates | ||
404 | * are use (RX_FLAG_HT) | ||
405 | * Notice: this is diff with windows define | ||
406 | */ | ||
567 | rx_status->rate_idx = rtlwifi_rate_mapping(hw, | 407 | rx_status->rate_idx = rtlwifi_rate_mapping(hw, |
568 | (bool)GET_RX_DESC_RXHT(pdesc), | 408 | stats->is_ht, stats->rate, |
569 | (u8)GET_RX_DESC_RXMCS(pdesc), | 409 | stats->isfirst_ampdu); |
570 | (bool)GET_RX_DESC_PAGGR(pdesc)); | ||
571 | 410 | ||
572 | rx_status->mactime = GET_RX_DESC_TSFL(pdesc); | 411 | rx_status->mactime = stats->timestamp_low; |
573 | if (phystatus) { | 412 | if (phystatus) { |
574 | p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + | 413 | p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + |
575 | stats->rx_bufshift); | 414 | stats->rx_bufshift); |
@@ -580,7 +419,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | |||
580 | } | 419 | } |
581 | 420 | ||
582 | /*rx_status->qual = stats->signal; */ | 421 | /*rx_status->qual = stats->signal; */ |
583 | rx_status->signal = stats->rssi + 10; | 422 | rx_status->signal = stats->recvsignalpower + 10; |
584 | /*rx_status->noise = -stats->noise; */ | 423 | /*rx_status->noise = -stats->noise; */ |
585 | 424 | ||
586 | return true; | 425 | return true; |
@@ -624,7 +463,8 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, | |||
624 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 463 | if (mac->opmode == NL80211_IFTYPE_STATION) { |
625 | bw_40 = mac->bw_40; | 464 | bw_40 = mac->bw_40; |
626 | } else if (mac->opmode == NL80211_IFTYPE_AP || | 465 | } else if (mac->opmode == NL80211_IFTYPE_AP || |
627 | mac->opmode == NL80211_IFTYPE_ADHOC) { | 466 | mac->opmode == NL80211_IFTYPE_ADHOC || |
467 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
628 | if (sta) | 468 | if (sta) |
629 | bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; | 469 | bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; |
630 | } | 470 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index b1ccff474c79..3d0498e69c8c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -202,7 +202,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
202 | } | 202 | } |
203 | } | 203 | } |
204 | for (i = 0; i < 14; i++) { | 204 | for (i = 0; i < 14; i++) { |
205 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 205 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
206 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", rf_path, i, | 206 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", rf_path, i, |
207 | rtlefuse->txpwrlevel_cck[rf_path][i], | 207 | rtlefuse->txpwrlevel_cck[rf_path][i], |
208 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i], | 208 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i], |
@@ -238,11 +238,11 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
238 | ((rtlefuse->eeprom_pwrlimit_ht40[index] | 238 | ((rtlefuse->eeprom_pwrlimit_ht40[index] |
239 | & 0xf0) >> 4); | 239 | & 0xf0) >> 4); |
240 | } | 240 | } |
241 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 241 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
242 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", | 242 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", |
243 | rf_path, i, | 243 | rf_path, i, |
244 | rtlefuse->pwrgroup_ht20[rf_path][i]); | 244 | rtlefuse->pwrgroup_ht20[rf_path][i]); |
245 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 245 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
246 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", | 246 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", |
247 | rf_path, i, | 247 | rf_path, i, |
248 | rtlefuse->pwrgroup_ht40[rf_path][i]); | 248 | rtlefuse->pwrgroup_ht40[rf_path][i]); |
@@ -273,26 +273,26 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
273 | rtlefuse->legacy_ht_txpowerdiff = | 273 | rtlefuse->legacy_ht_txpowerdiff = |
274 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; | 274 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; |
275 | for (i = 0; i < 14; i++) | 275 | for (i = 0; i < 14; i++) |
276 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 276 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
277 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", | 277 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", |
278 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); | 278 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); |
279 | for (i = 0; i < 14; i++) | 279 | for (i = 0; i < 14; i++) |
280 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 280 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
281 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", | 281 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", |
282 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); | 282 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); |
283 | for (i = 0; i < 14; i++) | 283 | for (i = 0; i < 14; i++) |
284 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 284 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
285 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", | 285 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", |
286 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); | 286 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); |
287 | for (i = 0; i < 14; i++) | 287 | for (i = 0; i < 14; i++) |
288 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 288 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
289 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", | 289 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", |
290 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); | 290 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); |
291 | if (!autoload_fail) | 291 | if (!autoload_fail) |
292 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); | 292 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); |
293 | else | 293 | else |
294 | rtlefuse->eeprom_regulatory = 0; | 294 | rtlefuse->eeprom_regulatory = 0; |
295 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 295 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
296 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | 296 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); |
297 | if (!autoload_fail) { | 297 | if (!autoload_fail) { |
298 | rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; | 298 | rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; |
@@ -301,7 +301,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
301 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; | 301 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; |
302 | rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; | 302 | rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; |
303 | } | 303 | } |
304 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 304 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
305 | "TSSI_A = 0x%x, TSSI_B = 0x%x\n", | 305 | "TSSI_A = 0x%x, TSSI_B = 0x%x\n", |
306 | rtlefuse->eeprom_tssi[RF90_PATH_A], | 306 | rtlefuse->eeprom_tssi[RF90_PATH_A], |
307 | rtlefuse->eeprom_tssi[RF90_PATH_B]); | 307 | rtlefuse->eeprom_tssi[RF90_PATH_B]); |
@@ -316,7 +316,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
316 | if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) | 316 | if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) |
317 | rtlefuse->apk_thermalmeterignore = true; | 317 | rtlefuse->apk_thermalmeterignore = true; |
318 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; | 318 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; |
319 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 319 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
320 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | 320 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); |
321 | } | 321 | } |
322 | 322 | ||
@@ -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/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index a73a17bc56dd..23d640a4debd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | |||
@@ -223,7 +223,7 @@ static struct rtl_hal_cfg rtl92cu_hal_cfg = { | |||
223 | 223 | ||
224 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | 224 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, |
225 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | 225 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, |
226 | .maps[RTL_IMR_BcnInt] = IMR_BCNINT, | 226 | .maps[RTL_IMR_BCNINT] = IMR_BCNINT, |
227 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | 227 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, |
228 | .maps[RTL_IMR_RDU] = IMR_RDU, | 228 | .maps[RTL_IMR_RDU] = IMR_RDU, |
229 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | 229 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index f0dada530153..763cf1defab5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | |||
@@ -434,7 +434,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
434 | (u32)hdr->addr1[2], (u32)hdr->addr1[3], | 434 | (u32)hdr->addr1[2], (u32)hdr->addr1[3], |
435 | (u32)hdr->addr1[4], (u32)hdr->addr1[5]); | 435 | (u32)hdr->addr1[4], (u32)hdr->addr1[5]); |
436 | memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); | 436 | memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); |
437 | ieee80211_rx_irqsafe(hw, skb); | 437 | ieee80211_rx(hw, skb); |
438 | } | 438 | } |
439 | 439 | ||
440 | void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb) | 440 | void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c index 5251fb8a111e..19a765532603 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c | |||
@@ -171,8 +171,8 @@ static void rtl92d_dm_diginit(struct ieee80211_hw *hw) | |||
171 | de_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; | 171 | de_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; |
172 | de_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; | 172 | de_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; |
173 | de_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; | 173 | de_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; |
174 | de_digtable->rx_gain_range_max = DM_DIG_FA_UPPER; | 174 | de_digtable->rx_gain_max = DM_DIG_FA_UPPER; |
175 | de_digtable->rx_gain_range_min = DM_DIG_FA_LOWER; | 175 | de_digtable->rx_gain_min = DM_DIG_FA_LOWER; |
176 | de_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; | 176 | de_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; |
177 | de_digtable->back_range_max = DM_DIG_BACKOFF_MAX; | 177 | de_digtable->back_range_max = DM_DIG_BACKOFF_MAX; |
178 | de_digtable->back_range_min = DM_DIG_BACKOFF_MIN; | 178 | de_digtable->back_range_min = DM_DIG_BACKOFF_MIN; |
@@ -444,8 +444,8 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw) | |||
444 | "dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n", | 444 | "dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n", |
445 | de_digtable->large_fa_hit, de_digtable->forbidden_igi); | 445 | de_digtable->large_fa_hit, de_digtable->forbidden_igi); |
446 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, | 446 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, |
447 | "dm_DIG() Before: Recover_cnt=%d, rx_gain_range_min=%x\n", | 447 | "dm_DIG() Before: Recover_cnt=%d, rx_gain_min=%x\n", |
448 | de_digtable->recover_cnt, de_digtable->rx_gain_range_min); | 448 | de_digtable->recover_cnt, de_digtable->rx_gain_min); |
449 | 449 | ||
450 | /* deal with abnorally large false alarm */ | 450 | /* deal with abnorally large false alarm */ |
451 | if (falsealm_cnt->cnt_all > 10000) { | 451 | if (falsealm_cnt->cnt_all > 10000) { |
@@ -459,9 +459,9 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw) | |||
459 | } | 459 | } |
460 | if (de_digtable->large_fa_hit >= 3) { | 460 | if (de_digtable->large_fa_hit >= 3) { |
461 | if ((de_digtable->forbidden_igi + 1) > DM_DIG_MAX) | 461 | if ((de_digtable->forbidden_igi + 1) > DM_DIG_MAX) |
462 | de_digtable->rx_gain_range_min = DM_DIG_MAX; | 462 | de_digtable->rx_gain_min = DM_DIG_MAX; |
463 | else | 463 | else |
464 | de_digtable->rx_gain_range_min = | 464 | de_digtable->rx_gain_min = |
465 | (de_digtable->forbidden_igi + 1); | 465 | (de_digtable->forbidden_igi + 1); |
466 | de_digtable->recover_cnt = 3600; /* 3600=2hr */ | 466 | de_digtable->recover_cnt = 3600; /* 3600=2hr */ |
467 | } | 467 | } |
@@ -475,12 +475,12 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw) | |||
475 | DM_DIG_FA_LOWER) { | 475 | DM_DIG_FA_LOWER) { |
476 | de_digtable->forbidden_igi = | 476 | de_digtable->forbidden_igi = |
477 | DM_DIG_FA_LOWER; | 477 | DM_DIG_FA_LOWER; |
478 | de_digtable->rx_gain_range_min = | 478 | de_digtable->rx_gain_min = |
479 | DM_DIG_FA_LOWER; | 479 | DM_DIG_FA_LOWER; |
480 | 480 | ||
481 | } else { | 481 | } else { |
482 | de_digtable->forbidden_igi--; | 482 | de_digtable->forbidden_igi--; |
483 | de_digtable->rx_gain_range_min = | 483 | de_digtable->rx_gain_min = |
484 | (de_digtable->forbidden_igi + 1); | 484 | (de_digtable->forbidden_igi + 1); |
485 | } | 485 | } |
486 | } else if (de_digtable->large_fa_hit == 3) { | 486 | } else if (de_digtable->large_fa_hit == 3) { |
@@ -492,13 +492,13 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw) | |||
492 | "dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n", | 492 | "dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n", |
493 | de_digtable->large_fa_hit, de_digtable->forbidden_igi); | 493 | de_digtable->large_fa_hit, de_digtable->forbidden_igi); |
494 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, | 494 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, |
495 | "dm_DIG() After: recover_cnt=%d, rx_gain_range_min=%x\n", | 495 | "dm_DIG() After: recover_cnt=%d, rx_gain_min=%x\n", |
496 | de_digtable->recover_cnt, de_digtable->rx_gain_range_min); | 496 | de_digtable->recover_cnt, de_digtable->rx_gain_min); |
497 | 497 | ||
498 | if (value_igi > DM_DIG_MAX) | 498 | if (value_igi > DM_DIG_MAX) |
499 | value_igi = DM_DIG_MAX; | 499 | value_igi = DM_DIG_MAX; |
500 | else if (value_igi < de_digtable->rx_gain_range_min) | 500 | else if (value_igi < de_digtable->rx_gain_min) |
501 | value_igi = de_digtable->rx_gain_range_min; | 501 | value_igi = de_digtable->rx_gain_min; |
502 | de_digtable->cur_igvalue = value_igi; | 502 | de_digtable->cur_igvalue = value_igi; |
503 | rtl92d_dm_write_dig(hw); | 503 | rtl92d_dm_write_dig(hw); |
504 | if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) | 504 | if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) |
@@ -1071,9 +1071,9 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( | |||
1071 | } | 1071 | } |
1072 | ele_d = (ofdmswing_table[(u8) ofdm_index[0]] & | 1072 | ele_d = (ofdmswing_table[(u8) ofdm_index[0]] & |
1073 | 0xFFC00000) >> 22; | 1073 | 0xFFC00000) >> 22; |
1074 | val_x = rtlphy->iqk_matrix_regsetting | 1074 | val_x = rtlphy->iqk_matrix |
1075 | [indexforchannel].value[0][0]; | 1075 | [indexforchannel].value[0][0]; |
1076 | val_y = rtlphy->iqk_matrix_regsetting | 1076 | val_y = rtlphy->iqk_matrix |
1077 | [indexforchannel].value[0][1]; | 1077 | [indexforchannel].value[0][1]; |
1078 | if (val_x != 0) { | 1078 | if (val_x != 0) { |
1079 | if ((val_x & 0x00000200) != 0) | 1079 | if ((val_x & 0x00000200) != 0) |
@@ -1175,9 +1175,9 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( | |||
1175 | if (is2t) { | 1175 | if (is2t) { |
1176 | ele_d = (ofdmswing_table[(u8) ofdm_index[1]] & | 1176 | ele_d = (ofdmswing_table[(u8) ofdm_index[1]] & |
1177 | 0xFFC00000) >> 22; | 1177 | 0xFFC00000) >> 22; |
1178 | val_x = rtlphy->iqk_matrix_regsetting | 1178 | val_x = rtlphy->iqk_matrix |
1179 | [indexforchannel].value[0][4]; | 1179 | [indexforchannel].value[0][4]; |
1180 | val_y = rtlphy->iqk_matrix_regsetting | 1180 | val_y = rtlphy->iqk_matrix |
1181 | [indexforchannel].value[0][5]; | 1181 | [indexforchannel].value[0][5]; |
1182 | if (val_x != 0) { | 1182 | if (val_x != 0) { |
1183 | if ((val_x & 0x00000200) != 0) | 1183 | if ((val_x & 0x00000200) != 0) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c index aa5b42521bb4..7dd8f6de0550 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c | |||
@@ -1183,7 +1183,7 @@ void rtl92d_linked_set_reg(struct ieee80211_hw *hw) | |||
1183 | u8 channel = rtlphy->current_channel; | 1183 | u8 channel = rtlphy->current_channel; |
1184 | 1184 | ||
1185 | indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); | 1185 | indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); |
1186 | if (!rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done) { | 1186 | if (!rtlphy->iqk_matrix[indexforchannel].iqk_done) { |
1187 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG, | 1187 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG, |
1188 | "Do IQK for channel:%d\n", channel); | 1188 | "Do IQK for channel:%d\n", channel); |
1189 | rtl92d_phy_iq_calibrate(hw); | 1189 | rtl92d_phy_iq_calibrate(hw); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c index 33041bd4da81..840bac5fa2f8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c | |||
@@ -2479,9 +2479,9 @@ void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw) | |||
2479 | rtlphy->current_channel); | 2479 | rtlphy->current_channel); |
2480 | 2480 | ||
2481 | for (i = 0; i < IQK_MATRIX_REG_NUM; i++) | 2481 | for (i = 0; i < IQK_MATRIX_REG_NUM; i++) |
2482 | rtlphy->iqk_matrix_regsetting[indexforchannel]. | 2482 | rtlphy->iqk_matrix[indexforchannel]. |
2483 | value[0][i] = result[final_candidate][i]; | 2483 | value[0][i] = result[final_candidate][i]; |
2484 | rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done = | 2484 | rtlphy->iqk_matrix[indexforchannel].iqk_done = |
2485 | true; | 2485 | true; |
2486 | 2486 | ||
2487 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD, | 2487 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD, |
@@ -2501,8 +2501,8 @@ void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel) | |||
2501 | indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); | 2501 | indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); |
2502 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "indexforchannel %d done %d\n", | 2502 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "indexforchannel %d done %d\n", |
2503 | indexforchannel, | 2503 | indexforchannel, |
2504 | rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done); | 2504 | rtlphy->iqk_matrix[indexforchannel].iqk_done); |
2505 | if (0 && !rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done && | 2505 | if (0 && !rtlphy->iqk_matrix[indexforchannel].iqk_done && |
2506 | rtlphy->need_iqk) { | 2506 | rtlphy->need_iqk) { |
2507 | /* Re Do IQK. */ | 2507 | /* Re Do IQK. */ |
2508 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD, | 2508 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD, |
@@ -2516,23 +2516,23 @@ void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel) | |||
2516 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, | 2516 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, |
2517 | "Just Read IQK Matrix reg for channel:%d....\n", | 2517 | "Just Read IQK Matrix reg for channel:%d....\n", |
2518 | channel); | 2518 | channel); |
2519 | if ((rtlphy->iqk_matrix_regsetting[indexforchannel]. | 2519 | if ((rtlphy->iqk_matrix[indexforchannel]. |
2520 | value[0] != NULL) | 2520 | value[0] != NULL) |
2521 | /*&&(regea4 != 0) */) | 2521 | /*&&(regea4 != 0) */) |
2522 | _rtl92d_phy_patha_fill_iqk_matrix(hw, true, | 2522 | _rtl92d_phy_patha_fill_iqk_matrix(hw, true, |
2523 | rtlphy->iqk_matrix_regsetting[ | 2523 | rtlphy->iqk_matrix[ |
2524 | indexforchannel].value, 0, | 2524 | indexforchannel].value, 0, |
2525 | (rtlphy->iqk_matrix_regsetting[ | 2525 | (rtlphy->iqk_matrix[ |
2526 | indexforchannel].value[0][2] == 0)); | 2526 | indexforchannel].value[0][2] == 0)); |
2527 | if (IS_92D_SINGLEPHY(rtlhal->version)) { | 2527 | if (IS_92D_SINGLEPHY(rtlhal->version)) { |
2528 | if ((rtlphy->iqk_matrix_regsetting[ | 2528 | if ((rtlphy->iqk_matrix[ |
2529 | indexforchannel].value[0][4] != 0) | 2529 | indexforchannel].value[0][4] != 0) |
2530 | /*&&(regec4 != 0) */) | 2530 | /*&&(regec4 != 0) */) |
2531 | _rtl92d_phy_pathb_fill_iqk_matrix(hw, | 2531 | _rtl92d_phy_pathb_fill_iqk_matrix(hw, |
2532 | true, | 2532 | true, |
2533 | rtlphy->iqk_matrix_regsetting[ | 2533 | rtlphy->iqk_matrix[ |
2534 | indexforchannel].value, 0, | 2534 | indexforchannel].value, 0, |
2535 | (rtlphy->iqk_matrix_regsetting[ | 2535 | (rtlphy->iqk_matrix[ |
2536 | indexforchannel].value[0][6] | 2536 | indexforchannel].value[0][6] |
2537 | == 0)); | 2537 | == 0)); |
2538 | } | 2538 | } |
@@ -2830,20 +2830,20 @@ void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw) | |||
2830 | 2830 | ||
2831 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | 2831 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, |
2832 | "settings regs %d default regs %d\n", | 2832 | "settings regs %d default regs %d\n", |
2833 | (int)(sizeof(rtlphy->iqk_matrix_regsetting) / | 2833 | (int)(sizeof(rtlphy->iqk_matrix) / |
2834 | sizeof(struct iqk_matrix_regs)), | 2834 | sizeof(struct iqk_matrix_regs)), |
2835 | IQK_MATRIX_REG_NUM); | 2835 | IQK_MATRIX_REG_NUM); |
2836 | /* 0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc */ | 2836 | /* 0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc */ |
2837 | for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) { | 2837 | for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) { |
2838 | rtlphy->iqk_matrix_regsetting[i].value[0][0] = 0x100; | 2838 | rtlphy->iqk_matrix[i].value[0][0] = 0x100; |
2839 | rtlphy->iqk_matrix_regsetting[i].value[0][2] = 0x100; | 2839 | rtlphy->iqk_matrix[i].value[0][2] = 0x100; |
2840 | rtlphy->iqk_matrix_regsetting[i].value[0][4] = 0x100; | 2840 | rtlphy->iqk_matrix[i].value[0][4] = 0x100; |
2841 | rtlphy->iqk_matrix_regsetting[i].value[0][6] = 0x100; | 2841 | rtlphy->iqk_matrix[i].value[0][6] = 0x100; |
2842 | rtlphy->iqk_matrix_regsetting[i].value[0][1] = 0x0; | 2842 | rtlphy->iqk_matrix[i].value[0][1] = 0x0; |
2843 | rtlphy->iqk_matrix_regsetting[i].value[0][3] = 0x0; | 2843 | rtlphy->iqk_matrix[i].value[0][3] = 0x0; |
2844 | rtlphy->iqk_matrix_regsetting[i].value[0][5] = 0x0; | 2844 | rtlphy->iqk_matrix[i].value[0][5] = 0x0; |
2845 | rtlphy->iqk_matrix_regsetting[i].value[0][7] = 0x0; | 2845 | rtlphy->iqk_matrix[i].value[0][7] = 0x0; |
2846 | rtlphy->iqk_matrix_regsetting[i].iqk_done = false; | 2846 | rtlphy->iqk_matrix[i].iqk_done = false; |
2847 | } | 2847 | } |
2848 | } | 2848 | } |
2849 | 2849 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h index ebb1d5f5e7b5..b7498c5bafc5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h | |||
@@ -543,7 +543,7 @@ | |||
543 | #define IMR_TIMEOUT1 BIT(16) | 543 | #define IMR_TIMEOUT1 BIT(16) |
544 | #define IMR_TXFOVW BIT(15) | 544 | #define IMR_TXFOVW BIT(15) |
545 | #define IMR_PSTIMEOUT BIT(14) | 545 | #define IMR_PSTIMEOUT BIT(14) |
546 | #define IMR_BcnInt BIT(13) | 546 | #define IMR_BCNINT BIT(13) |
547 | #define IMR_RXFOVW BIT(12) | 547 | #define IMR_RXFOVW BIT(12) |
548 | #define IMR_RDU BIT(11) | 548 | #define IMR_RDU BIT(11) |
549 | #define IMR_ATIMEND BIT(10) | 549 | #define IMR_ATIMEND BIT(10) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index 03c6d18b2e07..c18c04bf0c13 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c | |||
@@ -166,7 +166,7 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) | |||
166 | rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; | 166 | rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; |
167 | 167 | ||
168 | /* for early mode */ | 168 | /* for early mode */ |
169 | rtlpriv->rtlhal.earlymode_enable = true; | 169 | rtlpriv->rtlhal.earlymode_enable = false; |
170 | for (tid = 0; tid < 8; tid++) | 170 | for (tid = 0; tid < 8; tid++) |
171 | skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); | 171 | skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); |
172 | 172 | ||
@@ -319,7 +319,7 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = { | |||
319 | 319 | ||
320 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | 320 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, |
321 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | 321 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, |
322 | .maps[RTL_IMR_BcnInt] = IMR_BcnInt, | 322 | .maps[RTL_IMR_BCNINT] = IMR_BCNINT, |
323 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | 323 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, |
324 | .maps[RTL_IMR_RDU] = IMR_RDU, | 324 | .maps[RTL_IMR_RDU] = IMR_RDU, |
325 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | 325 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, |
@@ -333,7 +333,7 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = { | |||
333 | .maps[RTL_IMR_VIDOK] = IMR_VIDOK, | 333 | .maps[RTL_IMR_VIDOK] = IMR_VIDOK, |
334 | .maps[RTL_IMR_VODOK] = IMR_VODOK, | 334 | .maps[RTL_IMR_VODOK] = IMR_VODOK, |
335 | .maps[RTL_IMR_ROK] = IMR_ROK, | 335 | .maps[RTL_IMR_ROK] = IMR_ROK, |
336 | .maps[RTL_IBSS_INT_MASKS] = (IMR_BcnInt | IMR_TBDOK | IMR_TBDER), | 336 | .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), |
337 | 337 | ||
338 | .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, | 338 | .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, |
339 | .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, | 339 | .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h index 2d255e02d795..83c98674bfd3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h | |||
@@ -36,9 +36,6 @@ | |||
36 | #define SHORT_SLOT_TIME 9 | 36 | #define SHORT_SLOT_TIME 9 |
37 | #define NON_SHORT_SLOT_TIME 20 | 37 | #define NON_SHORT_SLOT_TIME 20 |
38 | 38 | ||
39 | /* Rx smooth factor */ | ||
40 | #define RX_SMOOTH_FACTOR 20 | ||
41 | |||
42 | /* Queue Select Value in TxDesc */ | 39 | /* Queue Select Value in TxDesc */ |
43 | #define QSLT_BK 0x2 | 40 | #define QSLT_BK 0x2 |
44 | #define QSLT_BE 0x0 | 41 | #define QSLT_BE 0x0 |
@@ -49,10 +46,6 @@ | |||
49 | #define QSLT_MGNT 0x12 | 46 | #define QSLT_MGNT 0x12 |
50 | #define QSLT_CMD 0x13 | 47 | #define QSLT_CMD 0x13 |
51 | 48 | ||
52 | #define PHY_RSSI_SLID_WIN_MAX 100 | ||
53 | #define PHY_LINKQUALITY_SLID_WIN_MAX 20 | ||
54 | #define PHY_BEACON_RSSI_SLID_WIN_MAX 10 | ||
55 | |||
56 | /* Tx Desc */ | 49 | /* Tx Desc */ |
57 | #define TX_DESC_SIZE_RTL8192S (16 * 4) | 50 | #define TX_DESC_SIZE_RTL8192S (16 * 4) |
58 | #define TX_CMDDESC_SIZE_RTL8192S (16 * 4) | 51 | #define TX_CMDDESC_SIZE_RTL8192S (16 * 4) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c index e551fe5f9ccd..b3a2d5ec59e6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c | |||
@@ -163,6 +163,7 @@ static void _rtl92s_dm_txpowertracking_callback_thermalmeter( | |||
163 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 163 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
164 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | 164 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
165 | u8 thermalvalue = 0; | 165 | u8 thermalvalue = 0; |
166 | u32 fw_cmd = 0; | ||
166 | 167 | ||
167 | rtlpriv->dm.txpower_trackinginit = true; | 168 | rtlpriv->dm.txpower_trackinginit = true; |
168 | 169 | ||
@@ -175,7 +176,19 @@ static void _rtl92s_dm_txpowertracking_callback_thermalmeter( | |||
175 | 176 | ||
176 | if (thermalvalue) { | 177 | if (thermalvalue) { |
177 | rtlpriv->dm.thermalvalue = thermalvalue; | 178 | rtlpriv->dm.thermalvalue = thermalvalue; |
178 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL); | 179 | if (hal_get_firmwareversion(rtlpriv) >= 0x35) { |
180 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL); | ||
181 | } else { | ||
182 | fw_cmd = (FW_TXPWR_TRACK_THERMAL | | ||
183 | (rtlpriv->efuse.thermalmeter[0] << 8) | | ||
184 | (thermalvalue << 16)); | ||
185 | |||
186 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
187 | "Write to FW Thermal Val = 0x%x\n", fw_cmd); | ||
188 | |||
189 | rtl_write_dword(rtlpriv, WFM5, fw_cmd); | ||
190 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
191 | } | ||
179 | } | 192 | } |
180 | 193 | ||
181 | rtlpriv->dm.txpowercount = 0; | 194 | rtlpriv->dm.txpowercount = 0; |
@@ -217,11 +230,10 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) | |||
217 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 230 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
218 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 231 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
219 | struct rate_adaptive *ra = &(rtlpriv->ra); | 232 | struct rate_adaptive *ra = &(rtlpriv->ra); |
220 | 233 | struct ieee80211_sta *sta = NULL; | |
221 | u32 low_rssi_thresh = 0; | 234 | u32 low_rssi_thresh = 0; |
222 | u32 middle_rssi_thresh = 0; | 235 | u32 middle_rssi_thresh = 0; |
223 | u32 high_rssi_thresh = 0; | 236 | u32 high_rssi_thresh = 0; |
224 | struct ieee80211_sta *sta = NULL; | ||
225 | 237 | ||
226 | if (is_hal_stop(rtlhal)) | 238 | if (is_hal_stop(rtlhal)) |
227 | return; | 239 | return; |
@@ -229,14 +241,12 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) | |||
229 | if (!rtlpriv->dm.useramask) | 241 | if (!rtlpriv->dm.useramask) |
230 | return; | 242 | return; |
231 | 243 | ||
232 | if (!rtlpriv->dm.inform_fw_driverctrldm) { | 244 | if (hal_get_firmwareversion(rtlpriv) >= 61 && |
245 | !rtlpriv->dm.inform_fw_driverctrldm) { | ||
233 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); | 246 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); |
234 | rtlpriv->dm.inform_fw_driverctrldm = true; | 247 | rtlpriv->dm.inform_fw_driverctrldm = true; |
235 | } | 248 | } |
236 | 249 | ||
237 | rcu_read_lock(); | ||
238 | if (mac->opmode == NL80211_IFTYPE_STATION) | ||
239 | sta = get_sta(hw, mac->vif, mac->bssid); | ||
240 | if ((mac->link_state == MAC80211_LINKED) && | 250 | if ((mac->link_state == MAC80211_LINKED) && |
241 | (mac->opmode == NL80211_IFTYPE_STATION)) { | 251 | (mac->opmode == NL80211_IFTYPE_STATION)) { |
242 | switch (ra->pre_ratr_state) { | 252 | switch (ra->pre_ratr_state) { |
@@ -285,12 +295,16 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) | |||
285 | rtlpriv->dm.undec_sm_pwdb, ra->ratr_state, | 295 | rtlpriv->dm.undec_sm_pwdb, ra->ratr_state, |
286 | ra->pre_ratr_state, ra->ratr_state); | 296 | ra->pre_ratr_state, ra->ratr_state); |
287 | 297 | ||
288 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | 298 | rcu_read_lock(); |
299 | sta = rtl_find_sta(hw, mac->bssid); | ||
300 | if (sta) | ||
301 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | ||
289 | ra->ratr_state); | 302 | ra->ratr_state); |
303 | rcu_read_unlock(); | ||
304 | |||
290 | ra->pre_ratr_state = ra->ratr_state; | 305 | ra->pre_ratr_state = ra->ratr_state; |
291 | } | 306 | } |
292 | } | 307 | } |
293 | rcu_read_unlock(); | ||
294 | } | 308 | } |
295 | 309 | ||
296 | static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) | 310 | static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) |
@@ -370,7 +384,8 @@ static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) | |||
370 | ra->ratr_state = DM_RATR_STA_MAX; | 384 | ra->ratr_state = DM_RATR_STA_MAX; |
371 | ra->pre_ratr_state = DM_RATR_STA_MAX; | 385 | ra->pre_ratr_state = DM_RATR_STA_MAX; |
372 | 386 | ||
373 | if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) | 387 | if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER && |
388 | hal_get_firmwareversion(rtlpriv) >= 60) | ||
374 | rtlpriv->dm.useramask = true; | 389 | rtlpriv->dm.useramask = true; |
375 | else | 390 | else |
376 | rtlpriv->dm.useramask = false; | 391 | rtlpriv->dm.useramask = false; |
@@ -457,13 +472,13 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) | |||
457 | digtable->back_val = DM_DIG_BACKOFF; | 472 | digtable->back_val = DM_DIG_BACKOFF; |
458 | 473 | ||
459 | if ((digtable->rssi_val + 10 - digtable->back_val) > | 474 | if ((digtable->rssi_val + 10 - digtable->back_val) > |
460 | digtable->rx_gain_range_max) | 475 | digtable->rx_gain_max) |
461 | digtable->cur_igvalue = | 476 | digtable->cur_igvalue = |
462 | digtable->rx_gain_range_max; | 477 | digtable->rx_gain_max; |
463 | else if ((digtable->rssi_val + 10 - digtable->back_val) | 478 | else if ((digtable->rssi_val + 10 - digtable->back_val) |
464 | < digtable->rx_gain_range_min) | 479 | < digtable->rx_gain_min) |
465 | digtable->cur_igvalue = | 480 | digtable->cur_igvalue = |
466 | digtable->rx_gain_range_min; | 481 | digtable->rx_gain_min; |
467 | else | 482 | else |
468 | digtable->cur_igvalue = digtable->rssi_val + 10 | 483 | digtable->cur_igvalue = digtable->rssi_val + 10 |
469 | - digtable->back_val; | 484 | - digtable->back_val; |
@@ -475,7 +490,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) | |||
475 | 490 | ||
476 | if (falsealm_cnt->cnt_all > 16000) | 491 | if (falsealm_cnt->cnt_all > 16000) |
477 | digtable->cur_igvalue = | 492 | digtable->cur_igvalue = |
478 | digtable->rx_gain_range_max; | 493 | digtable->rx_gain_max; |
479 | /* connected -> connected or disconnected -> disconnected */ | 494 | /* connected -> connected or disconnected -> disconnected */ |
480 | } else { | 495 | } else { |
481 | /* Firmware control DIG, do nothing in driver dm */ | 496 | /* Firmware control DIG, do nothing in driver dm */ |
@@ -677,9 +692,9 @@ static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw) | |||
677 | /* for dig debug rssi value */ | 692 | /* for dig debug rssi value */ |
678 | digtable->rssi_val = 50; | 693 | digtable->rssi_val = 50; |
679 | digtable->back_val = DM_DIG_BACKOFF; | 694 | digtable->back_val = DM_DIG_BACKOFF; |
680 | digtable->rx_gain_range_max = DM_DIG_MAX; | 695 | digtable->rx_gain_max = DM_DIG_MAX; |
681 | 696 | ||
682 | digtable->rx_gain_range_min = DM_DIG_MIN; | 697 | digtable->rx_gain_min = DM_DIG_MIN; |
683 | 698 | ||
684 | digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX; | 699 | digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX; |
685 | digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN; | 700 | digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index 084e7773bce2..4f461786a7eb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c | |||
@@ -400,6 +400,39 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
400 | 400 | ||
401 | break; | 401 | break; |
402 | } | 402 | } |
403 | case HW_VAR_FW_LPS_ACTION: { | ||
404 | bool enter_fwlps = *((bool *)val); | ||
405 | u8 rpwm_val, fw_pwrmode; | ||
406 | bool fw_current_inps; | ||
407 | |||
408 | if (enter_fwlps) { | ||
409 | rpwm_val = 0x02; /* RF off */ | ||
410 | fw_current_inps = true; | ||
411 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
412 | HW_VAR_FW_PSMODE_STATUS, | ||
413 | (u8 *)(&fw_current_inps)); | ||
414 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
415 | HW_VAR_H2C_FW_PWRMODE, | ||
416 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
417 | |||
418 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
419 | HW_VAR_SET_RPWM, | ||
420 | (u8 *)(&rpwm_val)); | ||
421 | } else { | ||
422 | rpwm_val = 0x0C; /* RF on */ | ||
423 | fw_pwrmode = FW_PS_ACTIVE_MODE; | ||
424 | fw_current_inps = false; | ||
425 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
426 | (u8 *)(&rpwm_val)); | ||
427 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
428 | HW_VAR_H2C_FW_PWRMODE, | ||
429 | (u8 *)(&fw_pwrmode)); | ||
430 | |||
431 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
432 | HW_VAR_FW_PSMODE_STATUS, | ||
433 | (u8 *)(&fw_current_inps)); | ||
434 | } | ||
435 | break; } | ||
403 | default: | 436 | default: |
404 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 437 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
405 | "switch case not processed\n"); | 438 | "switch case not processed\n"); |
@@ -438,7 +471,7 @@ void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw) | |||
438 | 471 | ||
439 | } | 472 | } |
440 | 473 | ||
441 | static u8 _rtl92ce_halset_sysclk(struct ieee80211_hw *hw, u8 data) | 474 | static u8 _rtl92se_halset_sysclk(struct ieee80211_hw *hw, u8 data) |
442 | { | 475 | { |
443 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 476 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
444 | u8 waitcount = 100; | 477 | u8 waitcount = 100; |
@@ -547,7 +580,7 @@ static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw) | |||
547 | tmpu1b &= ~(BIT(6) | BIT(7)); | 580 | tmpu1b &= ~(BIT(6) | BIT(7)); |
548 | 581 | ||
549 | /* Set failed, return to prevent hang. */ | 582 | /* Set failed, return to prevent hang. */ |
550 | if (!_rtl92ce_halset_sysclk(hw, tmpu1b)) | 583 | if (!_rtl92se_halset_sysclk(hw, tmpu1b)) |
551 | return; | 584 | return; |
552 | } | 585 | } |
553 | 586 | ||
@@ -650,7 +683,7 @@ static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw) | |||
650 | 683 | ||
651 | tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); | 684 | tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); |
652 | tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); | 685 | tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); |
653 | if (!_rtl92ce_halset_sysclk(hw, tmpu1b)) | 686 | if (!_rtl92se_halset_sysclk(hw, tmpu1b)) |
654 | return; /* Set failed, return to prevent hang. */ | 687 | return; /* Set failed, return to prevent hang. */ |
655 | 688 | ||
656 | rtl_write_word(rtlpriv, CMDR, 0x07FC); | 689 | rtl_write_word(rtlpriv, CMDR, 0x07FC); |
@@ -967,6 +1000,15 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) | |||
967 | return rtstatus; | 1000 | return rtstatus; |
968 | } | 1001 | } |
969 | 1002 | ||
1003 | /* because last function modify RCR, so we update | ||
1004 | * rcr var here, or TP will unstable for receive_config | ||
1005 | * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx | ||
1006 | * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 | ||
1007 | */ | ||
1008 | rtlpci->receive_config = rtl_read_dword(rtlpriv, RCR); | ||
1009 | rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); | ||
1010 | rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); | ||
1011 | |||
970 | /* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */ | 1012 | /* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */ |
971 | /* We must set flag avoid BB/RF config period later!! */ | 1013 | /* We must set flag avoid BB/RF config period later!! */ |
972 | rtl_write_dword(rtlpriv, CMDR, 0x37FC); | 1014 | rtl_write_dword(rtlpriv, CMDR, 0x37FC); |
@@ -982,25 +1024,6 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) | |||
982 | 1024 | ||
983 | rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; | 1025 | rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; |
984 | 1026 | ||
985 | /* RF Power Save */ | ||
986 | #if 0 | ||
987 | /* H/W or S/W RF OFF before sleep. */ | ||
988 | if (rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS) { | ||
989 | u32 rfoffreason = rtlpriv->psc.rfoff_reason; | ||
990 | |||
991 | rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT; | ||
992 | rtlpriv->psc.rfpwr_state = ERFON; | ||
993 | /* FIXME: check spinlocks if this block is uncommented */ | ||
994 | rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason); | ||
995 | } else { | ||
996 | /* gpio radio on/off is out of adapter start */ | ||
997 | if (rtlpriv->psc.hwradiooff == false) { | ||
998 | rtlpriv->psc.rfpwr_state = ERFON; | ||
999 | rtlpriv->psc.rfoff_reason = 0; | ||
1000 | } | ||
1001 | } | ||
1002 | #endif | ||
1003 | |||
1004 | /* Before RF-R/W we must execute the IO from Scott's suggestion. */ | 1027 | /* Before RF-R/W we must execute the IO from Scott's suggestion. */ |
1005 | rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, 0xDB); | 1028 | rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, 0xDB); |
1006 | if (rtlhal->version == VERSION_8192S_ACUT) | 1029 | if (rtlhal->version == VERSION_8192S_ACUT) |
@@ -1058,7 +1081,22 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) | |||
1058 | 1081 | ||
1059 | /* We enable high power and RA related mechanism after NIC | 1082 | /* We enable high power and RA related mechanism after NIC |
1060 | * initialized. */ | 1083 | * initialized. */ |
1061 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT); | 1084 | if (hal_get_firmwareversion(rtlpriv) >= 0x35) { |
1085 | /* Fw v.53 and later. */ | ||
1086 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT); | ||
1087 | } else if (hal_get_firmwareversion(rtlpriv) == 0x34) { | ||
1088 | /* Fw v.52. */ | ||
1089 | rtl_write_dword(rtlpriv, WFM5, FW_RA_INIT); | ||
1090 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1091 | } else { | ||
1092 | /* Compatible earlier FW version. */ | ||
1093 | rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET); | ||
1094 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1095 | rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE); | ||
1096 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1097 | rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH); | ||
1098 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1099 | } | ||
1062 | 1100 | ||
1063 | /* Add to prevent ASPM bug. */ | 1101 | /* Add to prevent ASPM bug. */ |
1064 | /* Always enable hst and NIC clock request. */ | 1102 | /* Always enable hst and NIC clock request. */ |
@@ -1229,7 +1267,6 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw) | |||
1229 | synchronize_irq(rtlpci->pdev->irq); | 1267 | synchronize_irq(rtlpci->pdev->irq); |
1230 | } | 1268 | } |
1231 | 1269 | ||
1232 | |||
1233 | static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) | 1270 | static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) |
1234 | { | 1271 | { |
1235 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1272 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -1754,7 +1791,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1754 | } | 1791 | } |
1755 | 1792 | ||
1756 | for (i = 0; i < 14; i++) { | 1793 | for (i = 0; i < 14; i++) { |
1757 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1794 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1758 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", | 1795 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", |
1759 | rf_path, i, | 1796 | rf_path, i, |
1760 | rtlefuse->txpwrlevel_cck[rf_path][i], | 1797 | rtlefuse->txpwrlevel_cck[rf_path][i], |
@@ -1791,11 +1828,11 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1791 | ((rtlefuse->eeprom_pwrgroup[rf_path][index] & | 1828 | ((rtlefuse->eeprom_pwrgroup[rf_path][index] & |
1792 | 0xf0) >> 4); | 1829 | 0xf0) >> 4); |
1793 | 1830 | ||
1794 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1831 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1795 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", | 1832 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", |
1796 | rf_path, i, | 1833 | rf_path, i, |
1797 | rtlefuse->pwrgroup_ht20[rf_path][i]); | 1834 | rtlefuse->pwrgroup_ht20[rf_path][i]); |
1798 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1835 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1799 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", | 1836 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", |
1800 | rf_path, i, | 1837 | rf_path, i, |
1801 | rtlefuse->pwrgroup_ht40[rf_path][i]); | 1838 | rtlefuse->pwrgroup_ht40[rf_path][i]); |
@@ -1850,27 +1887,27 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1850 | rtlefuse->eeprom_regulatory = | 1887 | rtlefuse->eeprom_regulatory = |
1851 | (hwinfo[EEPROM_REGULATORY] & 0x1); | 1888 | (hwinfo[EEPROM_REGULATORY] & 0x1); |
1852 | } | 1889 | } |
1853 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1890 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1854 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | 1891 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); |
1855 | 1892 | ||
1856 | for (i = 0; i < 14; i++) | 1893 | for (i = 0; i < 14; i++) |
1857 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1894 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1858 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", | 1895 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", |
1859 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); | 1896 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); |
1860 | for (i = 0; i < 14; i++) | 1897 | for (i = 0; i < 14; i++) |
1861 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1898 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1862 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", | 1899 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", |
1863 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); | 1900 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); |
1864 | for (i = 0; i < 14; i++) | 1901 | for (i = 0; i < 14; i++) |
1865 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1902 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1866 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", | 1903 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", |
1867 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); | 1904 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); |
1868 | for (i = 0; i < 14; i++) | 1905 | for (i = 0; i < 14; i++) |
1869 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1906 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1870 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", | 1907 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", |
1871 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); | 1908 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); |
1872 | 1909 | ||
1873 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1910 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1874 | "TxPwrSafetyFlag = %d\n", rtlefuse->txpwr_safetyflag); | 1911 | "TxPwrSafetyFlag = %d\n", rtlefuse->txpwr_safetyflag); |
1875 | 1912 | ||
1876 | /* Read RF-indication and Tx Power gain | 1913 | /* Read RF-indication and Tx Power gain |
@@ -1880,7 +1917,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1880 | rtlefuse->legacy_httxpowerdiff = | 1917 | rtlefuse->legacy_httxpowerdiff = |
1881 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0]; | 1918 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0]; |
1882 | 1919 | ||
1883 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1920 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1884 | "TxPowerDiff = %#x\n", rtlefuse->eeprom_txpowerdiff); | 1921 | "TxPowerDiff = %#x\n", rtlefuse->eeprom_txpowerdiff); |
1885 | 1922 | ||
1886 | /* Get TSSI value for each path. */ | 1923 | /* Get TSSI value for each path. */ |
@@ -1889,7 +1926,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1889 | usvalue = hwinfo[EEPROM_TSSI_B]; | 1926 | usvalue = hwinfo[EEPROM_TSSI_B]; |
1890 | rtlefuse->eeprom_tssi[RF90_PATH_B] = (u8)(usvalue & 0xff); | 1927 | rtlefuse->eeprom_tssi[RF90_PATH_B] = (u8)(usvalue & 0xff); |
1891 | 1928 | ||
1892 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", | 1929 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", |
1893 | rtlefuse->eeprom_tssi[RF90_PATH_A], | 1930 | rtlefuse->eeprom_tssi[RF90_PATH_A], |
1894 | rtlefuse->eeprom_tssi[RF90_PATH_B]); | 1931 | rtlefuse->eeprom_tssi[RF90_PATH_B]); |
1895 | 1932 | ||
@@ -1897,7 +1934,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1897 | /* and read ThermalMeter from EEPROM */ | 1934 | /* and read ThermalMeter from EEPROM */ |
1898 | tempval = hwinfo[EEPROM_THERMALMETER]; | 1935 | tempval = hwinfo[EEPROM_THERMALMETER]; |
1899 | rtlefuse->eeprom_thermalmeter = tempval; | 1936 | rtlefuse->eeprom_thermalmeter = tempval; |
1900 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1937 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1901 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | 1938 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); |
1902 | 1939 | ||
1903 | /* ThermalMeter, BIT(0)~3 for RFIC1, BIT(4)~7 for RFIC2 */ | 1940 | /* ThermalMeter, BIT(0)~3 for RFIC1, BIT(4)~7 for RFIC2 */ |
@@ -1914,7 +1951,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1914 | /* Version ID, Channel plan */ | 1951 | /* Version ID, Channel plan */ |
1915 | rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; | 1952 | rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; |
1916 | rtlefuse->txpwr_fromeprom = true; | 1953 | rtlefuse->txpwr_fromeprom = true; |
1917 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1954 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1918 | "EEPROM ChannelPlan = 0x%4x\n", rtlefuse->eeprom_channelplan); | 1955 | "EEPROM ChannelPlan = 0x%4x\n", rtlefuse->eeprom_channelplan); |
1919 | 1956 | ||
1920 | /* Read Customer ID or Board Type!!! */ | 1957 | /* Read Customer ID or Board Type!!! */ |
@@ -1999,6 +2036,8 @@ static void rtl92se_update_hal_rate_table(struct ieee80211_hw *hw, | |||
1999 | ratr_value = sta->supp_rates[1] << 4; | 2036 | ratr_value = sta->supp_rates[1] << 4; |
2000 | else | 2037 | else |
2001 | ratr_value = sta->supp_rates[0]; | 2038 | ratr_value = sta->supp_rates[0]; |
2039 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2040 | ratr_value = 0xfff; | ||
2002 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | 2041 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | |
2003 | sta->ht_cap.mcs.rx_mask[0] << 12); | 2042 | sta->ht_cap.mcs.rx_mask[0] << 12); |
2004 | switch (wirelessmode) { | 2043 | switch (wirelessmode) { |
@@ -2112,6 +2151,8 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw, | |||
2112 | ratr_bitmap = sta->supp_rates[1] << 4; | 2151 | ratr_bitmap = sta->supp_rates[1] << 4; |
2113 | else | 2152 | else |
2114 | ratr_bitmap = sta->supp_rates[0]; | 2153 | ratr_bitmap = sta->supp_rates[0]; |
2154 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2155 | ratr_bitmap = 0xfff; | ||
2115 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | 2156 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | |
2116 | sta->ht_cap.mcs.rx_mask[0] << 12); | 2157 | sta->ht_cap.mcs.rx_mask[0] << 12); |
2117 | switch (wirelessmode) { | 2158 | switch (wirelessmode) { |
@@ -2200,6 +2241,7 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw, | |||
2200 | ratr_bitmap &= 0x0f8ff0ff; | 2241 | ratr_bitmap &= 0x0f8ff0ff; |
2201 | break; | 2242 | break; |
2202 | } | 2243 | } |
2244 | sta_entry->ratr_index = ratr_index; | ||
2203 | 2245 | ||
2204 | if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) | 2246 | if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) |
2205 | ratr_bitmap &= 0x0FFFFFFF; | 2247 | ratr_bitmap &= 0x0FFFFFFF; |
@@ -2438,23 +2480,9 @@ void rtl92se_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, | |||
2438 | rtl_cam_del_entry(hw, p_macaddr); | 2480 | rtl_cam_del_entry(hw, p_macaddr); |
2439 | rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); | 2481 | rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); |
2440 | } else { | 2482 | } else { |
2441 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, | ||
2442 | "The insert KEY length is %d\n", | ||
2443 | rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); | ||
2444 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, | ||
2445 | "The insert KEY is %x %x\n", | ||
2446 | rtlpriv->sec.key_buf[0][0], | ||
2447 | rtlpriv->sec.key_buf[0][1]); | ||
2448 | |||
2449 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 2483 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
2450 | "add one entry\n"); | 2484 | "add one entry\n"); |
2451 | if (is_pairwise) { | 2485 | if (is_pairwise) { |
2452 | RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, | ||
2453 | "Pairwise Key content", | ||
2454 | rtlpriv->sec.pairwise_key, | ||
2455 | rtlpriv->sec. | ||
2456 | key_len[PAIRWISE_KEYIDX]); | ||
2457 | |||
2458 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 2486 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
2459 | "set Pairwise key\n"); | 2487 | "set Pairwise key\n"); |
2460 | 2488 | ||
@@ -2502,3 +2530,23 @@ void rtl92se_resume(struct ieee80211_hw *hw) | |||
2502 | pci_write_config_dword(rtlpci->pdev, 0x40, | 2530 | pci_write_config_dword(rtlpci->pdev, 0x40, |
2503 | val & 0xffff00ff); | 2531 | val & 0xffff00ff); |
2504 | } | 2532 | } |
2533 | |||
2534 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
2535 | void rtl92se_allow_all_destaddr(struct ieee80211_hw *hw, | ||
2536 | bool allow_all_da, bool write_into_reg) | ||
2537 | { | ||
2538 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2539 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
2540 | |||
2541 | if (allow_all_da) /* Set BIT0 */ | ||
2542 | rtlpci->receive_config |= RCR_AAP; | ||
2543 | else /* Clear BIT0 */ | ||
2544 | rtlpci->receive_config &= ~RCR_AAP; | ||
2545 | |||
2546 | if (write_into_reg) | ||
2547 | rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); | ||
2548 | |||
2549 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
2550 | "receive_config=0x%08X, write_into_reg=%d\n", | ||
2551 | rtlpci->receive_config, write_into_reg); | ||
2552 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h index a8e068c76e47..da48aa8cbe6f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h | |||
@@ -74,6 +74,7 @@ void rtl92se_set_key(struct ieee80211_hw *hw, | |||
74 | u8 enc_algo, bool is_wepkey, bool clear_all); | 74 | u8 enc_algo, bool is_wepkey, bool clear_all); |
75 | void rtl92se_suspend(struct ieee80211_hw *hw); | 75 | void rtl92se_suspend(struct ieee80211_hw *hw); |
76 | void rtl92se_resume(struct ieee80211_hw *hw); | 76 | void rtl92se_resume(struct ieee80211_hw *hw); |
77 | void rtl92se_allow_all_destaddr(struct ieee80211_hw *hw, | ||
78 | bool allow_all_da, bool write_into_reg); | ||
77 | 79 | ||
78 | #endif | 80 | #endif |
79 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index 67404975e00b..9c092e6eb3fe 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c | |||
@@ -1307,6 +1307,8 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw) | |||
1307 | if (is_hal_stop(rtlhal)) | 1307 | if (is_hal_stop(rtlhal)) |
1308 | return; | 1308 | return; |
1309 | 1309 | ||
1310 | if (hal_get_firmwareversion(rtlpriv) < 0x34) | ||
1311 | goto skip; | ||
1310 | /* We re-map RA related CMD IO to combinational ones */ | 1312 | /* We re-map RA related CMD IO to combinational ones */ |
1311 | /* if FW version is v.52 or later. */ | 1313 | /* if FW version is v.52 or later. */ |
1312 | switch (rtlhal->current_fwcmd_io) { | 1314 | switch (rtlhal->current_fwcmd_io) { |
@@ -1320,6 +1322,7 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw) | |||
1320 | break; | 1322 | break; |
1321 | } | 1323 | } |
1322 | 1324 | ||
1325 | skip: | ||
1323 | switch (rtlhal->current_fwcmd_io) { | 1326 | switch (rtlhal->current_fwcmd_io) { |
1324 | case FW_CMD_RA_RESET: | 1327 | case FW_CMD_RA_RESET: |
1325 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_RESET\n"); | 1328 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_RESET\n"); |
@@ -1440,7 +1443,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | |||
1440 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | 1443 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
1441 | u32 fw_param = FW_CMD_IO_PARA_QUERY(rtlpriv); | 1444 | u32 fw_param = FW_CMD_IO_PARA_QUERY(rtlpriv); |
1442 | u16 fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv); | 1445 | u16 fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv); |
1443 | bool bPostProcessing = false; | 1446 | bool postprocessing = false; |
1444 | 1447 | ||
1445 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | 1448 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, |
1446 | "Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n", | 1449 | "Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n", |
@@ -1449,15 +1452,24 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | |||
1449 | do { | 1452 | do { |
1450 | /* We re-map to combined FW CMD ones if firmware version */ | 1453 | /* We re-map to combined FW CMD ones if firmware version */ |
1451 | /* is v.53 or later. */ | 1454 | /* is v.53 or later. */ |
1452 | switch (fw_cmdio) { | 1455 | if (hal_get_firmwareversion(rtlpriv) >= 0x35) { |
1453 | case FW_CMD_RA_REFRESH_N: | 1456 | switch (fw_cmdio) { |
1454 | fw_cmdio = FW_CMD_RA_REFRESH_N_COMB; | 1457 | case FW_CMD_RA_REFRESH_N: |
1455 | break; | 1458 | fw_cmdio = FW_CMD_RA_REFRESH_N_COMB; |
1456 | case FW_CMD_RA_REFRESH_BG: | 1459 | break; |
1457 | fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB; | 1460 | case FW_CMD_RA_REFRESH_BG: |
1458 | break; | 1461 | fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB; |
1459 | default: | 1462 | break; |
1460 | break; | 1463 | default: |
1464 | break; | ||
1465 | } | ||
1466 | } else { | ||
1467 | if ((fw_cmdio == FW_CMD_IQK_ENABLE) || | ||
1468 | (fw_cmdio == FW_CMD_RA_REFRESH_N) || | ||
1469 | (fw_cmdio == FW_CMD_RA_REFRESH_BG)) { | ||
1470 | postprocessing = true; | ||
1471 | break; | ||
1472 | } | ||
1461 | } | 1473 | } |
1462 | 1474 | ||
1463 | /* If firmware version is v.62 or later, | 1475 | /* If firmware version is v.62 or later, |
@@ -1588,19 +1600,19 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | |||
1588 | fw_cmdmap &= ~FW_DIG_ENABLE_CTL; | 1600 | fw_cmdmap &= ~FW_DIG_ENABLE_CTL; |
1589 | 1601 | ||
1590 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | 1602 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); |
1591 | bPostProcessing = true; | 1603 | postprocessing = true; |
1592 | break; | 1604 | break; |
1593 | case FW_CMD_PAUSE_DM_BY_SCAN: | 1605 | case FW_CMD_PAUSE_DM_BY_SCAN: |
1594 | fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | | 1606 | fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | |
1595 | FW_HIGH_PWR_ENABLE_CTL | | 1607 | FW_HIGH_PWR_ENABLE_CTL | |
1596 | FW_SS_CTL); | 1608 | FW_SS_CTL); |
1597 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | 1609 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); |
1598 | bPostProcessing = true; | 1610 | postprocessing = true; |
1599 | break; | 1611 | break; |
1600 | case FW_CMD_HIGH_PWR_DISABLE: | 1612 | case FW_CMD_HIGH_PWR_DISABLE: |
1601 | fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; | 1613 | fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; |
1602 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | 1614 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); |
1603 | bPostProcessing = true; | 1615 | postprocessing = true; |
1604 | break; | 1616 | break; |
1605 | case FW_CMD_HIGH_PWR_ENABLE: | 1617 | case FW_CMD_HIGH_PWR_ENABLE: |
1606 | if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) && | 1618 | if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) && |
@@ -1608,7 +1620,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | |||
1608 | fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL | | 1620 | fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL | |
1609 | FW_SS_CTL); | 1621 | FW_SS_CTL); |
1610 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | 1622 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); |
1611 | bPostProcessing = true; | 1623 | postprocessing = true; |
1612 | } | 1624 | } |
1613 | break; | 1625 | break; |
1614 | case FW_CMD_DIG_MODE_FA: | 1626 | case FW_CMD_DIG_MODE_FA: |
@@ -1629,14 +1641,15 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | |||
1629 | default: | 1641 | default: |
1630 | /* Pass to original FW CMD processing callback | 1642 | /* Pass to original FW CMD processing callback |
1631 | * routine. */ | 1643 | * routine. */ |
1632 | bPostProcessing = true; | 1644 | postprocessing = true; |
1633 | break; | 1645 | break; |
1634 | } | 1646 | } |
1635 | } while (false); | 1647 | } while (false); |
1636 | 1648 | ||
1637 | /* We shall post processing these FW CMD if | 1649 | /* We shall post processing these FW CMD if |
1638 | * variable bPostProcessing is set. */ | 1650 | * variable postprocessing is set. |
1639 | if (bPostProcessing && !rtlhal->set_fwcmd_inprogress) { | 1651 | */ |
1652 | if (postprocessing && !rtlhal->set_fwcmd_inprogress) { | ||
1640 | rtlhal->set_fwcmd_inprogress = true; | 1653 | rtlhal->set_fwcmd_inprogress = true; |
1641 | /* Update current FW Cmd for callback use. */ | 1654 | /* Update current FW Cmd for callback use. */ |
1642 | rtlhal->current_fwcmd_io = fw_cmdio; | 1655 | rtlhal->current_fwcmd_io = fw_cmdio; |
@@ -1697,8 +1710,18 @@ void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw) | |||
1697 | 1710 | ||
1698 | } | 1711 | } |
1699 | 1712 | ||
1700 | void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 BeaconInterval) | 1713 | void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval) |
1701 | { | 1714 | { |
1702 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1715 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1703 | rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | (BeaconInterval << 8)); | 1716 | u32 new_bcn_num = 0; |
1717 | |||
1718 | if (hal_get_firmwareversion(rtlpriv) >= 0x33) { | ||
1719 | /* Fw v.51 and later. */ | ||
1720 | rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | | ||
1721 | (beaconinterval << 8)); | ||
1722 | } else { | ||
1723 | new_bcn_num = beaconinterval * 32 - 64; | ||
1724 | rtl_write_dword(rtlpriv, WFM3 + 4, new_bcn_num); | ||
1725 | rtl_write_dword(rtlpriv, WFM3, 0xB026007C); | ||
1726 | } | ||
1704 | } | 1727 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h index ac0387770630..8acf4765a7a6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define MAX_POSTCMD_CNT 16 | 39 | #define MAX_POSTCMD_CNT 16 |
40 | 40 | ||
41 | #define RF90_PATH_MAX 4 | 41 | #define RF90_PATH_MAX 4 |
42 | #define RF6052_MAX_PATH 2 | ||
42 | 43 | ||
43 | enum version_8192s { | 44 | enum version_8192s { |
44 | VERSION_8192S_ACUT, | 45 | VERSION_8192S_ACUT, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index cecc377e9e61..2e8e6f8d2d51 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c | |||
@@ -290,6 +290,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = { | |||
290 | .enable_hw_sec = rtl92se_enable_hw_security_config, | 290 | .enable_hw_sec = rtl92se_enable_hw_security_config, |
291 | .set_key = rtl92se_set_key, | 291 | .set_key = rtl92se_set_key, |
292 | .init_sw_leds = rtl92se_init_sw_leds, | 292 | .init_sw_leds = rtl92se_init_sw_leds, |
293 | .allow_all_destaddr = rtl92se_allow_all_destaddr, | ||
293 | .get_bbreg = rtl92s_phy_query_bb_reg, | 294 | .get_bbreg = rtl92s_phy_query_bb_reg, |
294 | .set_bbreg = rtl92s_phy_set_bb_reg, | 295 | .set_bbreg = rtl92s_phy_set_bb_reg, |
295 | .get_rfreg = rtl92s_phy_query_rf_reg, | 296 | .get_rfreg = rtl92s_phy_query_rf_reg, |
@@ -366,7 +367,7 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = { | |||
366 | 367 | ||
367 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | 368 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, |
368 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | 369 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, |
369 | .maps[RTL_IMR_BcnInt] = IMR_BCNINT, | 370 | .maps[RTL_IMR_BCNINT] = IMR_BCNINT, |
370 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | 371 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, |
371 | .maps[RTL_IMR_RDU] = IMR_RDU, | 372 | .maps[RTL_IMR_RDU] = IMR_RDU, |
372 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | 373 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 0b074f11f969..c7095118de6e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "../wifi.h" | 30 | #include "../wifi.h" |
31 | #include "../pci.h" | 31 | #include "../pci.h" |
32 | #include "../base.h" | 32 | #include "../base.h" |
33 | #include "../stats.h" | ||
33 | #include "reg.h" | 34 | #include "reg.h" |
34 | #include "def.h" | 35 | #include "def.h" |
35 | #include "phy.h" | 36 | #include "phy.h" |
@@ -43,7 +44,7 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) | |||
43 | 44 | ||
44 | if (unlikely(ieee80211_is_beacon(fc))) | 45 | if (unlikely(ieee80211_is_beacon(fc))) |
45 | return QSLT_BEACON; | 46 | return QSLT_BEACON; |
46 | if (ieee80211_is_mgmt(fc)) | 47 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) |
47 | return QSLT_MGNT; | 48 | return QSLT_MGNT; |
48 | if (ieee80211_is_nullfunc(fc)) | 49 | if (ieee80211_is_nullfunc(fc)) |
49 | return QSLT_HIGH; | 50 | return QSLT_HIGH; |
@@ -51,65 +52,6 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) | |||
51 | return skb->priority; | 52 | return skb->priority; |
52 | } | 53 | } |
53 | 54 | ||
54 | static u8 _rtl92s_query_rxpwrpercentage(char antpower) | ||
55 | { | ||
56 | if ((antpower <= -100) || (antpower >= 20)) | ||
57 | return 0; | ||
58 | else if (antpower >= 0) | ||
59 | return 100; | ||
60 | else | ||
61 | return 100 + antpower; | ||
62 | } | ||
63 | |||
64 | static u8 _rtl92s_evm_db_to_percentage(char value) | ||
65 | { | ||
66 | char ret_val; | ||
67 | ret_val = value; | ||
68 | |||
69 | if (ret_val >= 0) | ||
70 | ret_val = 0; | ||
71 | |||
72 | if (ret_val <= -33) | ||
73 | ret_val = -33; | ||
74 | |||
75 | ret_val = 0 - ret_val; | ||
76 | ret_val *= 3; | ||
77 | |||
78 | if (ret_val == 99) | ||
79 | ret_val = 100; | ||
80 | |||
81 | return ret_val; | ||
82 | } | ||
83 | |||
84 | static long _rtl92se_translate_todbm(struct ieee80211_hw *hw, | ||
85 | u8 signal_strength_index) | ||
86 | { | ||
87 | long signal_power; | ||
88 | |||
89 | signal_power = (long)((signal_strength_index + 1) >> 1); | ||
90 | signal_power -= 95; | ||
91 | return signal_power; | ||
92 | } | ||
93 | |||
94 | static long _rtl92se_signal_scale_mapping(struct ieee80211_hw *hw, | ||
95 | long currsig) | ||
96 | { | ||
97 | long retsig = 0; | ||
98 | |||
99 | /* Step 1. Scale mapping. */ | ||
100 | if (currsig > 47) | ||
101 | retsig = 100; | ||
102 | else if (currsig > 14 && currsig <= 47) | ||
103 | retsig = 100 - ((47 - currsig) * 3) / 2; | ||
104 | else if (currsig > 2 && currsig <= 14) | ||
105 | retsig = 48 - ((14 - currsig) * 15) / 7; | ||
106 | else if (currsig >= 0) | ||
107 | retsig = currsig * 9 + 1; | ||
108 | |||
109 | return retsig; | ||
110 | } | ||
111 | |||
112 | |||
113 | static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | 55 | static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, |
114 | struct rtl_stats *pstats, u8 *pdesc, | 56 | struct rtl_stats *pstats, u8 *pdesc, |
115 | struct rx_fwinfo *p_drvinfo, | 57 | struct rx_fwinfo *p_drvinfo, |
@@ -119,11 +61,11 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
119 | { | 61 | { |
120 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 62 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
121 | struct phy_sts_cck_8192s_t *cck_buf; | 63 | struct phy_sts_cck_8192s_t *cck_buf; |
64 | struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); | ||
122 | s8 rx_pwr_all = 0, rx_pwr[4]; | 65 | s8 rx_pwr_all = 0, rx_pwr[4]; |
123 | u8 rf_rx_num = 0, evm, pwdb_all; | 66 | u8 rf_rx_num = 0, evm, pwdb_all; |
124 | u8 i, max_spatial_stream; | 67 | u8 i, max_spatial_stream; |
125 | u32 rssi, total_rssi = 0; | 68 | u32 rssi, total_rssi = 0; |
126 | bool in_powersavemode = false; | ||
127 | bool is_cck = pstats->is_cck; | 69 | bool is_cck = pstats->is_cck; |
128 | 70 | ||
129 | pstats->packet_matchbssid = packet_match_bssid; | 71 | pstats->packet_matchbssid = packet_match_bssid; |
@@ -136,7 +78,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
136 | u8 report, cck_highpwr; | 78 | u8 report, cck_highpwr; |
137 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; | 79 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; |
138 | 80 | ||
139 | if (!in_powersavemode) | 81 | if (ppsc->rfpwr_state == ERFON) |
140 | cck_highpwr = (u8) rtl_get_bbreg(hw, | 82 | cck_highpwr = (u8) rtl_get_bbreg(hw, |
141 | RFPGA0_XA_HSSIPARAMETER2, | 83 | RFPGA0_XA_HSSIPARAMETER2, |
142 | 0x200); | 84 | 0x200); |
@@ -181,7 +123,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
181 | } | 123 | } |
182 | } | 124 | } |
183 | 125 | ||
184 | pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all); | 126 | pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); |
185 | 127 | ||
186 | /* CCK gain is smaller than OFDM/MCS gain, */ | 128 | /* CCK gain is smaller than OFDM/MCS gain, */ |
187 | /* so we add gain diff by experiences, the val is 6 */ | 129 | /* so we add gain diff by experiences, the val is 6 */ |
@@ -222,13 +164,13 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
222 | } else { | 164 | } else { |
223 | rtlpriv->dm.rfpath_rxenable[0] = | 165 | rtlpriv->dm.rfpath_rxenable[0] = |
224 | rtlpriv->dm.rfpath_rxenable[1] = true; | 166 | rtlpriv->dm.rfpath_rxenable[1] = true; |
225 | for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { | 167 | for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { |
226 | if (rtlpriv->dm.rfpath_rxenable[i]) | 168 | if (rtlpriv->dm.rfpath_rxenable[i]) |
227 | rf_rx_num++; | 169 | rf_rx_num++; |
228 | 170 | ||
229 | rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & | 171 | rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & |
230 | 0x3f) * 2) - 110; | 172 | 0x3f) * 2) - 110; |
231 | rssi = _rtl92s_query_rxpwrpercentage(rx_pwr[i]); | 173 | rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); |
232 | total_rssi += rssi; | 174 | total_rssi += rssi; |
233 | rtlpriv->stats.rx_snr_db[i] = | 175 | rtlpriv->stats.rx_snr_db[i] = |
234 | (long)(p_drvinfo->rxsnr[i] / 2); | 176 | (long)(p_drvinfo->rxsnr[i] / 2); |
@@ -238,7 +180,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
238 | } | 180 | } |
239 | 181 | ||
240 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; | 182 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; |
241 | pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all); | 183 | pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); |
242 | pstats->rx_pwdb_all = pwdb_all; | 184 | pstats->rx_pwdb_all = pwdb_all; |
243 | pstats->rxpower = rx_pwr_all; | 185 | pstats->rxpower = rx_pwr_all; |
244 | pstats->recvsignalpower = rx_pwr_all; | 186 | pstats->recvsignalpower = rx_pwr_all; |
@@ -250,7 +192,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
250 | max_spatial_stream = 1; | 192 | max_spatial_stream = 1; |
251 | 193 | ||
252 | for (i = 0; i < max_spatial_stream; i++) { | 194 | for (i = 0; i < max_spatial_stream; i++) { |
253 | evm = _rtl92s_evm_db_to_percentage(p_drvinfo->rxevm[i]); | 195 | evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]); |
254 | 196 | ||
255 | if (packet_match_bssid) { | 197 | if (packet_match_bssid) { |
256 | if (i == 0) | 198 | if (i == 0) |
@@ -262,212 +204,13 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
262 | } | 204 | } |
263 | 205 | ||
264 | if (is_cck) | 206 | if (is_cck) |
265 | pstats->signalstrength = (u8)(_rtl92se_signal_scale_mapping(hw, | 207 | pstats->signalstrength = (u8)(rtl_signal_scale_mapping(hw, |
266 | pwdb_all)); | 208 | pwdb_all)); |
267 | else if (rf_rx_num != 0) | 209 | else if (rf_rx_num != 0) |
268 | pstats->signalstrength = (u8) (_rtl92se_signal_scale_mapping(hw, | 210 | pstats->signalstrength = (u8) (rtl_signal_scale_mapping(hw, |
269 | total_rssi /= rf_rx_num)); | 211 | total_rssi /= rf_rx_num)); |
270 | } | 212 | } |
271 | 213 | ||
272 | static void _rtl92se_process_ui_rssi(struct ieee80211_hw *hw, | ||
273 | struct rtl_stats *pstats) | ||
274 | { | ||
275 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
276 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
277 | u8 rfpath; | ||
278 | u32 last_rssi, tmpval; | ||
279 | |||
280 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
281 | rtlpriv->stats.rssi_calculate_cnt++; | ||
282 | |||
283 | if (rtlpriv->stats.ui_rssi.total_num++ >= | ||
284 | PHY_RSSI_SLID_WIN_MAX) { | ||
285 | rtlpriv->stats.ui_rssi.total_num = | ||
286 | PHY_RSSI_SLID_WIN_MAX; | ||
287 | last_rssi = rtlpriv->stats.ui_rssi.elements[ | ||
288 | rtlpriv->stats.ui_rssi.index]; | ||
289 | rtlpriv->stats.ui_rssi.total_val -= last_rssi; | ||
290 | } | ||
291 | |||
292 | rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; | ||
293 | rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] | ||
294 | = pstats->signalstrength; | ||
295 | |||
296 | if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) | ||
297 | rtlpriv->stats.ui_rssi.index = 0; | ||
298 | |||
299 | tmpval = rtlpriv->stats.ui_rssi.total_val / | ||
300 | rtlpriv->stats.ui_rssi.total_num; | ||
301 | rtlpriv->stats.signal_strength = _rtl92se_translate_todbm(hw, | ||
302 | (u8) tmpval); | ||
303 | pstats->rssi = rtlpriv->stats.signal_strength; | ||
304 | } | ||
305 | |||
306 | if (!pstats->is_cck && pstats->packet_toself) { | ||
307 | for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; | ||
308 | rfpath++) { | ||
309 | if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { | ||
310 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
311 | pstats->rx_mimo_signalstrength[rfpath]; | ||
312 | |||
313 | } | ||
314 | |||
315 | if (pstats->rx_mimo_signalstrength[rfpath] > | ||
316 | rtlpriv->stats.rx_rssi_percentage[rfpath]) { | ||
317 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
318 | ((rtlpriv->stats.rx_rssi_percentage[rfpath] | ||
319 | * (RX_SMOOTH_FACTOR - 1)) + | ||
320 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
321 | (RX_SMOOTH_FACTOR); | ||
322 | |||
323 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
324 | rtlpriv->stats.rx_rssi_percentage[rfpath] | ||
325 | + 1; | ||
326 | } else { | ||
327 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
328 | ((rtlpriv->stats.rx_rssi_percentage[rfpath] | ||
329 | * (RX_SMOOTH_FACTOR - 1)) + | ||
330 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
331 | (RX_SMOOTH_FACTOR); | ||
332 | } | ||
333 | |||
334 | } | ||
335 | } | ||
336 | } | ||
337 | |||
338 | static void _rtl92se_update_rxsignalstatistics(struct ieee80211_hw *hw, | ||
339 | struct rtl_stats *pstats) | ||
340 | { | ||
341 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
342 | int weighting = 0; | ||
343 | |||
344 | if (rtlpriv->stats.recv_signal_power == 0) | ||
345 | rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; | ||
346 | |||
347 | if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) | ||
348 | weighting = 5; | ||
349 | else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) | ||
350 | weighting = (-5); | ||
351 | |||
352 | rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * 5 | ||
353 | + pstats->recvsignalpower + | ||
354 | weighting) / 6; | ||
355 | } | ||
356 | |||
357 | static void _rtl92se_process_pwdb(struct ieee80211_hw *hw, | ||
358 | struct rtl_stats *pstats) | ||
359 | { | ||
360 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
361 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
362 | long undec_sm_pwdb = 0; | ||
363 | |||
364 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
365 | return; | ||
366 | } else { | ||
367 | undec_sm_pwdb = | ||
368 | rtlpriv->dm.undec_sm_pwdb; | ||
369 | } | ||
370 | |||
371 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
372 | if (undec_sm_pwdb < 0) | ||
373 | undec_sm_pwdb = pstats->rx_pwdb_all; | ||
374 | |||
375 | if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { | ||
376 | undec_sm_pwdb = | ||
377 | (((undec_sm_pwdb) * | ||
378 | (RX_SMOOTH_FACTOR - 1)) + | ||
379 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
380 | |||
381 | undec_sm_pwdb = undec_sm_pwdb + 1; | ||
382 | } else { | ||
383 | undec_sm_pwdb = (((undec_sm_pwdb) * | ||
384 | (RX_SMOOTH_FACTOR - 1)) + (pstats->rx_pwdb_all)) / | ||
385 | (RX_SMOOTH_FACTOR); | ||
386 | } | ||
387 | |||
388 | rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; | ||
389 | _rtl92se_update_rxsignalstatistics(hw, pstats); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | static void rtl_92s_process_streams(struct ieee80211_hw *hw, | ||
394 | struct rtl_stats *pstats) | ||
395 | { | ||
396 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
397 | u32 stream; | ||
398 | |||
399 | for (stream = 0; stream < 2; stream++) { | ||
400 | if (pstats->rx_mimo_sig_qual[stream] != -1) { | ||
401 | if (rtlpriv->stats.rx_evm_percentage[stream] == 0) { | ||
402 | rtlpriv->stats.rx_evm_percentage[stream] = | ||
403 | pstats->rx_mimo_sig_qual[stream]; | ||
404 | } | ||
405 | |||
406 | rtlpriv->stats.rx_evm_percentage[stream] = | ||
407 | ((rtlpriv->stats.rx_evm_percentage[stream] * | ||
408 | (RX_SMOOTH_FACTOR - 1)) + | ||
409 | (pstats->rx_mimo_sig_qual[stream] * | ||
410 | 1)) / (RX_SMOOTH_FACTOR); | ||
411 | } | ||
412 | } | ||
413 | } | ||
414 | |||
415 | static void _rtl92se_process_ui_link_quality(struct ieee80211_hw *hw, | ||
416 | struct rtl_stats *pstats) | ||
417 | { | ||
418 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
419 | u32 last_evm = 0, tmpval; | ||
420 | |||
421 | if (pstats->signalquality != 0) { | ||
422 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
423 | |||
424 | if (rtlpriv->stats.ui_link_quality.total_num++ >= | ||
425 | PHY_LINKQUALITY_SLID_WIN_MAX) { | ||
426 | rtlpriv->stats.ui_link_quality.total_num = | ||
427 | PHY_LINKQUALITY_SLID_WIN_MAX; | ||
428 | last_evm = | ||
429 | rtlpriv->stats.ui_link_quality.elements[ | ||
430 | rtlpriv->stats.ui_link_quality.index]; | ||
431 | rtlpriv->stats.ui_link_quality.total_val -= | ||
432 | last_evm; | ||
433 | } | ||
434 | |||
435 | rtlpriv->stats.ui_link_quality.total_val += | ||
436 | pstats->signalquality; | ||
437 | rtlpriv->stats.ui_link_quality.elements[ | ||
438 | rtlpriv->stats.ui_link_quality.index++] = | ||
439 | pstats->signalquality; | ||
440 | |||
441 | if (rtlpriv->stats.ui_link_quality.index >= | ||
442 | PHY_LINKQUALITY_SLID_WIN_MAX) | ||
443 | rtlpriv->stats.ui_link_quality.index = 0; | ||
444 | |||
445 | tmpval = rtlpriv->stats.ui_link_quality.total_val / | ||
446 | rtlpriv->stats.ui_link_quality.total_num; | ||
447 | rtlpriv->stats.signal_quality = tmpval; | ||
448 | |||
449 | rtlpriv->stats.last_sigstrength_inpercent = tmpval; | ||
450 | |||
451 | rtl_92s_process_streams(hw, pstats); | ||
452 | |||
453 | } | ||
454 | } | ||
455 | } | ||
456 | |||
457 | static void _rtl92se_process_phyinfo(struct ieee80211_hw *hw, | ||
458 | u8 *buffer, | ||
459 | struct rtl_stats *pcurrent_stats) | ||
460 | { | ||
461 | |||
462 | if (!pcurrent_stats->packet_matchbssid && | ||
463 | !pcurrent_stats->packet_beacon) | ||
464 | return; | ||
465 | |||
466 | _rtl92se_process_ui_rssi(hw, pcurrent_stats); | ||
467 | _rtl92se_process_pwdb(hw, pcurrent_stats); | ||
468 | _rtl92se_process_ui_link_quality(hw, pcurrent_stats); | ||
469 | } | ||
470 | |||
471 | static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, | 214 | static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, |
472 | struct sk_buff *skb, struct rtl_stats *pstats, | 215 | struct sk_buff *skb, struct rtl_stats *pstats, |
473 | u8 *pdesc, struct rx_fwinfo *p_drvinfo) | 216 | u8 *pdesc, struct rx_fwinfo *p_drvinfo) |
@@ -505,7 +248,7 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, | |||
505 | 248 | ||
506 | _rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, | 249 | _rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, |
507 | packet_matchbssid, packet_toself, packet_beacon); | 250 | packet_matchbssid, packet_toself, packet_beacon); |
508 | _rtl92se_process_phyinfo(hw, tmp_buf, pstats); | 251 | rtl_process_phyinfo(hw, tmp_buf, pstats); |
509 | } | 252 | } |
510 | 253 | ||
511 | bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | 254 | bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, |
@@ -541,9 +284,6 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | |||
541 | rx_status->freq = hw->conf.chandef.chan->center_freq; | 284 | rx_status->freq = hw->conf.chandef.chan->center_freq; |
542 | rx_status->band = hw->conf.chandef.chan->band; | 285 | rx_status->band = hw->conf.chandef.chan->band; |
543 | 286 | ||
544 | hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size | ||
545 | + stats->rx_bufshift); | ||
546 | |||
547 | if (stats->crc) | 287 | if (stats->crc) |
548 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | 288 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
549 | 289 | ||
@@ -563,6 +303,13 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | |||
563 | * for IEEE80211w frame, and mac80211 sw will help | 303 | * for IEEE80211w frame, and mac80211 sw will help |
564 | * to decrypt it */ | 304 | * to decrypt it */ |
565 | if (stats->decrypted) { | 305 | if (stats->decrypted) { |
306 | hdr = (struct ieee80211_hdr *)(skb->data + | ||
307 | stats->rx_drvinfo_size + stats->rx_bufshift); | ||
308 | |||
309 | if (!hdr) { | ||
310 | /* during testing, hdr was NULL here */ | ||
311 | return false; | ||
312 | } | ||
566 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | 313 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && |
567 | (ieee80211_has_protected(hdr->frame_control))) | 314 | (ieee80211_has_protected(hdr->frame_control))) |
568 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | 315 | rx_status->flag &= ~RX_FLAG_DECRYPTED; |
@@ -630,6 +377,11 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, | |||
630 | 377 | ||
631 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S); | 378 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S); |
632 | 379 | ||
380 | if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { | ||
381 | firstseg = true; | ||
382 | lastseg = true; | ||
383 | } | ||
384 | |||
633 | if (firstseg) { | 385 | if (firstseg) { |
634 | if (rtlpriv->dm.useramask) { | 386 | if (rtlpriv->dm.useramask) { |
635 | /* set txdesc macId */ | 387 | /* set txdesc macId */ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c index 12e2a3cb0701..a36eee28f9e7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c | |||
@@ -166,8 +166,8 @@ static void rtl8723ae_dm_diginit(struct ieee80211_hw *hw) | |||
166 | dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; | 166 | dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; |
167 | dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; | 167 | dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; |
168 | dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; | 168 | dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; |
169 | dm_digtable->rx_gain_range_max = DM_DIG_MAX; | 169 | dm_digtable->rx_gain_max = DM_DIG_MAX; |
170 | dm_digtable->rx_gain_range_min = DM_DIG_MIN; | 170 | dm_digtable->rx_gain_min = DM_DIG_MIN; |
171 | dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; | 171 | dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; |
172 | dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; | 172 | dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; |
173 | dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; | 173 | dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; |
@@ -291,11 +291,11 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) | |||
291 | } | 291 | } |
292 | 292 | ||
293 | if ((dgtbl->rssi_val_min + 10 - dgtbl->back_val) > | 293 | if ((dgtbl->rssi_val_min + 10 - dgtbl->back_val) > |
294 | dgtbl->rx_gain_range_max) | 294 | dgtbl->rx_gain_max) |
295 | dgtbl->cur_igvalue = dgtbl->rx_gain_range_max; | 295 | dgtbl->cur_igvalue = dgtbl->rx_gain_max; |
296 | else if ((dgtbl->rssi_val_min + 10 - | 296 | else if ((dgtbl->rssi_val_min + 10 - |
297 | dgtbl->back_val) < dgtbl->rx_gain_range_min) | 297 | dgtbl->back_val) < dgtbl->rx_gain_min) |
298 | dgtbl->cur_igvalue = dgtbl->rx_gain_range_min; | 298 | dgtbl->cur_igvalue = dgtbl->rx_gain_min; |
299 | else | 299 | else |
300 | dgtbl->cur_igvalue = dgtbl->rssi_val_min + 10 - dgtbl->back_val; | 300 | dgtbl->cur_igvalue = dgtbl->rssi_val_min + 10 - dgtbl->back_val; |
301 | 301 | ||
@@ -707,6 +707,77 @@ void rtl8723ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) | |||
707 | rtlpriv->dm.useramask = false; | 707 | rtlpriv->dm.useramask = false; |
708 | } | 708 | } |
709 | 709 | ||
710 | static void rtl8723ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) | ||
711 | { | ||
712 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
713 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
714 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
715 | struct rate_adaptive *p_ra = &(rtlpriv->ra); | ||
716 | u32 low_rssithresh_for_ra, high_rssithresh_for_ra; | ||
717 | struct ieee80211_sta *sta = NULL; | ||
718 | |||
719 | if (is_hal_stop(rtlhal)) { | ||
720 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
721 | " driver is going to unload\n"); | ||
722 | return; | ||
723 | } | ||
724 | |||
725 | if (!rtlpriv->dm.useramask) { | ||
726 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
727 | " driver does not control rate adaptive mask\n"); | ||
728 | return; | ||
729 | } | ||
730 | |||
731 | if (mac->link_state == MAC80211_LINKED && | ||
732 | mac->opmode == NL80211_IFTYPE_STATION) { | ||
733 | switch (p_ra->pre_ratr_state) { | ||
734 | case DM_RATR_STA_HIGH: | ||
735 | high_rssithresh_for_ra = 50; | ||
736 | low_rssithresh_for_ra = 20; | ||
737 | break; | ||
738 | case DM_RATR_STA_MIDDLE: | ||
739 | high_rssithresh_for_ra = 55; | ||
740 | low_rssithresh_for_ra = 20; | ||
741 | break; | ||
742 | case DM_RATR_STA_LOW: | ||
743 | high_rssithresh_for_ra = 50; | ||
744 | low_rssithresh_for_ra = 25; | ||
745 | break; | ||
746 | default: | ||
747 | high_rssithresh_for_ra = 50; | ||
748 | low_rssithresh_for_ra = 20; | ||
749 | break; | ||
750 | } | ||
751 | |||
752 | if (rtlpriv->dm.undec_sm_pwdb > high_rssithresh_for_ra) | ||
753 | p_ra->ratr_state = DM_RATR_STA_HIGH; | ||
754 | else if (rtlpriv->dm.undec_sm_pwdb > low_rssithresh_for_ra) | ||
755 | p_ra->ratr_state = DM_RATR_STA_MIDDLE; | ||
756 | else | ||
757 | p_ra->ratr_state = DM_RATR_STA_LOW; | ||
758 | |||
759 | if (p_ra->pre_ratr_state != p_ra->ratr_state) { | ||
760 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
761 | "RSSI = %ld\n", | ||
762 | rtlpriv->dm.undec_sm_pwdb); | ||
763 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
764 | "RSSI_LEVEL = %d\n", p_ra->ratr_state); | ||
765 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
766 | "PreState = %d, CurState = %d\n", | ||
767 | p_ra->pre_ratr_state, p_ra->ratr_state); | ||
768 | |||
769 | rcu_read_lock(); | ||
770 | sta = rtl_find_sta(hw, mac->bssid); | ||
771 | if (sta) | ||
772 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | ||
773 | p_ra->ratr_state); | ||
774 | rcu_read_unlock(); | ||
775 | |||
776 | p_ra->pre_ratr_state = p_ra->ratr_state; | ||
777 | } | ||
778 | } | ||
779 | } | ||
780 | |||
710 | static void rtl8723ae_dm_init_dynamic_bpowersaving(struct ieee80211_hw *hw) | 781 | static void rtl8723ae_dm_init_dynamic_bpowersaving(struct ieee80211_hw *hw) |
711 | { | 782 | { |
712 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 783 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -853,6 +924,9 @@ void rtl8723ae_dm_watchdog(struct ieee80211_hw *hw) | |||
853 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, | 924 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, |
854 | (u8 *) (&fw_ps_awake)); | 925 | (u8 *) (&fw_ps_awake)); |
855 | 926 | ||
927 | if (ppsc->p2p_ps_info.p2p_ps_mode) | ||
928 | fw_ps_awake = false; | ||
929 | |||
856 | if ((ppsc->rfpwr_state == ERFON) && | 930 | if ((ppsc->rfpwr_state == ERFON) && |
857 | ((!fw_current_inpsmode) && fw_ps_awake) && | 931 | ((!fw_current_inpsmode) && fw_ps_awake) && |
858 | (!ppsc->rfchange_inprogress)) { | 932 | (!ppsc->rfchange_inprogress)) { |
@@ -861,7 +935,7 @@ void rtl8723ae_dm_watchdog(struct ieee80211_hw *hw) | |||
861 | rtl8723ae_dm_false_alarm_counter_statistics(hw); | 935 | rtl8723ae_dm_false_alarm_counter_statistics(hw); |
862 | rtl8723ae_dm_dynamic_bpowersaving(hw); | 936 | rtl8723ae_dm_dynamic_bpowersaving(hw); |
863 | rtl8723ae_dm_dynamic_txpower(hw); | 937 | rtl8723ae_dm_dynamic_txpower(hw); |
864 | /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */ | 938 | rtl8723ae_dm_refresh_rate_adaptive_mask(hw); |
865 | rtl8723ae_dm_bt_coexist(hw); | 939 | rtl8723ae_dm_bt_coexist(hw); |
866 | rtl8723ae_dm_check_edca_turbo(hw); | 940 | rtl8723ae_dm_check_edca_turbo(hw); |
867 | } | 941 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h index 39d246196247..a372b0204456 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h | |||
@@ -55,7 +55,13 @@ | |||
55 | #define DM_DIG_BACKOFF_MIN -4 | 55 | #define DM_DIG_BACKOFF_MIN -4 |
56 | #define DM_DIG_BACKOFF_DEFAULT 10 | 56 | #define DM_DIG_BACKOFF_DEFAULT 10 |
57 | 57 | ||
58 | #define RXPATHSELECTION_SS_TH_LOW 30 | ||
59 | #define RXPATHSELECTION_DIFF_TH 18 | ||
60 | |||
58 | #define DM_RATR_STA_INIT 0 | 61 | #define DM_RATR_STA_INIT 0 |
62 | #define DM_RATR_STA_HIGH 1 | ||
63 | #define DM_RATR_STA_MIDDLE 2 | ||
64 | #define DM_RATR_STA_LOW 3 | ||
59 | 65 | ||
60 | #define TXHIGHPWRLEVEL_NORMAL 0 | 66 | #define TXHIGHPWRLEVEL_NORMAL 0 |
61 | #define TXHIGHPWRLEVEL_LEVEL1 1 | 67 | #define TXHIGHPWRLEVEL_LEVEL1 1 |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c index 35cb8f83eed4..dedfa1ed3e02 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c | |||
@@ -494,7 +494,9 @@ void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) | |||
494 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); | 494 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); |
495 | 495 | ||
496 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); | 496 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); |
497 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1); | 497 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, |
498 | (rtlpriv->mac80211.p2p) ? | ||
499 | ppsc->smart_ps : 1); | ||
498 | SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, | 500 | SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, |
499 | ppsc->reg_max_lps_awakeintvl); | 501 | ppsc->reg_max_lps_awakeintvl); |
500 | 502 | ||
@@ -741,3 +743,96 @@ void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) | |||
741 | 743 | ||
742 | rtl8723ae_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); | 744 | rtl8723ae_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); |
743 | } | 745 | } |
746 | |||
747 | static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, | ||
748 | u8 ctwindow) | ||
749 | { | ||
750 | u8 u1_ctwindow_period[1] = {ctwindow}; | ||
751 | |||
752 | rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); | ||
753 | } | ||
754 | |||
755 | void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | ||
756 | { | ||
757 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
758 | struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); | ||
759 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
760 | struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); | ||
761 | struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; | ||
762 | u8 i; | ||
763 | u16 ctwindow; | ||
764 | u32 start_time, tsf_low; | ||
765 | |||
766 | switch (p2p_ps_state) { | ||
767 | case P2P_PS_DISABLE: | ||
768 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); | ||
769 | memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t)); | ||
770 | break; | ||
771 | case P2P_PS_ENABLE: | ||
772 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); | ||
773 | /* update CTWindow value. */ | ||
774 | if (p2pinfo->ctwindow > 0) { | ||
775 | p2p_ps_offload->ctwindow_en = 1; | ||
776 | ctwindow = p2pinfo->ctwindow; | ||
777 | rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow); | ||
778 | } | ||
779 | |||
780 | /* hw only support 2 set of NoA */ | ||
781 | for (i = 0; i < p2pinfo->noa_num; i++) { | ||
782 | /* To control the register setting for which NOA*/ | ||
783 | rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); | ||
784 | if (i == 0) | ||
785 | p2p_ps_offload->noa0_en = 1; | ||
786 | else | ||
787 | p2p_ps_offload->noa1_en = 1; | ||
788 | |||
789 | /* config P2P NoA Descriptor Register */ | ||
790 | rtl_write_dword(rtlpriv, 0x5E0, | ||
791 | p2pinfo->noa_duration[i]); | ||
792 | rtl_write_dword(rtlpriv, 0x5E4, | ||
793 | p2pinfo->noa_interval[i]); | ||
794 | |||
795 | /*Get Current TSF value */ | ||
796 | tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); | ||
797 | |||
798 | start_time = p2pinfo->noa_start_time[i]; | ||
799 | if (p2pinfo->noa_count_type[i] != 1) { | ||
800 | while (start_time <= (tsf_low+(50*1024))) { | ||
801 | start_time += p2pinfo->noa_interval[i]; | ||
802 | if (p2pinfo->noa_count_type[i] != 255) | ||
803 | p2pinfo->noa_count_type[i]--; | ||
804 | } | ||
805 | } | ||
806 | rtl_write_dword(rtlpriv, 0x5E8, start_time); | ||
807 | rtl_write_dword(rtlpriv, 0x5EC, | ||
808 | p2pinfo->noa_count_type[i]); | ||
809 | } | ||
810 | if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { | ||
811 | /* rst p2p circuit */ | ||
812 | rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); | ||
813 | |||
814 | p2p_ps_offload->offload_en = 1; | ||
815 | |||
816 | if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { | ||
817 | p2p_ps_offload->role = 1; | ||
818 | p2p_ps_offload->allstasleep = 0; | ||
819 | } else { | ||
820 | p2p_ps_offload->role = 0; | ||
821 | } | ||
822 | p2p_ps_offload->discovery = 0; | ||
823 | } | ||
824 | break; | ||
825 | case P2P_PS_SCAN: | ||
826 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); | ||
827 | p2p_ps_offload->discovery = 1; | ||
828 | break; | ||
829 | case P2P_PS_SCAN_DONE: | ||
830 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); | ||
831 | p2p_ps_offload->discovery = 0; | ||
832 | p2pinfo->p2p_ps_state = P2P_PS_ENABLE; | ||
833 | break; | ||
834 | default: | ||
835 | break; | ||
836 | } | ||
837 | rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); | ||
838 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h index 89994e16dc83..ed3b795e6980 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h | |||
@@ -70,8 +70,10 @@ enum rtl8192c_h2c_cmd { | |||
70 | H2C_SETPWRMODE = 1, | 70 | H2C_SETPWRMODE = 1, |
71 | H2C_JOINBSSRPT = 2, | 71 | H2C_JOINBSSRPT = 2, |
72 | H2C_RSVDPAGE = 3, | 72 | H2C_RSVDPAGE = 3, |
73 | H2C_RSSI_REPORT = 5, | 73 | H2C_RSSI_REPORT = 4, |
74 | H2C_RA_MASK = 6, | 74 | H2C_P2P_PS_CTW_CMD = 5, |
75 | H2C_P2P_PS_OFFLOAD = 6, | ||
76 | H2C_RA_MASK = 7, | ||
75 | MAX_H2CCMD | 77 | MAX_H2CCMD |
76 | }; | 78 | }; |
77 | 79 | ||
@@ -97,5 +99,6 @@ void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw); | |||
97 | void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); | 99 | void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); |
98 | void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); | 100 | void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); |
99 | void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); | 101 | void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); |
102 | void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); | ||
100 | 103 | ||
101 | #endif | 104 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c index 9a0c71c2e15e..c333dfd116b8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c | |||
@@ -449,6 +449,9 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
449 | rtl8723ae_set_fw_joinbss_report_cmd(hw, (*(u8 *) val)); | 449 | rtl8723ae_set_fw_joinbss_report_cmd(hw, (*(u8 *) val)); |
450 | 450 | ||
451 | break; } | 451 | break; } |
452 | case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: | ||
453 | rtl8723ae_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); | ||
454 | break; | ||
452 | case HW_VAR_AID:{ | 455 | case HW_VAR_AID:{ |
453 | u16 u2btmp; | 456 | u16 u2btmp; |
454 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); | 457 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); |
@@ -474,6 +477,39 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
474 | if (btype_ibss == true) | 477 | if (btype_ibss == true) |
475 | _rtl8723ae_resume_tx_beacon(hw); | 478 | _rtl8723ae_resume_tx_beacon(hw); |
476 | break; } | 479 | break; } |
480 | case HW_VAR_FW_LPS_ACTION: { | ||
481 | bool enter_fwlps = *((bool *)val); | ||
482 | u8 rpwm_val, fw_pwrmode; | ||
483 | bool fw_current_inps; | ||
484 | |||
485 | if (enter_fwlps) { | ||
486 | rpwm_val = 0x02; /* RF off */ | ||
487 | fw_current_inps = true; | ||
488 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
489 | HW_VAR_FW_PSMODE_STATUS, | ||
490 | (u8 *)(&fw_current_inps)); | ||
491 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
492 | HW_VAR_H2C_FW_PWRMODE, | ||
493 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
494 | |||
495 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
496 | HW_VAR_SET_RPWM, | ||
497 | (u8 *)(&rpwm_val)); | ||
498 | } else { | ||
499 | rpwm_val = 0x0C; /* RF on */ | ||
500 | fw_pwrmode = FW_PS_ACTIVE_MODE; | ||
501 | fw_current_inps = false; | ||
502 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
503 | (u8 *)(&rpwm_val)); | ||
504 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
505 | HW_VAR_H2C_FW_PWRMODE, | ||
506 | (u8 *)(&fw_pwrmode)); | ||
507 | |||
508 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
509 | HW_VAR_FW_PSMODE_STATUS, | ||
510 | (u8 *)(&fw_current_inps)); | ||
511 | } | ||
512 | break; } | ||
477 | default: | 513 | default: |
478 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 514 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
479 | "switch case not processed\n"); | 515 | "switch case not processed\n"); |
@@ -1379,7 +1415,7 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1379 | } | 1415 | } |
1380 | 1416 | ||
1381 | for (i = 0; i < 14; i++) { | 1417 | for (i = 0; i < 14; i++) { |
1382 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1418 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1383 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = " | 1419 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = " |
1384 | "[0x%x / 0x%x / 0x%x]\n", rf_path, i, | 1420 | "[0x%x / 0x%x / 0x%x]\n", rf_path, i, |
1385 | rtlefuse->txpwrlevel_cck[rf_path][i], | 1421 | rtlefuse->txpwrlevel_cck[rf_path][i], |
@@ -1420,10 +1456,10 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1420 | 0xf0) >> 4); | 1456 | 0xf0) >> 4); |
1421 | } | 1457 | } |
1422 | 1458 | ||
1423 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1459 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1424 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", rf_path, i, | 1460 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", rf_path, i, |
1425 | rtlefuse->pwrgroup_ht20[rf_path][i]); | 1461 | rtlefuse->pwrgroup_ht20[rf_path][i]); |
1426 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1462 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1427 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", rf_path, i, | 1463 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", rf_path, i, |
1428 | rtlefuse->pwrgroup_ht40[rf_path][i]); | 1464 | rtlefuse->pwrgroup_ht40[rf_path][i]); |
1429 | } | 1465 | } |
@@ -1463,19 +1499,19 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1463 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; | 1499 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; |
1464 | 1500 | ||
1465 | for (i = 0; i < 14; i++) | 1501 | for (i = 0; i < 14; i++) |
1466 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1502 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1467 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, | 1503 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, |
1468 | rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); | 1504 | rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); |
1469 | for (i = 0; i < 14; i++) | 1505 | for (i = 0; i < 14; i++) |
1470 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1506 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1471 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, | 1507 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, |
1472 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); | 1508 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); |
1473 | for (i = 0; i < 14; i++) | 1509 | for (i = 0; i < 14; i++) |
1474 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1510 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1475 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, | 1511 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, |
1476 | rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); | 1512 | rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); |
1477 | for (i = 0; i < 14; i++) | 1513 | for (i = 0; i < 14; i++) |
1478 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1514 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1479 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, | 1515 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, |
1480 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); | 1516 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); |
1481 | 1517 | ||
@@ -1483,14 +1519,14 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1483 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); | 1519 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); |
1484 | else | 1520 | else |
1485 | rtlefuse->eeprom_regulatory = 0; | 1521 | rtlefuse->eeprom_regulatory = 0; |
1486 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1522 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1487 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | 1523 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); |
1488 | 1524 | ||
1489 | if (!autoload_fail) | 1525 | if (!autoload_fail) |
1490 | rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; | 1526 | rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; |
1491 | else | 1527 | else |
1492 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; | 1528 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; |
1493 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1529 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1494 | "TSSI_A = 0x%x, TSSI_B = 0x%x\n", | 1530 | "TSSI_A = 0x%x, TSSI_B = 0x%x\n", |
1495 | rtlefuse->eeprom_tssi[RF90_PATH_A], | 1531 | rtlefuse->eeprom_tssi[RF90_PATH_A], |
1496 | rtlefuse->eeprom_tssi[RF90_PATH_B]); | 1532 | rtlefuse->eeprom_tssi[RF90_PATH_B]); |
@@ -1505,7 +1541,7 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1505 | rtlefuse->apk_thermalmeterignore = true; | 1541 | rtlefuse->apk_thermalmeterignore = true; |
1506 | 1542 | ||
1507 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; | 1543 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; |
1508 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1544 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1509 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | 1545 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); |
1510 | } | 1546 | } |
1511 | 1547 | ||
@@ -1713,19 +1749,7 @@ static void _rtl8723ae_hal_customized_behavior(struct ieee80211_hw *hw) | |||
1713 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 1749 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
1714 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1750 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1715 | 1751 | ||
1716 | switch (rtlhal->oem_id) { | 1752 | pcipriv->ledctl.led_opendrain = true; |
1717 | case RT_CID_819x_HP: | ||
1718 | pcipriv->ledctl.led_opendrain = true; | ||
1719 | break; | ||
1720 | case RT_CID_819x_Lenovo: | ||
1721 | case RT_CID_DEFAULT: | ||
1722 | case RT_CID_TOSHIBA: | ||
1723 | case RT_CID_CCX: | ||
1724 | case RT_CID_819x_Acer: | ||
1725 | case RT_CID_WHQL: | ||
1726 | default: | ||
1727 | break; | ||
1728 | } | ||
1729 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | 1753 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
1730 | "RT Customized ID: 0x%02X\n", rtlhal->oem_id); | 1754 | "RT Customized ID: 0x%02X\n", rtlhal->oem_id); |
1731 | } | 1755 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c index 9c4e1d811187..061526fe6e2d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c | |||
@@ -54,8 +54,9 @@ void rtl8723ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) | |||
54 | case LED_PIN_GPIO0: | 54 | case LED_PIN_GPIO0: |
55 | break; | 55 | break; |
56 | case LED_PIN_LED0: | 56 | case LED_PIN_LED0: |
57 | ledcfg &= ~BIT(6); | ||
57 | rtl_write_byte(rtlpriv, | 58 | rtl_write_byte(rtlpriv, |
58 | REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6)); | 59 | REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5)); |
59 | break; | 60 | break; |
60 | case LED_PIN_LED1: | 61 | case LED_PIN_LED1: |
61 | rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); | 62 | rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); |
@@ -84,16 +85,21 @@ void rtl8723ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) | |||
84 | break; | 85 | break; |
85 | case LED_PIN_LED0: | 86 | case LED_PIN_LED0: |
86 | ledcfg &= 0xf0; | 87 | ledcfg &= 0xf0; |
87 | if (pcipriv->ledctl.led_opendrain) | 88 | if (pcipriv->ledctl.led_opendrain) { |
89 | ledcfg &= 0x90; | ||
90 | rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3))); | ||
91 | ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); | ||
92 | ledcfg &= 0xFE; | ||
93 | rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg); | ||
94 | } else { | ||
95 | ledcfg &= ~BIT(6); | ||
88 | rtl_write_byte(rtlpriv, REG_LEDCFG2, | 96 | rtl_write_byte(rtlpriv, REG_LEDCFG2, |
89 | (ledcfg | BIT(1) | BIT(5) | BIT(6))); | 97 | (ledcfg | BIT(3) | BIT(5))); |
90 | else | 98 | } |
91 | rtl_write_byte(rtlpriv, REG_LEDCFG2, | ||
92 | (ledcfg | BIT(3) | BIT(5) | BIT(6))); | ||
93 | break; | 99 | break; |
94 | case LED_PIN_LED1: | 100 | case LED_PIN_LED1: |
95 | ledcfg &= 0x0f; | 101 | ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1) & 0x10; |
96 | rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); | 102 | rtl_write_byte(rtlpriv, REG_LEDCFG1, (ledcfg | BIT(3))); |
97 | break; | 103 | break; |
98 | default: | 104 | default: |
99 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 105 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c index bb7cc90bafb2..e4c4cdc3eb67 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c | |||
@@ -305,7 +305,7 @@ static struct rtl_hal_cfg rtl8723ae_hal_cfg = { | |||
305 | 305 | ||
306 | .maps[RTL_IMR_TXFOVW] = PHIMR_TXFOVW, | 306 | .maps[RTL_IMR_TXFOVW] = PHIMR_TXFOVW, |
307 | .maps[RTL_IMR_PSTIMEOUT] = PHIMR_PSTIMEOUT, | 307 | .maps[RTL_IMR_PSTIMEOUT] = PHIMR_PSTIMEOUT, |
308 | .maps[RTL_IMR_BcnInt] = PHIMR_BCNDMAINT0, | 308 | .maps[RTL_IMR_BCNINT] = PHIMR_BCNDMAINT0, |
309 | .maps[RTL_IMR_RXFOVW] = PHIMR_RXFOVW, | 309 | .maps[RTL_IMR_RXFOVW] = PHIMR_RXFOVW, |
310 | .maps[RTL_IMR_RDU] = PHIMR_RDU, | 310 | .maps[RTL_IMR_RDU] = PHIMR_RDU, |
311 | .maps[RTL_IMR_ATIMEND] = PHIMR_ATIMEND_E, | 311 | .maps[RTL_IMR_ATIMEND] = PHIMR_ATIMEND_E, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c index 601261d67e84..c72758d8f4ed 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c | |||
@@ -307,9 +307,6 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw, | |||
307 | rx_status->freq = hw->conf.chandef.chan->center_freq; | 307 | rx_status->freq = hw->conf.chandef.chan->center_freq; |
308 | rx_status->band = hw->conf.chandef.chan->band; | 308 | rx_status->band = hw->conf.chandef.chan->band; |
309 | 309 | ||
310 | hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size | ||
311 | + status->rx_bufshift); | ||
312 | |||
313 | if (status->crc) | 310 | if (status->crc) |
314 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | 311 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
315 | 312 | ||
@@ -330,6 +327,13 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw, | |||
330 | * to decrypt it | 327 | * to decrypt it |
331 | */ | 328 | */ |
332 | if (status->decrypted) { | 329 | if (status->decrypted) { |
330 | hdr = (struct ieee80211_hdr *)(skb->data + | ||
331 | status->rx_drvinfo_size + status->rx_bufshift); | ||
332 | |||
333 | if (!hdr) { | ||
334 | /* during testing, hdr could be NULL here */ | ||
335 | return false; | ||
336 | } | ||
333 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | 337 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && |
334 | (ieee80211_has_protected(hdr->frame_control))) | 338 | (ieee80211_has_protected(hdr->frame_control))) |
335 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | 339 | rx_status->flag &= ~RX_FLAG_DECRYPTED; |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 156b52732f3d..83915dcd0e58 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 | ||
@@ -309,6 +308,8 @@ static int _rtl_usb_init_tx(struct ieee80211_hw *hw) | |||
309 | return 0; | 308 | return 0; |
310 | } | 309 | } |
311 | 310 | ||
311 | static void _rtl_rx_work(unsigned long param); | ||
312 | |||
312 | static int _rtl_usb_init_rx(struct ieee80211_hw *hw) | 313 | static int _rtl_usb_init_rx(struct ieee80211_hw *hw) |
313 | { | 314 | { |
314 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 315 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -325,6 +326,12 @@ static int _rtl_usb_init_rx(struct ieee80211_hw *hw) | |||
325 | pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n", | 326 | pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n", |
326 | rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep); | 327 | rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep); |
327 | init_usb_anchor(&rtlusb->rx_submitted); | 328 | init_usb_anchor(&rtlusb->rx_submitted); |
329 | init_usb_anchor(&rtlusb->rx_cleanup_urbs); | ||
330 | |||
331 | skb_queue_head_init(&rtlusb->rx_queue); | ||
332 | rtlusb->rx_work_tasklet.func = _rtl_rx_work; | ||
333 | rtlusb->rx_work_tasklet.data = (unsigned long)rtlusb; | ||
334 | |||
328 | return 0; | 335 | return 0; |
329 | } | 336 | } |
330 | 337 | ||
@@ -406,40 +413,30 @@ static void rtl_usb_init_sw(struct ieee80211_hw *hw) | |||
406 | rtlusb->disableHWSM = true; | 413 | rtlusb->disableHWSM = true; |
407 | } | 414 | } |
408 | 415 | ||
409 | #define __RADIO_TAP_SIZE_RSV 32 | ||
410 | |||
411 | static void _rtl_rx_completed(struct urb *urb); | 416 | static void _rtl_rx_completed(struct urb *urb); |
412 | 417 | ||
413 | static struct sk_buff *_rtl_prep_rx_urb(struct ieee80211_hw *hw, | 418 | static int _rtl_prep_rx_urb(struct ieee80211_hw *hw, struct rtl_usb *rtlusb, |
414 | struct rtl_usb *rtlusb, | 419 | struct urb *urb, gfp_t gfp_mask) |
415 | struct urb *urb, | ||
416 | gfp_t gfp_mask) | ||
417 | { | 420 | { |
418 | struct sk_buff *skb; | ||
419 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 421 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
422 | void *buf; | ||
420 | 423 | ||
421 | skb = __dev_alloc_skb((rtlusb->rx_max_size + __RADIO_TAP_SIZE_RSV), | 424 | buf = usb_alloc_coherent(rtlusb->udev, rtlusb->rx_max_size, gfp_mask, |
422 | gfp_mask); | 425 | &urb->transfer_dma); |
423 | if (!skb) { | 426 | if (!buf) { |
424 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | 427 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
425 | "Failed to __dev_alloc_skb!!\n"); | 428 | "Failed to usb_alloc_coherent!!\n"); |
426 | return ERR_PTR(-ENOMEM); | 429 | return -ENOMEM; |
427 | } | 430 | } |
428 | 431 | ||
429 | /* reserve some space for mac80211's radiotap */ | ||
430 | skb_reserve(skb, __RADIO_TAP_SIZE_RSV); | ||
431 | usb_fill_bulk_urb(urb, rtlusb->udev, | 432 | usb_fill_bulk_urb(urb, rtlusb->udev, |
432 | usb_rcvbulkpipe(rtlusb->udev, rtlusb->in_ep), | 433 | usb_rcvbulkpipe(rtlusb->udev, rtlusb->in_ep), |
433 | skb->data, min(skb_tailroom(skb), | 434 | buf, rtlusb->rx_max_size, _rtl_rx_completed, rtlusb); |
434 | (int)rtlusb->rx_max_size), | 435 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
435 | _rtl_rx_completed, skb); | ||
436 | 436 | ||
437 | _rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep); | 437 | return 0; |
438 | return skb; | ||
439 | } | 438 | } |
440 | 439 | ||
441 | #undef __RADIO_TAP_SIZE_RSV | ||
442 | |||
443 | static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, | 440 | static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, |
444 | struct sk_buff *skb) | 441 | struct sk_buff *skb) |
445 | { | 442 | { |
@@ -523,22 +520,11 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, | |||
523 | if (unicast) | 520 | if (unicast) |
524 | rtlpriv->link_info.num_rx_inperiod++; | 521 | rtlpriv->link_info.num_rx_inperiod++; |
525 | } | 522 | } |
526 | if (likely(rtl_action_proc(hw, skb, false))) { | 523 | |
527 | struct sk_buff *uskb = NULL; | 524 | if (likely(rtl_action_proc(hw, skb, false))) |
528 | u8 *pdata; | 525 | ieee80211_rx(hw, skb); |
529 | 526 | else | |
530 | uskb = dev_alloc_skb(skb->len + 128); | ||
531 | if (uskb) { /* drop packet on allocation failure */ | ||
532 | memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, | ||
533 | sizeof(rx_status)); | ||
534 | pdata = (u8 *)skb_put(uskb, skb->len); | ||
535 | memcpy(pdata, skb->data, skb->len); | ||
536 | ieee80211_rx_irqsafe(hw, uskb); | ||
537 | } | ||
538 | dev_kfree_skb_any(skb); | ||
539 | } else { | ||
540 | dev_kfree_skb_any(skb); | 527 | dev_kfree_skb_any(skb); |
541 | } | ||
542 | } | 528 | } |
543 | } | 529 | } |
544 | 530 | ||
@@ -555,15 +541,70 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
555 | while (!skb_queue_empty(&rx_queue)) { | 541 | while (!skb_queue_empty(&rx_queue)) { |
556 | _skb = skb_dequeue(&rx_queue); | 542 | _skb = skb_dequeue(&rx_queue); |
557 | _rtl_usb_rx_process_agg(hw, _skb); | 543 | _rtl_usb_rx_process_agg(hw, _skb); |
558 | ieee80211_rx_irqsafe(hw, _skb); | 544 | ieee80211_rx(hw, _skb); |
559 | } | 545 | } |
560 | } | 546 | } |
561 | 547 | ||
548 | #define __RX_SKB_MAX_QUEUED 32 | ||
549 | |||
550 | static void _rtl_rx_work(unsigned long param) | ||
551 | { | ||
552 | struct rtl_usb *rtlusb = (struct rtl_usb *)param; | ||
553 | struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); | ||
554 | struct sk_buff *skb; | ||
555 | |||
556 | while ((skb = skb_dequeue(&rtlusb->rx_queue))) { | ||
557 | if (unlikely(IS_USB_STOP(rtlusb))) { | ||
558 | dev_kfree_skb_any(skb); | ||
559 | continue; | ||
560 | } | ||
561 | |||
562 | if (likely(!rtlusb->usb_rx_segregate_hdl)) { | ||
563 | _rtl_usb_rx_process_noagg(hw, skb); | ||
564 | } else { | ||
565 | /* TO DO */ | ||
566 | _rtl_rx_pre_process(hw, skb); | ||
567 | pr_err("rx agg not supported\n"); | ||
568 | } | ||
569 | } | ||
570 | } | ||
571 | |||
572 | static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr, | ||
573 | unsigned int len) | ||
574 | { | ||
575 | unsigned int padding = 0; | ||
576 | |||
577 | /* make function no-op when possible */ | ||
578 | if (NET_IP_ALIGN == 0 || len < sizeof(*hdr)) | ||
579 | return 0; | ||
580 | |||
581 | /* alignment calculation as in lbtf_rx() / carl9170_rx_copy_data() */ | ||
582 | /* TODO: deduplicate common code, define helper function instead? */ | ||
583 | |||
584 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
585 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
586 | |||
587 | padding ^= NET_IP_ALIGN; | ||
588 | |||
589 | /* Input might be invalid, avoid accessing memory outside | ||
590 | * the buffer. | ||
591 | */ | ||
592 | if ((unsigned long)qc - (unsigned long)hdr < len && | ||
593 | *qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) | ||
594 | padding ^= NET_IP_ALIGN; | ||
595 | } | ||
596 | |||
597 | if (ieee80211_has_a4(hdr->frame_control)) | ||
598 | padding ^= NET_IP_ALIGN; | ||
599 | |||
600 | return padding; | ||
601 | } | ||
602 | |||
603 | #define __RADIO_TAP_SIZE_RSV 32 | ||
604 | |||
562 | static void _rtl_rx_completed(struct urb *_urb) | 605 | static void _rtl_rx_completed(struct urb *_urb) |
563 | { | 606 | { |
564 | struct sk_buff *skb = (struct sk_buff *)_urb->context; | 607 | struct rtl_usb *rtlusb = (struct rtl_usb *)_urb->context; |
565 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
566 | struct rtl_usb *rtlusb = (struct rtl_usb *)info->rate_driver_data[0]; | ||
567 | struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); | 608 | struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); |
568 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 609 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
569 | int err = 0; | 610 | int err = 0; |
@@ -572,28 +613,50 @@ static void _rtl_rx_completed(struct urb *_urb) | |||
572 | goto free; | 613 | goto free; |
573 | 614 | ||
574 | if (likely(0 == _urb->status)) { | 615 | if (likely(0 == _urb->status)) { |
575 | /* If this code were moved to work queue, would CPU | 616 | unsigned int padding; |
576 | * utilization be improved? NOTE: We shall allocate another skb | 617 | struct sk_buff *skb; |
577 | * and reuse the original one. | 618 | unsigned int qlen; |
578 | */ | 619 | unsigned int size = _urb->actual_length; |
579 | skb_put(skb, _urb->actual_length); | 620 | struct ieee80211_hdr *hdr; |
580 | 621 | ||
581 | if (likely(!rtlusb->usb_rx_segregate_hdl)) { | 622 | if (size < RTL_RX_DESC_SIZE + sizeof(struct ieee80211_hdr)) { |
582 | struct sk_buff *_skb; | 623 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
583 | _rtl_usb_rx_process_noagg(hw, skb); | 624 | "Too short packet from bulk IN! (len: %d)\n", |
584 | _skb = _rtl_prep_rx_urb(hw, rtlusb, _urb, GFP_ATOMIC); | 625 | size); |
585 | if (IS_ERR(_skb)) { | 626 | goto resubmit; |
586 | err = PTR_ERR(_skb); | 627 | } |
587 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | 628 | |
588 | "Can't allocate skb for bulk IN!\n"); | 629 | qlen = skb_queue_len(&rtlusb->rx_queue); |
589 | return; | 630 | if (qlen >= __RX_SKB_MAX_QUEUED) { |
590 | } | 631 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
591 | skb = _skb; | 632 | "Pending RX skbuff queue full! (qlen: %d)\n", |
592 | } else{ | 633 | qlen); |
593 | /* TO DO */ | 634 | goto resubmit; |
594 | _rtl_rx_pre_process(hw, skb); | ||
595 | pr_err("rx agg not supported\n"); | ||
596 | } | 635 | } |
636 | |||
637 | hdr = (void *)(_urb->transfer_buffer + RTL_RX_DESC_SIZE); | ||
638 | padding = _rtl_rx_get_padding(hdr, size - RTL_RX_DESC_SIZE); | ||
639 | |||
640 | skb = dev_alloc_skb(size + __RADIO_TAP_SIZE_RSV + padding); | ||
641 | if (!skb) { | ||
642 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | ||
643 | "Can't allocate skb for bulk IN!\n"); | ||
644 | goto resubmit; | ||
645 | } | ||
646 | |||
647 | _rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep); | ||
648 | |||
649 | /* Make sure the payload data is 4 byte aligned. */ | ||
650 | skb_reserve(skb, padding); | ||
651 | |||
652 | /* reserve some space for mac80211's radiotap */ | ||
653 | skb_reserve(skb, __RADIO_TAP_SIZE_RSV); | ||
654 | |||
655 | memcpy(skb_put(skb, size), _urb->transfer_buffer, size); | ||
656 | |||
657 | skb_queue_tail(&rtlusb->rx_queue, skb); | ||
658 | tasklet_schedule(&rtlusb->rx_work_tasklet); | ||
659 | |||
597 | goto resubmit; | 660 | goto resubmit; |
598 | } | 661 | } |
599 | 662 | ||
@@ -609,9 +672,6 @@ static void _rtl_rx_completed(struct urb *_urb) | |||
609 | } | 672 | } |
610 | 673 | ||
611 | resubmit: | 674 | resubmit: |
612 | skb_reset_tail_pointer(skb); | ||
613 | skb_trim(skb, 0); | ||
614 | |||
615 | usb_anchor_urb(_urb, &rtlusb->rx_submitted); | 675 | usb_anchor_urb(_urb, &rtlusb->rx_submitted); |
616 | err = usb_submit_urb(_urb, GFP_ATOMIC); | 676 | err = usb_submit_urb(_urb, GFP_ATOMIC); |
617 | if (unlikely(err)) { | 677 | if (unlikely(err)) { |
@@ -621,13 +681,34 @@ resubmit: | |||
621 | return; | 681 | return; |
622 | 682 | ||
623 | free: | 683 | free: |
624 | dev_kfree_skb_irq(skb); | 684 | /* On some architectures, usb_free_coherent must not be called from |
685 | * hardirq context. Queue urb to cleanup list. | ||
686 | */ | ||
687 | usb_anchor_urb(_urb, &rtlusb->rx_cleanup_urbs); | ||
688 | } | ||
689 | |||
690 | #undef __RADIO_TAP_SIZE_RSV | ||
691 | |||
692 | static void _rtl_usb_cleanup_rx(struct ieee80211_hw *hw) | ||
693 | { | ||
694 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); | ||
695 | struct urb *urb; | ||
696 | |||
697 | usb_kill_anchored_urbs(&rtlusb->rx_submitted); | ||
698 | |||
699 | tasklet_kill(&rtlusb->rx_work_tasklet); | ||
700 | skb_queue_purge(&rtlusb->rx_queue); | ||
701 | |||
702 | while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) { | ||
703 | usb_free_coherent(urb->dev, urb->transfer_buffer_length, | ||
704 | urb->transfer_buffer, urb->transfer_dma); | ||
705 | usb_free_urb(urb); | ||
706 | } | ||
625 | } | 707 | } |
626 | 708 | ||
627 | static int _rtl_usb_receive(struct ieee80211_hw *hw) | 709 | static int _rtl_usb_receive(struct ieee80211_hw *hw) |
628 | { | 710 | { |
629 | struct urb *urb; | 711 | struct urb *urb; |
630 | struct sk_buff *skb; | ||
631 | int err; | 712 | int err; |
632 | int i; | 713 | int i; |
633 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 714 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -646,11 +727,10 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw) | |||
646 | goto err_out; | 727 | goto err_out; |
647 | } | 728 | } |
648 | 729 | ||
649 | skb = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL); | 730 | err = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL); |
650 | if (IS_ERR(skb)) { | 731 | if (err < 0) { |
651 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | 732 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
652 | "Failed to prep_rx_urb!!\n"); | 733 | "Failed to prep_rx_urb!!\n"); |
653 | err = PTR_ERR(skb); | ||
654 | usb_free_urb(urb); | 734 | usb_free_urb(urb); |
655 | goto err_out; | 735 | goto err_out; |
656 | } | 736 | } |
@@ -665,6 +745,7 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw) | |||
665 | 745 | ||
666 | err_out: | 746 | err_out: |
667 | usb_kill_anchored_urbs(&rtlusb->rx_submitted); | 747 | usb_kill_anchored_urbs(&rtlusb->rx_submitted); |
748 | _rtl_usb_cleanup_rx(hw); | ||
668 | return err; | 749 | return err; |
669 | } | 750 | } |
670 | 751 | ||
@@ -706,7 +787,7 @@ static void rtl_usb_cleanup(struct ieee80211_hw *hw) | |||
706 | SET_USB_STOP(rtlusb); | 787 | SET_USB_STOP(rtlusb); |
707 | 788 | ||
708 | /* clean up rx stuff. */ | 789 | /* clean up rx stuff. */ |
709 | usb_kill_anchored_urbs(&rtlusb->rx_submitted); | 790 | _rtl_usb_cleanup_rx(hw); |
710 | 791 | ||
711 | /* clean up tx stuff */ | 792 | /* clean up tx stuff */ |
712 | for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) { | 793 | for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) { |
@@ -851,6 +932,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
851 | if (unlikely(!_urb)) { | 932 | if (unlikely(!_urb)) { |
852 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 933 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
853 | "Can't allocate urb. Drop skb!\n"); | 934 | "Can't allocate urb. Drop skb!\n"); |
935 | kfree_skb(skb); | ||
854 | return; | 936 | return; |
855 | } | 937 | } |
856 | _rtl_submit_tx_urb(hw, _urb); | 938 | _rtl_submit_tx_urb(hw, _urb); |
diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h index fb986f98d1df..685273ca9561 100644 --- a/drivers/net/wireless/rtlwifi/usb.h +++ b/drivers/net/wireless/rtlwifi/usb.h | |||
@@ -136,11 +136,14 @@ struct rtl_usb { | |||
136 | void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *); | 136 | void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *); |
137 | 137 | ||
138 | /* Rx */ | 138 | /* Rx */ |
139 | u8 in_ep_nums ; | 139 | u8 in_ep_nums; |
140 | u32 in_ep; /* Bulk IN endpoint number */ | 140 | u32 in_ep; /* Bulk IN endpoint number */ |
141 | u32 rx_max_size; /* Bulk IN max buffer size */ | 141 | u32 rx_max_size; /* Bulk IN max buffer size */ |
142 | u32 rx_urb_num; /* How many Bulk INs are submitted to host. */ | 142 | u32 rx_urb_num; /* How many Bulk INs are submitted to host. */ |
143 | struct usb_anchor rx_submitted; | 143 | struct usb_anchor rx_submitted; |
144 | struct usb_anchor rx_cleanup_urbs; | ||
145 | struct tasklet_struct rx_work_tasklet; | ||
146 | struct sk_buff_head rx_queue; | ||
144 | void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *, | 147 | void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *, |
145 | struct sk_buff_head *); | 148 | struct sk_buff_head *); |
146 | void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *); | 149 | void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *); |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index c3eff32acf6c..44328baa6389 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -99,11 +99,36 @@ | |||
99 | #define CHANNEL_GROUP_MAX_5G 9 | 99 | #define CHANNEL_GROUP_MAX_5G 9 |
100 | #define CHANNEL_MAX_NUMBER_2G 14 | 100 | #define CHANNEL_MAX_NUMBER_2G 14 |
101 | #define AVG_THERMAL_NUM 8 | 101 | #define AVG_THERMAL_NUM 8 |
102 | #define AVG_THERMAL_NUM_88E 4 | ||
102 | #define MAX_TID_COUNT 9 | 103 | #define MAX_TID_COUNT 9 |
103 | 104 | ||
104 | /* for early mode */ | 105 | /* for early mode */ |
105 | #define FCS_LEN 4 | 106 | #define FCS_LEN 4 |
106 | #define EM_HDR_LEN 8 | 107 | #define EM_HDR_LEN 8 |
108 | |||
109 | #define MAX_TX_COUNT 4 | ||
110 | #define MAX_RF_PATH 4 | ||
111 | #define MAX_CHNL_GROUP_24G 6 | ||
112 | #define MAX_CHNL_GROUP_5G 14 | ||
113 | |||
114 | struct txpower_info_2g { | ||
115 | u8 index_cck_base[MAX_RF_PATH][MAX_CHNL_GROUP_24G]; | ||
116 | u8 index_bw40_base[MAX_RF_PATH][MAX_CHNL_GROUP_24G]; | ||
117 | /*If only one tx, only BW20 and OFDM are used.*/ | ||
118 | u8 cck_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
119 | u8 ofdm_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
120 | u8 bw20_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
121 | u8 bw40_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
122 | }; | ||
123 | |||
124 | struct txpower_info_5g { | ||
125 | u8 index_bw40_base[MAX_RF_PATH][MAX_CHNL_GROUP_5G]; | ||
126 | /*If only one tx, only BW20, OFDM, BW80 and BW160 are used.*/ | ||
127 | u8 ofdm_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
128 | u8 bw20_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
129 | u8 bw40_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
130 | }; | ||
131 | |||
107 | enum intf_type { | 132 | enum intf_type { |
108 | INTF_PCI = 0, | 133 | INTF_PCI = 0, |
109 | INTF_USB = 1, | 134 | INTF_USB = 1, |
@@ -137,6 +162,7 @@ enum hardware_type { | |||
137 | HARDWARE_TYPE_RTL8192DU, | 162 | HARDWARE_TYPE_RTL8192DU, |
138 | HARDWARE_TYPE_RTL8723AE, | 163 | HARDWARE_TYPE_RTL8723AE, |
139 | HARDWARE_TYPE_RTL8723U, | 164 | HARDWARE_TYPE_RTL8723U, |
165 | HARDWARE_TYPE_RTL8188EE, | ||
140 | 166 | ||
141 | /* keep it last */ | 167 | /* keep it last */ |
142 | HARDWARE_TYPE_NUM | 168 | HARDWARE_TYPE_NUM |
@@ -263,7 +289,7 @@ enum hw_variables { | |||
263 | HW_VAR_RATR_0, | 289 | HW_VAR_RATR_0, |
264 | HW_VAR_RRSR, | 290 | HW_VAR_RRSR, |
265 | HW_VAR_CPU_RST, | 291 | HW_VAR_CPU_RST, |
266 | HW_VAR_CECHK_BSSID, | 292 | HW_VAR_CHECK_BSSID, |
267 | HW_VAR_LBK_MODE, | 293 | HW_VAR_LBK_MODE, |
268 | HW_VAR_AES_11N_FIX, | 294 | HW_VAR_AES_11N_FIX, |
269 | HW_VAR_USB_RX_AGGR, | 295 | HW_VAR_USB_RX_AGGR, |
@@ -278,7 +304,10 @@ enum hw_variables { | |||
278 | HW_VAR_SET_RPWM, | 304 | HW_VAR_SET_RPWM, |
279 | HW_VAR_H2C_FW_PWRMODE, | 305 | HW_VAR_H2C_FW_PWRMODE, |
280 | HW_VAR_H2C_FW_JOINBSSRPT, | 306 | HW_VAR_H2C_FW_JOINBSSRPT, |
307 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
281 | HW_VAR_FW_PSMODE_STATUS, | 308 | HW_VAR_FW_PSMODE_STATUS, |
309 | HW_VAR_RESUME_CLK_ON, | ||
310 | HW_VAR_FW_LPS_ACTION, | ||
282 | HW_VAR_1X1_RECV_COMBINE, | 311 | HW_VAR_1X1_RECV_COMBINE, |
283 | HW_VAR_STOP_SEND_BEACON, | 312 | HW_VAR_STOP_SEND_BEACON, |
284 | HW_VAR_TSF_TIMER, | 313 | HW_VAR_TSF_TIMER, |
@@ -305,6 +334,7 @@ enum hw_variables { | |||
305 | HW_VAR_INT_AC, | 334 | HW_VAR_INT_AC, |
306 | HW_VAR_RF_TIMING, | 335 | HW_VAR_RF_TIMING, |
307 | 336 | ||
337 | HAL_DEF_WOWLAN, | ||
308 | HW_VAR_MRC, | 338 | HW_VAR_MRC, |
309 | 339 | ||
310 | HW_VAR_MGT_FILTER, | 340 | HW_VAR_MGT_FILTER, |
@@ -461,6 +491,7 @@ enum rtl_var_map { | |||
461 | EFUSE_MAX_SECTION_MAP, | 491 | EFUSE_MAX_SECTION_MAP, |
462 | EFUSE_REAL_CONTENT_SIZE, | 492 | EFUSE_REAL_CONTENT_SIZE, |
463 | EFUSE_OOB_PROTECT_BYTES_LEN, | 493 | EFUSE_OOB_PROTECT_BYTES_LEN, |
494 | EFUSE_ACCESS, | ||
464 | 495 | ||
465 | /*CAM map */ | 496 | /*CAM map */ |
466 | RWCAM, | 497 | RWCAM, |
@@ -493,7 +524,7 @@ enum rtl_var_map { | |||
493 | RTL_IMR_TIMEOUT1, /*Timeout interrupt 1 */ | 524 | RTL_IMR_TIMEOUT1, /*Timeout interrupt 1 */ |
494 | RTL_IMR_TXFOVW, /*Transmit FIFO Overflow */ | 525 | RTL_IMR_TXFOVW, /*Transmit FIFO Overflow */ |
495 | RTL_IMR_PSTIMEOUT, /*Power save time out interrupt */ | 526 | RTL_IMR_PSTIMEOUT, /*Power save time out interrupt */ |
496 | RTL_IMR_BcnInt, /*Beacon DMA Interrupt 0 */ | 527 | RTL_IMR_BCNINT, /*Beacon DMA Interrupt 0 */ |
497 | RTL_IMR_RXFOVW, /*Receive FIFO Overflow */ | 528 | RTL_IMR_RXFOVW, /*Receive FIFO Overflow */ |
498 | RTL_IMR_RDU, /*Receive Descriptor Unavailable */ | 529 | RTL_IMR_RDU, /*Receive Descriptor Unavailable */ |
499 | RTL_IMR_ATIMEND, /*For 92C,ATIM Window End Interrupt */ | 530 | RTL_IMR_ATIMEND, /*For 92C,ATIM Window End Interrupt */ |
@@ -508,7 +539,7 @@ enum rtl_var_map { | |||
508 | RTL_IMR_VIDOK, /*AC_VI DMA OK Interrupt */ | 539 | RTL_IMR_VIDOK, /*AC_VI DMA OK Interrupt */ |
509 | RTL_IMR_VODOK, /*AC_VO DMA Interrupt */ | 540 | RTL_IMR_VODOK, /*AC_VO DMA Interrupt */ |
510 | RTL_IMR_ROK, /*Receive DMA OK Interrupt */ | 541 | RTL_IMR_ROK, /*Receive DMA OK Interrupt */ |
511 | RTL_IBSS_INT_MASKS, /*(RTL_IMR_BcnInt | RTL_IMR_TBDOK | | 542 | RTL_IBSS_INT_MASKS, /*(RTL_IMR_BCNINT | RTL_IMR_TBDOK | |
512 | * RTL_IMR_TBDER) */ | 543 | * RTL_IMR_TBDER) */ |
513 | RTL_IMR_C2HCMD, /*fw interrupt*/ | 544 | RTL_IMR_C2HCMD, /*fw interrupt*/ |
514 | 545 | ||
@@ -742,6 +773,11 @@ struct false_alarm_statistics { | |||
742 | u32 cnt_ofdm_fail; | 773 | u32 cnt_ofdm_fail; |
743 | u32 cnt_cck_fail; | 774 | u32 cnt_cck_fail; |
744 | u32 cnt_all; | 775 | u32 cnt_all; |
776 | u32 cnt_ofdm_cca; | ||
777 | u32 cnt_cck_cca; | ||
778 | u32 cnt_cca_all; | ||
779 | u32 cnt_bw_usc; | ||
780 | u32 cnt_bw_lsc; | ||
745 | }; | 781 | }; |
746 | 782 | ||
747 | struct init_gain { | 783 | struct init_gain { |
@@ -826,8 +862,67 @@ struct rtl_rfkill { | |||
826 | bool rfkill_state; /*0 is off, 1 is on */ | 862 | bool rfkill_state; /*0 is off, 1 is on */ |
827 | }; | 863 | }; |
828 | 864 | ||
865 | /*for P2P PS**/ | ||
866 | #define P2P_MAX_NOA_NUM 2 | ||
867 | |||
868 | enum p2p_role { | ||
869 | P2P_ROLE_DISABLE = 0, | ||
870 | P2P_ROLE_DEVICE = 1, | ||
871 | P2P_ROLE_CLIENT = 2, | ||
872 | P2P_ROLE_GO = 3 | ||
873 | }; | ||
874 | |||
875 | enum p2p_ps_state { | ||
876 | P2P_PS_DISABLE = 0, | ||
877 | P2P_PS_ENABLE = 1, | ||
878 | P2P_PS_SCAN = 2, | ||
879 | P2P_PS_SCAN_DONE = 3, | ||
880 | P2P_PS_ALLSTASLEEP = 4, /* for P2P GO */ | ||
881 | }; | ||
882 | |||
883 | enum p2p_ps_mode { | ||
884 | P2P_PS_NONE = 0, | ||
885 | P2P_PS_CTWINDOW = 1, | ||
886 | P2P_PS_NOA = 2, | ||
887 | P2P_PS_MIX = 3, /* CTWindow and NoA */ | ||
888 | }; | ||
889 | |||
890 | struct rtl_p2p_ps_info { | ||
891 | enum p2p_ps_mode p2p_ps_mode; /* indicate p2p ps mode */ | ||
892 | enum p2p_ps_state p2p_ps_state; /* indicate p2p ps state */ | ||
893 | u8 noa_index; /* Identifies instance of Notice of Absence timing. */ | ||
894 | /* Client traffic window. A period of time in TU after TBTT. */ | ||
895 | u8 ctwindow; | ||
896 | u8 opp_ps; /* opportunistic power save. */ | ||
897 | u8 noa_num; /* number of NoA descriptor in P2P IE. */ | ||
898 | /* Count for owner, Type of client. */ | ||
899 | u8 noa_count_type[P2P_MAX_NOA_NUM]; | ||
900 | /* Max duration for owner, preferred or min acceptable duration | ||
901 | * for client. | ||
902 | */ | ||
903 | u32 noa_duration[P2P_MAX_NOA_NUM]; | ||
904 | /* Length of interval for owner, preferred or max acceptable intervali | ||
905 | * of client. | ||
906 | */ | ||
907 | u32 noa_interval[P2P_MAX_NOA_NUM]; | ||
908 | /* schedule in terms of the lower 4 bytes of the TSF timer. */ | ||
909 | u32 noa_start_time[P2P_MAX_NOA_NUM]; | ||
910 | }; | ||
911 | |||
912 | struct p2p_ps_offload_t { | ||
913 | u8 offload_en:1; | ||
914 | u8 role:1; /* 1: Owner, 0: Client */ | ||
915 | u8 ctwindow_en:1; | ||
916 | u8 noa0_en:1; | ||
917 | u8 noa1_en:1; | ||
918 | u8 allstasleep:1; | ||
919 | u8 discovery:1; | ||
920 | u8 reserved:1; | ||
921 | }; | ||
922 | |||
829 | #define IQK_MATRIX_REG_NUM 8 | 923 | #define IQK_MATRIX_REG_NUM 8 |
830 | #define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) | 924 | #define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) |
925 | |||
831 | struct iqk_matrix_regs { | 926 | struct iqk_matrix_regs { |
832 | bool iqk_done; | 927 | bool iqk_done; |
833 | long value[1][IQK_MATRIX_REG_NUM]; | 928 | long value[1][IQK_MATRIX_REG_NUM]; |
@@ -889,7 +984,7 @@ struct rtl_phy { | |||
889 | 984 | ||
890 | /* Dual mac */ | 985 | /* Dual mac */ |
891 | bool need_iqk; | 986 | bool need_iqk; |
892 | struct iqk_matrix_regs iqk_matrix_regsetting[IQK_MATRIX_SETTINGS_NUM]; | 987 | struct iqk_matrix_regs iqk_matrix[IQK_MATRIX_SETTINGS_NUM]; |
893 | 988 | ||
894 | bool rfpi_enable; | 989 | bool rfpi_enable; |
895 | 990 | ||
@@ -902,6 +997,8 @@ struct rtl_phy { | |||
902 | /* the current Tx power level */ | 997 | /* the current Tx power level */ |
903 | u8 cur_cck_txpwridx; | 998 | u8 cur_cck_txpwridx; |
904 | u8 cur_ofdm24g_txpwridx; | 999 | u8 cur_ofdm24g_txpwridx; |
1000 | u8 cur_bw20_txpwridx; | ||
1001 | u8 cur_bw40_txpwridx; | ||
905 | 1002 | ||
906 | u32 rfreg_chnlval[2]; | 1003 | u32 rfreg_chnlval[2]; |
907 | bool apk_done; | 1004 | bool apk_done; |
@@ -940,20 +1037,21 @@ struct rtl_ht_agg { | |||
940 | u8 rx_agg_state; | 1037 | u8 rx_agg_state; |
941 | }; | 1038 | }; |
942 | 1039 | ||
1040 | struct rssi_sta { | ||
1041 | long undec_sm_pwdb; | ||
1042 | }; | ||
1043 | |||
943 | struct rtl_tid_data { | 1044 | struct rtl_tid_data { |
944 | u16 seq_number; | 1045 | u16 seq_number; |
945 | struct rtl_ht_agg agg; | 1046 | struct rtl_ht_agg agg; |
946 | }; | 1047 | }; |
947 | 1048 | ||
948 | struct rssi_sta { | ||
949 | long undec_sm_pwdb; | ||
950 | }; | ||
951 | |||
952 | struct rtl_sta_info { | 1049 | struct rtl_sta_info { |
953 | struct list_head list; | 1050 | struct list_head list; |
954 | u8 ratr_index; | 1051 | u8 ratr_index; |
955 | u8 wireless_mode; | 1052 | u8 wireless_mode; |
956 | u8 mimo_ps; | 1053 | u8 mimo_ps; |
1054 | u8 mac_addr[ETH_ALEN]; | ||
957 | struct rtl_tid_data tids[MAX_TID_COUNT]; | 1055 | struct rtl_tid_data tids[MAX_TID_COUNT]; |
958 | 1056 | ||
959 | /* just used for ap adhoc or mesh*/ | 1057 | /* just used for ap adhoc or mesh*/ |
@@ -1005,6 +1103,8 @@ struct rtl_mac { | |||
1005 | int n_bitrates; | 1103 | int n_bitrates; |
1006 | 1104 | ||
1007 | bool offchan_delay; | 1105 | bool offchan_delay; |
1106 | u8 p2p; /*using p2p role*/ | ||
1107 | bool p2p_in_use; | ||
1008 | 1108 | ||
1009 | /*filters */ | 1109 | /*filters */ |
1010 | u32 rx_conf; | 1110 | u32 rx_conf; |
@@ -1014,11 +1114,11 @@ struct rtl_mac { | |||
1014 | 1114 | ||
1015 | bool act_scanning; | 1115 | bool act_scanning; |
1016 | u8 cnt_after_linked; | 1116 | u8 cnt_after_linked; |
1117 | bool skip_scan; | ||
1017 | 1118 | ||
1018 | /* early mode */ | 1119 | /* early mode */ |
1019 | /* skb wait queue */ | 1120 | /* skb wait queue */ |
1020 | struct sk_buff_head skb_waitq[MAX_TID_COUNT]; | 1121 | struct sk_buff_head skb_waitq[MAX_TID_COUNT]; |
1021 | u8 earlymode_threshold; | ||
1022 | 1122 | ||
1023 | /*RDG*/ | 1123 | /*RDG*/ |
1024 | bool rdg_en; | 1124 | bool rdg_en; |
@@ -1042,6 +1142,7 @@ struct rtl_mac { | |||
1042 | u8 retry_short; | 1142 | u8 retry_short; |
1043 | u8 retry_long; | 1143 | u8 retry_long; |
1044 | u16 assoc_id; | 1144 | u16 assoc_id; |
1145 | bool hiddenssid; | ||
1045 | 1146 | ||
1046 | /*IBSS*/ | 1147 | /*IBSS*/ |
1047 | int beacon_interval; | 1148 | int beacon_interval; |
@@ -1111,10 +1212,13 @@ struct bt_coexist_8723 { | |||
1111 | 1212 | ||
1112 | struct rtl_hal { | 1213 | struct rtl_hal { |
1113 | struct ieee80211_hw *hw; | 1214 | struct ieee80211_hw *hw; |
1114 | struct bt_coexist_8723 hal_coex_8723; | 1215 | bool driver_is_goingto_unload; |
1115 | bool up_first_time; | 1216 | bool up_first_time; |
1217 | bool first_init; | ||
1116 | bool being_init_adapter; | 1218 | bool being_init_adapter; |
1117 | bool bbrf_ready; | 1219 | bool bbrf_ready; |
1220 | bool mac_func_enable; | ||
1221 | struct bt_coexist_8723 hal_coex_8723; | ||
1118 | 1222 | ||
1119 | enum intf_type interface; | 1223 | enum intf_type interface; |
1120 | u16 hw_type; /*92c or 92d or 92s and so on */ | 1224 | u16 hw_type; /*92c or 92d or 92s and so on */ |
@@ -1122,6 +1226,7 @@ struct rtl_hal { | |||
1122 | u8 oem_id; | 1226 | u8 oem_id; |
1123 | u32 version; /*version of chip */ | 1227 | u32 version; /*version of chip */ |
1124 | u8 state; /*stop 0, start 1 */ | 1228 | u8 state; /*stop 0, start 1 */ |
1229 | u8 board_type; | ||
1125 | 1230 | ||
1126 | /*firmware */ | 1231 | /*firmware */ |
1127 | u32 fwsize; | 1232 | u32 fwsize; |
@@ -1141,6 +1246,10 @@ struct rtl_hal { | |||
1141 | bool set_fwcmd_inprogress; | 1246 | bool set_fwcmd_inprogress; |
1142 | u8 current_fwcmd_io; | 1247 | u8 current_fwcmd_io; |
1143 | 1248 | ||
1249 | struct p2p_ps_offload_t p2p_ps_offload; | ||
1250 | bool fw_clk_change_in_progress; | ||
1251 | bool allow_sw_to_change_hwclc; | ||
1252 | u8 fw_ps_state; | ||
1144 | /**/ | 1253 | /**/ |
1145 | bool driver_going2unload; | 1254 | bool driver_going2unload; |
1146 | 1255 | ||
@@ -1157,6 +1266,7 @@ struct rtl_hal { | |||
1157 | /* just for DualMac S3S4 */ | 1266 | /* just for DualMac S3S4 */ |
1158 | u8 macphyctl_reg; | 1267 | u8 macphyctl_reg; |
1159 | bool earlymode_enable; | 1268 | bool earlymode_enable; |
1269 | u8 max_earlymode_num; | ||
1160 | /* Dual mac*/ | 1270 | /* Dual mac*/ |
1161 | bool during_mac0init_radiob; | 1271 | bool during_mac0init_radiob; |
1162 | bool during_mac1init_radioa; | 1272 | bool during_mac1init_radioa; |
@@ -1193,6 +1303,29 @@ struct rtl_security { | |||
1193 | u8 *pairwise_key; | 1303 | u8 *pairwise_key; |
1194 | }; | 1304 | }; |
1195 | 1305 | ||
1306 | #define ASSOCIATE_ENTRY_NUM 33 | ||
1307 | |||
1308 | struct fast_ant_training { | ||
1309 | u8 bssid[6]; | ||
1310 | u8 antsel_rx_keep_0; | ||
1311 | u8 antsel_rx_keep_1; | ||
1312 | u8 antsel_rx_keep_2; | ||
1313 | u32 ant_sum[7]; | ||
1314 | u32 ant_cnt[7]; | ||
1315 | u32 ant_ave[7]; | ||
1316 | u8 fat_state; | ||
1317 | u32 train_idx; | ||
1318 | u8 antsel_a[ASSOCIATE_ENTRY_NUM]; | ||
1319 | u8 antsel_b[ASSOCIATE_ENTRY_NUM]; | ||
1320 | u8 antsel_c[ASSOCIATE_ENTRY_NUM]; | ||
1321 | u32 main_ant_sum[ASSOCIATE_ENTRY_NUM]; | ||
1322 | u32 aux_ant_sum[ASSOCIATE_ENTRY_NUM]; | ||
1323 | u32 main_ant_cnt[ASSOCIATE_ENTRY_NUM]; | ||
1324 | u32 aux_ant_cnt[ASSOCIATE_ENTRY_NUM]; | ||
1325 | u8 rx_idle_ant; | ||
1326 | bool becomelinked; | ||
1327 | }; | ||
1328 | |||
1196 | struct rtl_dm { | 1329 | struct rtl_dm { |
1197 | /*PHY status for Dynamic Management */ | 1330 | /*PHY status for Dynamic Management */ |
1198 | long entry_min_undec_sm_pwdb; | 1331 | long entry_min_undec_sm_pwdb; |
@@ -1229,9 +1362,24 @@ struct rtl_dm { | |||
1229 | bool disable_tx_int; | 1362 | bool disable_tx_int; |
1230 | char ofdm_index[2]; | 1363 | char ofdm_index[2]; |
1231 | char cck_index; | 1364 | char cck_index; |
1365 | char delta_power_index; | ||
1366 | char delta_power_index_last; | ||
1367 | char power_index_offset; | ||
1368 | |||
1369 | /*88e tx power tracking*/ | ||
1370 | u8 swing_idx_ofdm[2]; | ||
1371 | u8 swing_idx_ofdm_cur; | ||
1372 | u8 swing_idx_ofdm_base; | ||
1373 | bool swing_flag_ofdm; | ||
1374 | u8 swing_idx_cck; | ||
1375 | u8 swing_idx_cck_cur; | ||
1376 | u8 swing_idx_cck_base; | ||
1377 | bool swing_flag_cck; | ||
1232 | 1378 | ||
1233 | /* DMSP */ | 1379 | /* DMSP */ |
1234 | bool supp_phymode_switch; | 1380 | bool supp_phymode_switch; |
1381 | |||
1382 | struct fast_ant_training fat_table; | ||
1235 | }; | 1383 | }; |
1236 | 1384 | ||
1237 | #define EFUSE_MAX_LOGICAL_SIZE 256 | 1385 | #define EFUSE_MAX_LOGICAL_SIZE 256 |
@@ -1264,6 +1412,9 @@ struct rtl_efuse { | |||
1264 | u8 external_pa; | 1412 | u8 external_pa; |
1265 | 1413 | ||
1266 | u8 dev_addr[6]; | 1414 | u8 dev_addr[6]; |
1415 | u8 wowlan_enable; | ||
1416 | u8 antenna_div_cfg; | ||
1417 | u8 antenna_div_type; | ||
1267 | 1418 | ||
1268 | bool txpwr_fromeprom; | 1419 | bool txpwr_fromeprom; |
1269 | u8 eeprom_crystalcap; | 1420 | u8 eeprom_crystalcap; |
@@ -1319,14 +1470,12 @@ struct rtl_ps_ctl { | |||
1319 | bool rfchange_inprogress; | 1470 | bool rfchange_inprogress; |
1320 | bool swrf_processing; | 1471 | bool swrf_processing; |
1321 | bool hwradiooff; | 1472 | bool hwradiooff; |
1322 | |||
1323 | /* | 1473 | /* |
1324 | * just for PCIE ASPM | 1474 | * just for PCIE ASPM |
1325 | * If it supports ASPM, Offset[560h] = 0x40, | 1475 | * If it supports ASPM, Offset[560h] = 0x40, |
1326 | * otherwise Offset[560h] = 0x00. | 1476 | * otherwise Offset[560h] = 0x00. |
1327 | * */ | 1477 | * */ |
1328 | bool support_aspm; | 1478 | bool support_aspm; |
1329 | |||
1330 | bool support_backdoor; | 1479 | bool support_backdoor; |
1331 | 1480 | ||
1332 | /*for LPS */ | 1481 | /*for LPS */ |
@@ -1341,6 +1490,7 @@ struct rtl_ps_ctl { | |||
1341 | bool fw_current_inpsmode; | 1490 | bool fw_current_inpsmode; |
1342 | u8 reg_max_lps_awakeintvl; | 1491 | u8 reg_max_lps_awakeintvl; |
1343 | bool report_linked; | 1492 | bool report_linked; |
1493 | bool low_power_enable;/*for 32k*/ | ||
1344 | 1494 | ||
1345 | /*for IPS */ | 1495 | /*for IPS */ |
1346 | bool inactiveps; | 1496 | bool inactiveps; |
@@ -1373,6 +1523,11 @@ struct rtl_ps_ctl { | |||
1373 | unsigned long last_beacon; | 1523 | unsigned long last_beacon; |
1374 | unsigned long last_action; | 1524 | unsigned long last_action; |
1375 | unsigned long last_slept; | 1525 | unsigned long last_slept; |
1526 | |||
1527 | /*For P2P PS */ | ||
1528 | struct rtl_p2p_ps_info p2p_ps_info; | ||
1529 | u8 pwr_mode; | ||
1530 | u8 smart_ps; | ||
1376 | }; | 1531 | }; |
1377 | 1532 | ||
1378 | struct rtl_stats { | 1533 | struct rtl_stats { |
@@ -1381,7 +1536,7 @@ struct rtl_stats { | |||
1381 | s8 rssi; | 1536 | s8 rssi; |
1382 | u8 signal; | 1537 | u8 signal; |
1383 | u8 noise; | 1538 | u8 noise; |
1384 | u16 rate; /*in 100 kbps */ | 1539 | u8 rate; /* hw desc rate */ |
1385 | u8 received_channel; | 1540 | u8 received_channel; |
1386 | u8 control; | 1541 | u8 control; |
1387 | u8 mask; | 1542 | u8 mask; |
@@ -1423,8 +1578,16 @@ struct rtl_stats { | |||
1423 | bool packet_toself; | 1578 | bool packet_toself; |
1424 | bool packet_beacon; /*for rssi */ | 1579 | bool packet_beacon; /*for rssi */ |
1425 | char cck_adc_pwdb[4]; /*for rx path selection */ | 1580 | char cck_adc_pwdb[4]; /*for rx path selection */ |
1581 | |||
1582 | u8 packet_report_type; | ||
1583 | |||
1584 | u32 macid; | ||
1585 | u8 wake_match; | ||
1586 | u32 bt_rx_rssi_percentage; | ||
1587 | u32 macid_valid_entry[2]; | ||
1426 | }; | 1588 | }; |
1427 | 1589 | ||
1590 | |||
1428 | struct rt_link_detect { | 1591 | struct rt_link_detect { |
1429 | /* count for roaming */ | 1592 | /* count for roaming */ |
1430 | u32 bcn_rx_inperiod; | 1593 | u32 bcn_rx_inperiod; |
@@ -1477,7 +1640,8 @@ struct rtl_tcb_desc { | |||
1477 | /* early mode */ | 1640 | /* early mode */ |
1478 | u8 empkt_num; | 1641 | u8 empkt_num; |
1479 | /* The max value by HW */ | 1642 | /* The max value by HW */ |
1480 | u32 empkt_len[5]; | 1643 | u32 empkt_len[10]; |
1644 | bool btx_enable_sw_calc_duration; | ||
1481 | }; | 1645 | }; |
1482 | 1646 | ||
1483 | struct rtl_hal_ops { | 1647 | struct rtl_hal_ops { |
@@ -1553,7 +1717,7 @@ struct rtl_hal_ops { | |||
1553 | void (*allow_all_destaddr)(struct ieee80211_hw *hw, | 1717 | void (*allow_all_destaddr)(struct ieee80211_hw *hw, |
1554 | bool allow_all_da, bool write_into_reg); | 1718 | bool allow_all_da, bool write_into_reg); |
1555 | void (*linked_set_reg) (struct ieee80211_hw *hw); | 1719 | void (*linked_set_reg) (struct ieee80211_hw *hw); |
1556 | void (*check_switch_to_dmdp) (struct ieee80211_hw *hw); | 1720 | void (*chk_switch_dmdp) (struct ieee80211_hw *hw); |
1557 | void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); | 1721 | void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); |
1558 | void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw); | 1722 | void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw); |
1559 | bool (*phy_rf6052_config) (struct ieee80211_hw *hw); | 1723 | bool (*phy_rf6052_config) (struct ieee80211_hw *hw); |
@@ -1662,6 +1826,8 @@ struct rtl_locks { | |||
1662 | /*spin lock */ | 1826 | /*spin lock */ |
1663 | spinlock_t ips_lock; | 1827 | spinlock_t ips_lock; |
1664 | spinlock_t irq_th_lock; | 1828 | spinlock_t irq_th_lock; |
1829 | spinlock_t irq_pci_lock; | ||
1830 | spinlock_t tx_lock; | ||
1665 | spinlock_t h2c_lock; | 1831 | spinlock_t h2c_lock; |
1666 | spinlock_t rf_ps_lock; | 1832 | spinlock_t rf_ps_lock; |
1667 | spinlock_t rf_lock; | 1833 | spinlock_t rf_lock; |
@@ -1670,6 +1836,9 @@ struct rtl_locks { | |||
1670 | spinlock_t entry_list_lock; | 1836 | spinlock_t entry_list_lock; |
1671 | spinlock_t usb_lock; | 1837 | spinlock_t usb_lock; |
1672 | 1838 | ||
1839 | /*FW clock change */ | ||
1840 | spinlock_t fw_ps_lock; | ||
1841 | |||
1673 | /*Dual mac*/ | 1842 | /*Dual mac*/ |
1674 | spinlock_t cck_and_rw_pagea_lock; | 1843 | spinlock_t cck_and_rw_pagea_lock; |
1675 | 1844 | ||
@@ -1683,7 +1852,8 @@ struct rtl_works { | |||
1683 | /*timer */ | 1852 | /*timer */ |
1684 | struct timer_list watchdog_timer; | 1853 | struct timer_list watchdog_timer; |
1685 | struct timer_list dualmac_easyconcurrent_retrytimer; | 1854 | struct timer_list dualmac_easyconcurrent_retrytimer; |
1686 | 1855 | struct timer_list fw_clockoff_timer; | |
1856 | struct timer_list fast_antenna_training_timer; | ||
1687 | /*task */ | 1857 | /*task */ |
1688 | struct tasklet_struct irq_tasklet; | 1858 | struct tasklet_struct irq_tasklet; |
1689 | struct tasklet_struct irq_prepare_bcn_tasklet; | 1859 | struct tasklet_struct irq_prepare_bcn_tasklet; |
@@ -1696,8 +1866,9 @@ struct rtl_works { | |||
1696 | /* For SW LPS */ | 1866 | /* For SW LPS */ |
1697 | struct delayed_work ps_work; | 1867 | struct delayed_work ps_work; |
1698 | struct delayed_work ps_rfon_wq; | 1868 | struct delayed_work ps_rfon_wq; |
1869 | struct delayed_work fwevt_wq; | ||
1699 | 1870 | ||
1700 | struct work_struct lps_leave_work; | 1871 | struct work_struct lps_change_work; |
1701 | }; | 1872 | }; |
1702 | 1873 | ||
1703 | struct rtl_debug { | 1874 | struct rtl_debug { |
@@ -1767,10 +1938,12 @@ struct dig_t { | |||
1767 | char back_val; | 1938 | char back_val; |
1768 | char back_range_max; | 1939 | char back_range_max; |
1769 | char back_range_min; | 1940 | char back_range_min; |
1770 | u8 rx_gain_range_max; | 1941 | u8 rx_gain_max; |
1771 | u8 rx_gain_range_min; | 1942 | u8 rx_gain_min; |
1772 | u8 min_undec_pwdb_for_dm; | 1943 | u8 min_undec_pwdb_for_dm; |
1773 | u8 rssi_val_min; | 1944 | u8 rssi_val_min; |
1945 | u8 pre_cck_cca_thres; | ||
1946 | u8 cur_cck_cca_thres; | ||
1774 | u8 pre_cck_pd_state; | 1947 | u8 pre_cck_pd_state; |
1775 | u8 cur_cck_pd_state; | 1948 | u8 cur_cck_pd_state; |
1776 | u8 pre_cck_fa_state; | 1949 | u8 pre_cck_fa_state; |
@@ -1792,6 +1965,13 @@ struct dig_t { | |||
1792 | u8 backoff_enable_flag; | 1965 | u8 backoff_enable_flag; |
1793 | char backoffval_range_max; | 1966 | char backoffval_range_max; |
1794 | char backoffval_range_min; | 1967 | char backoffval_range_min; |
1968 | u8 dig_min_0; | ||
1969 | u8 dig_min_1; | ||
1970 | bool media_connect_0; | ||
1971 | bool media_connect_1; | ||
1972 | |||
1973 | u32 antdiv_rssi_max; | ||
1974 | u32 rssi_max; | ||
1795 | }; | 1975 | }; |
1796 | 1976 | ||
1797 | struct rtl_global_var { | 1977 | struct rtl_global_var { |
@@ -1802,6 +1982,7 @@ struct rtl_global_var { | |||
1802 | }; | 1982 | }; |
1803 | 1983 | ||
1804 | struct rtl_priv { | 1984 | struct rtl_priv { |
1985 | struct ieee80211_hw *hw; | ||
1805 | struct completion firmware_loading_complete; | 1986 | struct completion firmware_loading_complete; |
1806 | struct list_head list; | 1987 | struct list_head list; |
1807 | struct rtl_priv *buddy_priv; | 1988 | struct rtl_priv *buddy_priv; |
@@ -1866,6 +2047,7 @@ struct rtl_priv { | |||
1866 | bool bt_operation_on; | 2047 | bool bt_operation_on; |
1867 | }; | 2048 | }; |
1868 | }; | 2049 | }; |
2050 | bool enter_ps; /* true when entering PS */ | ||
1869 | 2051 | ||
1870 | /*This must be the last item so | 2052 | /*This must be the last item so |
1871 | that it points to the data allocated | 2053 | that it points to the data allocated |
@@ -2127,6 +2309,7 @@ value to host byte ordering.*/ | |||
2127 | #define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) | 2309 | #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) | 2310 | #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) | 2311 | #define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA) |
2312 | #define rtl_dm(rtlpriv) (&((rtlpriv)->dm)) | ||
2130 | 2313 | ||
2131 | #define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ | 2314 | #define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ |
2132 | #define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ | 2315 | #define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ |
diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index e57ee48edff6..e2b3d9c541e8 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c | |||
@@ -186,8 +186,10 @@ static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) | |||
186 | wl->set_power(true); | 186 | wl->set_power(true); |
187 | 187 | ||
188 | ret = pm_runtime_get_sync(&func->dev); | 188 | ret = pm_runtime_get_sync(&func->dev); |
189 | if (ret < 0) | 189 | if (ret < 0) { |
190 | pm_runtime_put_sync(&func->dev); | ||
190 | goto out; | 191 | goto out; |
192 | } | ||
191 | 193 | ||
192 | sdio_claim_host(func); | 194 | sdio_claim_host(func); |
193 | sdio_enable_func(func); | 195 | sdio_enable_func(func); |
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 09694e39bb14..1c627da85083 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
@@ -723,6 +723,7 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
723 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; | 723 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; |
724 | wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; | 724 | wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; |
725 | wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ; | 725 | wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ; |
726 | wl->ba_rx_session_count_max = WL12XX_RX_BA_MAX_SESSIONS; | ||
726 | out: | 727 | out: |
727 | return ret; | 728 | return ret; |
728 | } | 729 | } |
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h index d4552857480c..222d03540200 100644 --- a/drivers/net/wireless/ti/wl12xx/wl12xx.h +++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h | |||
@@ -63,6 +63,8 @@ | |||
63 | 63 | ||
64 | #define WL12XX_NUM_MAC_ADDRESSES 2 | 64 | #define WL12XX_NUM_MAC_ADDRESSES 2 |
65 | 65 | ||
66 | #define WL12XX_RX_BA_MAX_SESSIONS 3 | ||
67 | |||
66 | struct wl127x_rx_mem_pool_addr { | 68 | struct wl127x_rx_mem_pool_addr { |
67 | u32 addr; | 69 | u32 addr; |
68 | u32 addr_extra; | 70 | u32 addr_extra; |
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index da3ef1b10a9c..9fa692d11025 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -678,6 +678,7 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
678 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; | 678 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; |
679 | wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC; | 679 | wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC; |
680 | wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ; | 680 | wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ; |
681 | wl->ba_rx_session_count_max = WL18XX_RX_BA_MAX_SESSIONS; | ||
681 | out: | 682 | out: |
682 | return ret; | 683 | return ret; |
683 | } | 684 | } |
@@ -1144,6 +1145,7 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, | |||
1144 | static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) | 1145 | static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) |
1145 | { | 1146 | { |
1146 | u32 fuse; | 1147 | u32 fuse; |
1148 | s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0; | ||
1147 | int ret; | 1149 | int ret; |
1148 | 1150 | ||
1149 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 1151 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); |
@@ -1154,8 +1156,29 @@ static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) | |||
1154 | if (ret < 0) | 1156 | if (ret < 0) |
1155 | goto out; | 1157 | goto out; |
1156 | 1158 | ||
1159 | pg_ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; | ||
1160 | rom = (fuse & WL18XX_ROM_VER_MASK) >> WL18XX_ROM_VER_OFFSET; | ||
1161 | |||
1162 | if (rom <= 0xE) | ||
1163 | metal = (fuse & WL18XX_METAL_VER_MASK) >> | ||
1164 | WL18XX_METAL_VER_OFFSET; | ||
1165 | else | ||
1166 | metal = (fuse & WL18XX_NEW_METAL_VER_MASK) >> | ||
1167 | WL18XX_NEW_METAL_VER_OFFSET; | ||
1168 | |||
1169 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse); | ||
1170 | if (ret < 0) | ||
1171 | goto out; | ||
1172 | |||
1173 | rdl_ver = (fuse & WL18XX_RDL_VER_MASK) >> WL18XX_RDL_VER_OFFSET; | ||
1174 | if (rdl_ver > RDL_MAX) | ||
1175 | rdl_ver = RDL_NONE; | ||
1176 | |||
1177 | wl1271_info("wl18xx HW: RDL %d, %s, PG %x.%x (ROM %x)", | ||
1178 | rdl_ver, rdl_names[rdl_ver], pg_ver, metal, rom); | ||
1179 | |||
1157 | if (ver) | 1180 | if (ver) |
1158 | *ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; | 1181 | *ver = pg_ver; |
1159 | 1182 | ||
1160 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 1183 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
1161 | 1184 | ||
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h index 937b71d8783f..6306e04cd258 100644 --- a/drivers/net/wireless/ti/wl18xx/reg.h +++ b/drivers/net/wireless/ti/wl18xx/reg.h | |||
@@ -131,6 +131,16 @@ | |||
131 | #define WL18XX_REG_FUSE_DATA_1_3 0xA0260C | 131 | #define WL18XX_REG_FUSE_DATA_1_3 0xA0260C |
132 | #define WL18XX_PG_VER_MASK 0x70 | 132 | #define WL18XX_PG_VER_MASK 0x70 |
133 | #define WL18XX_PG_VER_OFFSET 4 | 133 | #define WL18XX_PG_VER_OFFSET 4 |
134 | #define WL18XX_ROM_VER_MASK 0x3 | ||
135 | #define WL18XX_ROM_VER_OFFSET 0 | ||
136 | #define WL18XX_METAL_VER_MASK 0xC | ||
137 | #define WL18XX_METAL_VER_OFFSET 2 | ||
138 | #define WL18XX_NEW_METAL_VER_MASK 0x180 | ||
139 | #define WL18XX_NEW_METAL_VER_OFFSET 7 | ||
140 | |||
141 | #define WL18XX_REG_FUSE_DATA_2_3 0xA02614 | ||
142 | #define WL18XX_RDL_VER_MASK 0x1f00 | ||
143 | #define WL18XX_RDL_VER_OFFSET 8 | ||
134 | 144 | ||
135 | #define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602 | 145 | #define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602 |
136 | #define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606 | 146 | #define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606 |
@@ -188,4 +198,23 @@ enum { | |||
188 | NUM_BOARD_TYPES, | 198 | NUM_BOARD_TYPES, |
189 | }; | 199 | }; |
190 | 200 | ||
201 | enum { | ||
202 | RDL_NONE = 0, | ||
203 | RDL_1_HP = 1, | ||
204 | RDL_2_SP = 2, | ||
205 | RDL_3_HP = 3, | ||
206 | RDL_4_SP = 4, | ||
207 | |||
208 | _RDL_LAST, | ||
209 | RDL_MAX = _RDL_LAST - 1, | ||
210 | }; | ||
211 | |||
212 | static const char * const rdl_names[] = { | ||
213 | [RDL_NONE] = "", | ||
214 | [RDL_1_HP] = "1853 SISO", | ||
215 | [RDL_2_SP] = "1857 MIMO", | ||
216 | [RDL_3_HP] = "1893 SISO", | ||
217 | [RDL_4_SP] = "1897 MIMO", | ||
218 | }; | ||
219 | |||
191 | #endif /* __REG_H__ */ | 220 | #endif /* __REG_H__ */ |
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h index b6739e79efcf..9204e07ee432 100644 --- a/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h | |||
@@ -29,7 +29,7 @@ | |||
29 | #define WL18XX_IFTYPE_VER 5 | 29 | #define WL18XX_IFTYPE_VER 5 |
30 | #define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE | 30 | #define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE |
31 | #define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE | 31 | #define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE |
32 | #define WL18XX_MINOR_VER 28 | 32 | #define WL18XX_MINOR_VER 39 |
33 | 33 | ||
34 | #define WL18XX_CMD_MAX_SIZE 740 | 34 | #define WL18XX_CMD_MAX_SIZE 740 |
35 | 35 | ||
@@ -40,6 +40,8 @@ | |||
40 | 40 | ||
41 | #define WL18XX_NUM_MAC_ADDRESSES 3 | 41 | #define WL18XX_NUM_MAC_ADDRESSES 3 |
42 | 42 | ||
43 | #define WL18XX_RX_BA_MAX_SESSIONS 5 | ||
44 | |||
43 | struct wl18xx_priv { | 45 | struct wl18xx_priv { |
44 | /* buffer for sending commands to FW */ | 46 | /* buffer for sending commands to FW */ |
45 | u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; | 47 | u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; |
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index c79654323396..7a970cd9c555 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
@@ -1736,6 +1736,35 @@ out: | |||
1736 | 1736 | ||
1737 | } | 1737 | } |
1738 | 1738 | ||
1739 | int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
1740 | s8 *avg_rssi) | ||
1741 | { | ||
1742 | struct acx_roaming_stats *acx; | ||
1743 | int ret = 0; | ||
1744 | |||
1745 | wl1271_debug(DEBUG_ACX, "acx roaming statistics"); | ||
1746 | |||
1747 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1748 | if (!acx) { | ||
1749 | ret = -ENOMEM; | ||
1750 | goto out; | ||
1751 | } | ||
1752 | |||
1753 | acx->role_id = wlvif->role_id; | ||
1754 | ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL, | ||
1755 | acx, sizeof(*acx)); | ||
1756 | if (ret < 0) { | ||
1757 | wl1271_warning("acx roaming statistics failed: %d", ret); | ||
1758 | ret = -ENOMEM; | ||
1759 | goto out; | ||
1760 | } | ||
1761 | |||
1762 | *avg_rssi = acx->rssi_beacon; | ||
1763 | out: | ||
1764 | kfree(acx); | ||
1765 | return ret; | ||
1766 | } | ||
1767 | |||
1739 | #ifdef CONFIG_PM | 1768 | #ifdef CONFIG_PM |
1740 | /* Set the global behaviour of RX filters - On/Off + default action */ | 1769 | /* Set the global behaviour of RX filters - On/Off + default action */ |
1741 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, | 1770 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, |
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index 126536c6a393..6dcfad9b0472 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h | |||
@@ -728,8 +728,6 @@ struct wl1271_acx_ht_information { | |||
728 | u8 padding[2]; | 728 | u8 padding[2]; |
729 | } __packed; | 729 | } __packed; |
730 | 730 | ||
731 | #define RX_BA_MAX_SESSIONS 3 | ||
732 | |||
733 | struct wl1271_acx_ba_initiator_policy { | 731 | struct wl1271_acx_ba_initiator_policy { |
734 | struct acx_header header; | 732 | struct acx_header header; |
735 | 733 | ||
@@ -955,6 +953,18 @@ struct acx_rx_filter_cfg { | |||
955 | u8 fields[0]; | 953 | u8 fields[0]; |
956 | } __packed; | 954 | } __packed; |
957 | 955 | ||
956 | struct acx_roaming_stats { | ||
957 | struct acx_header header; | ||
958 | |||
959 | u8 role_id; | ||
960 | u8 pad[3]; | ||
961 | u32 missed_beacons; | ||
962 | u8 snr_data; | ||
963 | u8 snr_bacon; | ||
964 | s8 rssi_data; | ||
965 | s8 rssi_beacon; | ||
966 | } __packed; | ||
967 | |||
958 | enum { | 968 | enum { |
959 | ACX_WAKE_UP_CONDITIONS = 0x0000, | 969 | ACX_WAKE_UP_CONDITIONS = 0x0000, |
960 | ACX_MEM_CFG = 0x0001, | 970 | ACX_MEM_CFG = 0x0001, |
@@ -1112,6 +1122,8 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); | |||
1112 | int wl1271_acx_fm_coex(struct wl1271 *wl); | 1122 | int wl1271_acx_fm_coex(struct wl1271 *wl); |
1113 | int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); | 1123 | int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); |
1114 | int wl12xx_acx_config_hangover(struct wl1271 *wl); | 1124 | int wl12xx_acx_config_hangover(struct wl1271 *wl); |
1125 | int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
1126 | s8 *avg_rssi); | ||
1115 | 1127 | ||
1116 | #ifdef CONFIG_PM | 1128 | #ifdef CONFIG_PM |
1117 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, | 1129 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 6331f9e1cb39..c9e060795d13 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -327,6 +327,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) | |||
327 | wl->links[link].prev_freed_pkts = | 327 | wl->links[link].prev_freed_pkts = |
328 | wl->fw_status_2->counters.tx_lnk_free_pkts[link]; | 328 | wl->fw_status_2->counters.tx_lnk_free_pkts[link]; |
329 | wl->links[link].wlvif = wlvif; | 329 | wl->links[link].wlvif = wlvif; |
330 | |||
331 | /* | ||
332 | * Take saved value for total freed packets from wlvif, in case this is | ||
333 | * recovery/resume | ||
334 | */ | ||
335 | if (wlvif->bss_type != BSS_TYPE_AP_BSS) | ||
336 | wl->links[link].total_freed_pkts = wlvif->total_freed_pkts; | ||
337 | |||
330 | *hlid = link; | 338 | *hlid = link; |
331 | 339 | ||
332 | wl->active_link_count++; | 340 | wl->active_link_count++; |
@@ -358,6 +366,26 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) | |||
358 | wl1271_tx_reset_link_queues(wl, *hlid); | 366 | wl1271_tx_reset_link_queues(wl, *hlid); |
359 | wl->links[*hlid].wlvif = NULL; | 367 | wl->links[*hlid].wlvif = NULL; |
360 | 368 | ||
369 | if (wlvif->bss_type == BSS_TYPE_STA_BSS || | ||
370 | (wlvif->bss_type == BSS_TYPE_AP_BSS && | ||
371 | *hlid == wlvif->ap.bcast_hlid)) { | ||
372 | /* | ||
373 | * save the total freed packets in the wlvif, in case this is | ||
374 | * recovery or suspend | ||
375 | */ | ||
376 | wlvif->total_freed_pkts = wl->links[*hlid].total_freed_pkts; | ||
377 | |||
378 | /* | ||
379 | * increment the initial seq number on recovery to account for | ||
380 | * transmitted packets that we haven't yet got in the FW status | ||
381 | */ | ||
382 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | ||
383 | wlvif->total_freed_pkts += | ||
384 | WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
385 | } | ||
386 | |||
387 | wl->links[*hlid].total_freed_pkts = 0; | ||
388 | |||
361 | *hlid = WL12XX_INVALID_LINK_ID; | 389 | *hlid = WL12XX_INVALID_LINK_ID; |
362 | wl->active_link_count--; | 390 | wl->active_link_count--; |
363 | WARN_ON_ONCE(wl->active_link_count < 0); | 391 | WARN_ON_ONCE(wl->active_link_count < 0); |
@@ -609,6 +637,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
609 | if (ret < 0) | 637 | if (ret < 0) |
610 | goto out_free_global; | 638 | goto out_free_global; |
611 | 639 | ||
640 | /* use the previous security seq, if this is a recovery/resume */ | ||
641 | wl->links[wlvif->ap.bcast_hlid].total_freed_pkts = | ||
642 | wlvif->total_freed_pkts; | ||
643 | |||
612 | cmd->role_id = wlvif->role_id; | 644 | cmd->role_id = wlvif->role_id; |
613 | cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); | 645 | cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); |
614 | cmd->ap.bss_index = WL1271_AP_BSS_INDEX; | 646 | cmd->ap.bss_index = WL1271_AP_BSS_INDEX; |
diff --git a/drivers/net/wireless/ti/wlcore/debug.h b/drivers/net/wireless/ti/wlcore/debug.h index db4bf5a68ce2..0420bd45e4ee 100644 --- a/drivers/net/wireless/ti/wlcore/debug.h +++ b/drivers/net/wireless/ti/wlcore/debug.h | |||
@@ -89,25 +89,24 @@ extern u32 wl12xx_debug_level; | |||
89 | } while (0) | 89 | } while (0) |
90 | #endif | 90 | #endif |
91 | 91 | ||
92 | /* TODO: use pr_debug_hex_dump when it becomes available */ | 92 | #define wl1271_dump(level, prefix, buf, len) \ |
93 | #define wl1271_dump(level, prefix, buf, len) \ | 93 | do { \ |
94 | do { \ | 94 | if (level & wl12xx_debug_level) \ |
95 | if (level & wl12xx_debug_level) \ | 95 | print_hex_dump_debug(DRIVER_PREFIX prefix, \ |
96 | print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ | 96 | DUMP_PREFIX_OFFSET, 16, 1, \ |
97 | DUMP_PREFIX_OFFSET, 16, 1, \ | 97 | buf, \ |
98 | buf, \ | 98 | min_t(size_t, len, DEBUG_DUMP_LIMIT), \ |
99 | min_t(size_t, len, DEBUG_DUMP_LIMIT), \ | 99 | 0); \ |
100 | 0); \ | ||
101 | } while (0) | 100 | } while (0) |
102 | 101 | ||
103 | #define wl1271_dump_ascii(level, prefix, buf, len) \ | 102 | #define wl1271_dump_ascii(level, prefix, buf, len) \ |
104 | do { \ | 103 | do { \ |
105 | if (level & wl12xx_debug_level) \ | 104 | if (level & wl12xx_debug_level) \ |
106 | print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ | 105 | print_hex_dump_debug(DRIVER_PREFIX prefix, \ |
107 | DUMP_PREFIX_OFFSET, 16, 1, \ | 106 | DUMP_PREFIX_OFFSET, 16, 1, \ |
108 | buf, \ | 107 | buf, \ |
109 | min_t(size_t, len, DEBUG_DUMP_LIMIT), \ | 108 | min_t(size_t, len, DEBUG_DUMP_LIMIT), \ |
110 | true); \ | 109 | true); \ |
111 | } while (0) | 110 | } while (0) |
112 | 111 | ||
113 | #endif /* __DEBUG_H__ */ | 112 | #endif /* __DEBUG_H__ */ |
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index e70a7c864865..c3e1f79c7856 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
@@ -598,8 +598,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, | |||
598 | VIF_STATE_PRINT_INT(last_rssi_event); | 598 | VIF_STATE_PRINT_INT(last_rssi_event); |
599 | VIF_STATE_PRINT_INT(ba_support); | 599 | VIF_STATE_PRINT_INT(ba_support); |
600 | VIF_STATE_PRINT_INT(ba_allowed); | 600 | VIF_STATE_PRINT_INT(ba_allowed); |
601 | VIF_STATE_PRINT_LLHEX(tx_security_seq); | 601 | VIF_STATE_PRINT_LLHEX(total_freed_pkts); |
602 | VIF_STATE_PRINT_INT(tx_security_last_seq_lsb); | ||
603 | } | 602 | } |
604 | 603 | ||
605 | #undef VIF_STATE_PRINT_INT | 604 | #undef VIF_STATE_PRINT_INT |
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 70f289aa1bc6..67f61689b49e 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
@@ -237,6 +237,14 @@ void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap) | |||
237 | !test_bit(wlvif->role_id , &roles_bitmap)) | 237 | !test_bit(wlvif->role_id , &roles_bitmap)) |
238 | continue; | 238 | continue; |
239 | 239 | ||
240 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
241 | |||
242 | /* don't attempt roaming in case of p2p */ | ||
243 | if (wlvif->p2p) { | ||
244 | ieee80211_connection_loss(vif); | ||
245 | continue; | ||
246 | } | ||
247 | |||
240 | /* | 248 | /* |
241 | * if the work is already queued, it should take place. | 249 | * if the work is already queued, it should take place. |
242 | * We don't want to delay the connection loss | 250 | * We don't want to delay the connection loss |
@@ -246,7 +254,6 @@ void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap) | |||
246 | &wlvif->connection_loss_work, | 254 | &wlvif->connection_loss_work, |
247 | msecs_to_jiffies(delay)); | 255 | msecs_to_jiffies(delay)); |
248 | 256 | ||
249 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
250 | ieee80211_cqm_rssi_notify( | 257 | ieee80211_cqm_rssi_notify( |
251 | vif, | 258 | vif, |
252 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, | 259 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index c26cb095010c..953111a502ee 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -108,8 +108,7 @@ static void wl1271_reg_notify(struct wiphy *wiphy, | |||
108 | 108 | ||
109 | } | 109 | } |
110 | 110 | ||
111 | if (likely(wl->state == WLCORE_STATE_ON)) | 111 | wlcore_regdomain_config(wl); |
112 | wlcore_regdomain_config(wl); | ||
113 | } | 112 | } |
114 | 113 | ||
115 | static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 114 | static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
@@ -332,10 +331,9 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, | |||
332 | struct wl12xx_vif *wlvif, | 331 | struct wl12xx_vif *wlvif, |
333 | u8 hlid, u8 tx_pkts) | 332 | u8 hlid, u8 tx_pkts) |
334 | { | 333 | { |
335 | bool fw_ps, single_link; | 334 | bool fw_ps; |
336 | 335 | ||
337 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 336 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
338 | single_link = (wl->active_link_count == 1); | ||
339 | 337 | ||
340 | /* | 338 | /* |
341 | * Wake up from high level PS if the STA is asleep with too little | 339 | * Wake up from high level PS if the STA is asleep with too little |
@@ -348,8 +346,13 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, | |||
348 | * Start high-level PS if the STA is asleep with enough blocks in FW. | 346 | * Start high-level PS if the STA is asleep with enough blocks in FW. |
349 | * Make an exception if this is the only connected link. In this | 347 | * Make an exception if this is the only connected link. In this |
350 | * case FW-memory congestion is less of a problem. | 348 | * case FW-memory congestion is less of a problem. |
349 | * Note that a single connected STA means 3 active links, since we must | ||
350 | * account for the global and broadcast AP links. The "fw_ps" check | ||
351 | * assures us the third link is a STA connected to the AP. Otherwise | ||
352 | * the FW would not set the PSM bit. | ||
351 | */ | 353 | */ |
352 | else if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | 354 | else if (wl->active_link_count > 3 && fw_ps && |
355 | tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | ||
353 | wl12xx_ps_link_start(wl, wlvif, hlid, true); | 356 | wl12xx_ps_link_start(wl, wlvif, hlid, true); |
354 | } | 357 | } |
355 | 358 | ||
@@ -414,13 +417,21 @@ static int wlcore_fw_status(struct wl1271 *wl, | |||
414 | 417 | ||
415 | 418 | ||
416 | for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) { | 419 | for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) { |
420 | u8 diff; | ||
417 | lnk = &wl->links[i]; | 421 | lnk = &wl->links[i]; |
422 | |||
418 | /* prevent wrap-around in freed-packets counter */ | 423 | /* prevent wrap-around in freed-packets counter */ |
419 | lnk->allocated_pkts -= | 424 | diff = (status_2->counters.tx_lnk_free_pkts[i] - |
420 | (status_2->counters.tx_lnk_free_pkts[i] - | 425 | lnk->prev_freed_pkts) & 0xff; |
421 | lnk->prev_freed_pkts) & 0xff; | 426 | |
427 | if (diff == 0) | ||
428 | continue; | ||
422 | 429 | ||
430 | lnk->allocated_pkts -= diff; | ||
423 | lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i]; | 431 | lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i]; |
432 | |||
433 | /* accumulate the prev_freed_pkts counter */ | ||
434 | lnk->total_freed_pkts += diff; | ||
424 | } | 435 | } |
425 | 436 | ||
426 | /* prevent wrap-around in total blocks counter */ | 437 | /* prevent wrap-around in total blocks counter */ |
@@ -640,6 +651,25 @@ static irqreturn_t wlcore_irq(int irq, void *cookie) | |||
640 | unsigned long flags; | 651 | unsigned long flags; |
641 | struct wl1271 *wl = cookie; | 652 | struct wl1271 *wl = cookie; |
642 | 653 | ||
654 | /* complete the ELP completion */ | ||
655 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
656 | set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | ||
657 | if (wl->elp_compl) { | ||
658 | complete(wl->elp_compl); | ||
659 | wl->elp_compl = NULL; | ||
660 | } | ||
661 | |||
662 | if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { | ||
663 | /* don't enqueue a work right now. mark it as pending */ | ||
664 | set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); | ||
665 | wl1271_debug(DEBUG_IRQ, "should not enqueue work"); | ||
666 | disable_irq_nosync(wl->irq); | ||
667 | pm_wakeup_event(wl->dev, 0); | ||
668 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
669 | return IRQ_HANDLED; | ||
670 | } | ||
671 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
672 | |||
643 | /* TX might be handled here, avoid redundant work */ | 673 | /* TX might be handled here, avoid redundant work */ |
644 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | 674 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); |
645 | cancel_work_sync(&wl->tx_work); | 675 | cancel_work_sync(&wl->tx_work); |
@@ -919,18 +949,6 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
919 | goto out_unlock; | 949 | goto out_unlock; |
920 | } | 950 | } |
921 | 951 | ||
922 | /* | ||
923 | * Advance security sequence number to overcome potential progress | ||
924 | * in the firmware during recovery. This doens't hurt if the network is | ||
925 | * not encrypted. | ||
926 | */ | ||
927 | wl12xx_for_each_wlvif(wl, wlvif) { | ||
928 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || | ||
929 | test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) | ||
930 | wlvif->tx_security_seq += | ||
931 | WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
932 | } | ||
933 | |||
934 | /* Prevent spurious TX during FW restart */ | 952 | /* Prevent spurious TX during FW restart */ |
935 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); | 953 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); |
936 | 954 | ||
@@ -2523,6 +2541,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
2523 | wl1271_ps_elp_sleep(wl); | 2541 | wl1271_ps_elp_sleep(wl); |
2524 | } | 2542 | } |
2525 | deinit: | 2543 | deinit: |
2544 | wl12xx_tx_reset_wlvif(wl, wlvif); | ||
2545 | |||
2526 | /* clear all hlids (except system_hlid) */ | 2546 | /* clear all hlids (except system_hlid) */ |
2527 | wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; | 2547 | wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; |
2528 | 2548 | ||
@@ -2546,7 +2566,6 @@ deinit: | |||
2546 | 2566 | ||
2547 | dev_kfree_skb(wlvif->probereq); | 2567 | dev_kfree_skb(wlvif->probereq); |
2548 | wlvif->probereq = NULL; | 2568 | wlvif->probereq = NULL; |
2549 | wl12xx_tx_reset_wlvif(wl, wlvif); | ||
2550 | if (wl->last_wlvif == wlvif) | 2569 | if (wl->last_wlvif == wlvif) |
2551 | wl->last_wlvif = NULL; | 2570 | wl->last_wlvif = NULL; |
2552 | list_del(&wlvif->list); | 2571 | list_del(&wlvif->list); |
@@ -2860,10 +2879,6 @@ static int wlcore_unset_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
2860 | wlvif->sta.klv_template_id, | 2879 | wlvif->sta.klv_template_id, |
2861 | ACX_KEEP_ALIVE_TPL_INVALID); | 2880 | ACX_KEEP_ALIVE_TPL_INVALID); |
2862 | 2881 | ||
2863 | /* reset TX security counters on a clean disconnect */ | ||
2864 | wlvif->tx_security_last_seq_lsb = 0; | ||
2865 | wlvif->tx_security_seq = 0; | ||
2866 | |||
2867 | return 0; | 2882 | return 0; |
2868 | } | 2883 | } |
2869 | 2884 | ||
@@ -3262,6 +3277,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
3262 | u32 tx_seq_32 = 0; | 3277 | u32 tx_seq_32 = 0; |
3263 | u16 tx_seq_16 = 0; | 3278 | u16 tx_seq_16 = 0; |
3264 | u8 key_type; | 3279 | u8 key_type; |
3280 | u8 hlid; | ||
3265 | 3281 | ||
3266 | wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); | 3282 | wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); |
3267 | 3283 | ||
@@ -3271,6 +3287,22 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
3271 | key_conf->keylen, key_conf->flags); | 3287 | key_conf->keylen, key_conf->flags); |
3272 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); | 3288 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); |
3273 | 3289 | ||
3290 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | ||
3291 | if (sta) { | ||
3292 | struct wl1271_station *wl_sta = (void *)sta->drv_priv; | ||
3293 | hlid = wl_sta->hlid; | ||
3294 | } else { | ||
3295 | hlid = wlvif->ap.bcast_hlid; | ||
3296 | } | ||
3297 | else | ||
3298 | hlid = wlvif->sta.hlid; | ||
3299 | |||
3300 | if (hlid != WL12XX_INVALID_LINK_ID) { | ||
3301 | u64 tx_seq = wl->links[hlid].total_freed_pkts; | ||
3302 | tx_seq_32 = WL1271_TX_SECURITY_HI32(tx_seq); | ||
3303 | tx_seq_16 = WL1271_TX_SECURITY_LO16(tx_seq); | ||
3304 | } | ||
3305 | |||
3274 | switch (key_conf->cipher) { | 3306 | switch (key_conf->cipher) { |
3275 | case WLAN_CIPHER_SUITE_WEP40: | 3307 | case WLAN_CIPHER_SUITE_WEP40: |
3276 | case WLAN_CIPHER_SUITE_WEP104: | 3308 | case WLAN_CIPHER_SUITE_WEP104: |
@@ -3280,22 +3312,14 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
3280 | break; | 3312 | break; |
3281 | case WLAN_CIPHER_SUITE_TKIP: | 3313 | case WLAN_CIPHER_SUITE_TKIP: |
3282 | key_type = KEY_TKIP; | 3314 | key_type = KEY_TKIP; |
3283 | |||
3284 | key_conf->hw_key_idx = key_conf->keyidx; | 3315 | key_conf->hw_key_idx = key_conf->keyidx; |
3285 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); | ||
3286 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); | ||
3287 | break; | 3316 | break; |
3288 | case WLAN_CIPHER_SUITE_CCMP: | 3317 | case WLAN_CIPHER_SUITE_CCMP: |
3289 | key_type = KEY_AES; | 3318 | key_type = KEY_AES; |
3290 | |||
3291 | key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; | 3319 | key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; |
3292 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); | ||
3293 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); | ||
3294 | break; | 3320 | break; |
3295 | case WL1271_CIPHER_SUITE_GEM: | 3321 | case WL1271_CIPHER_SUITE_GEM: |
3296 | key_type = KEY_GEM; | 3322 | key_type = KEY_GEM; |
3297 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); | ||
3298 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); | ||
3299 | break; | 3323 | break; |
3300 | default: | 3324 | default: |
3301 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); | 3325 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); |
@@ -3358,6 +3382,10 @@ void wlcore_regdomain_config(struct wl1271 *wl) | |||
3358 | return; | 3382 | return; |
3359 | 3383 | ||
3360 | mutex_lock(&wl->mutex); | 3384 | mutex_lock(&wl->mutex); |
3385 | |||
3386 | if (unlikely(wl->state != WLCORE_STATE_ON)) | ||
3387 | goto out; | ||
3388 | |||
3361 | ret = wl1271_ps_elp_wakeup(wl); | 3389 | ret = wl1271_ps_elp_wakeup(wl); |
3362 | if (ret < 0) | 3390 | if (ret < 0) |
3363 | goto out; | 3391 | goto out; |
@@ -4499,6 +4527,9 @@ static int wl1271_allocate_sta(struct wl1271 *wl, | |||
4499 | return -EBUSY; | 4527 | return -EBUSY; |
4500 | } | 4528 | } |
4501 | 4529 | ||
4530 | /* use the previous security seq, if this is a recovery/resume */ | ||
4531 | wl->links[wl_sta->hlid].total_freed_pkts = wl_sta->total_freed_pkts; | ||
4532 | |||
4502 | set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map); | 4533 | set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map); |
4503 | memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); | 4534 | memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); |
4504 | wl->active_sta_count++; | 4535 | wl->active_sta_count++; |
@@ -4507,12 +4538,37 @@ static int wl1271_allocate_sta(struct wl1271 *wl, | |||
4507 | 4538 | ||
4508 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) | 4539 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) |
4509 | { | 4540 | { |
4541 | struct wl1271_station *wl_sta; | ||
4542 | struct ieee80211_sta *sta; | ||
4543 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
4544 | |||
4510 | if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) | 4545 | if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) |
4511 | return; | 4546 | return; |
4512 | 4547 | ||
4513 | clear_bit(hlid, wlvif->ap.sta_hlid_map); | 4548 | clear_bit(hlid, wlvif->ap.sta_hlid_map); |
4514 | __clear_bit(hlid, &wl->ap_ps_map); | 4549 | __clear_bit(hlid, &wl->ap_ps_map); |
4515 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 4550 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
4551 | |||
4552 | /* | ||
4553 | * save the last used PN in the private part of iee80211_sta, | ||
4554 | * in case of recovery/suspend | ||
4555 | */ | ||
4556 | rcu_read_lock(); | ||
4557 | sta = ieee80211_find_sta(vif, wl->links[hlid].addr); | ||
4558 | if (sta) { | ||
4559 | wl_sta = (void *)sta->drv_priv; | ||
4560 | wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts; | ||
4561 | |||
4562 | /* | ||
4563 | * increment the initial seq number on recovery to account for | ||
4564 | * transmitted packets that we haven't yet got in the FW status | ||
4565 | */ | ||
4566 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | ||
4567 | wl_sta->total_freed_pkts += | ||
4568 | WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
4569 | } | ||
4570 | rcu_read_unlock(); | ||
4571 | |||
4516 | wl12xx_free_link(wl, wlvif, &hlid); | 4572 | wl12xx_free_link(wl, wlvif, &hlid); |
4517 | wl->active_sta_count--; | 4573 | wl->active_sta_count--; |
4518 | 4574 | ||
@@ -4616,13 +4672,11 @@ static int wl12xx_update_sta_state(struct wl1271 *wl, | |||
4616 | enum ieee80211_sta_state new_state) | 4672 | enum ieee80211_sta_state new_state) |
4617 | { | 4673 | { |
4618 | struct wl1271_station *wl_sta; | 4674 | struct wl1271_station *wl_sta; |
4619 | u8 hlid; | ||
4620 | bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; | 4675 | bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; |
4621 | bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; | 4676 | bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; |
4622 | int ret; | 4677 | int ret; |
4623 | 4678 | ||
4624 | wl_sta = (struct wl1271_station *)sta->drv_priv; | 4679 | wl_sta = (struct wl1271_station *)sta->drv_priv; |
4625 | hlid = wl_sta->hlid; | ||
4626 | 4680 | ||
4627 | /* Add station (AP mode) */ | 4681 | /* Add station (AP mode) */ |
4628 | if (is_ap && | 4682 | if (is_ap && |
@@ -4648,12 +4702,12 @@ static int wl12xx_update_sta_state(struct wl1271 *wl, | |||
4648 | /* Authorize station (AP mode) */ | 4702 | /* Authorize station (AP mode) */ |
4649 | if (is_ap && | 4703 | if (is_ap && |
4650 | new_state == IEEE80211_STA_AUTHORIZED) { | 4704 | new_state == IEEE80211_STA_AUTHORIZED) { |
4651 | ret = wl12xx_cmd_set_peer_state(wl, wlvif, hlid); | 4705 | ret = wl12xx_cmd_set_peer_state(wl, wlvif, wl_sta->hlid); |
4652 | if (ret < 0) | 4706 | if (ret < 0) |
4653 | return ret; | 4707 | return ret; |
4654 | 4708 | ||
4655 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, | 4709 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, |
4656 | hlid); | 4710 | wl_sta->hlid); |
4657 | if (ret) | 4711 | if (ret) |
4658 | return ret; | 4712 | return ret; |
4659 | 4713 | ||
@@ -4784,7 +4838,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, | |||
4784 | break; | 4838 | break; |
4785 | } | 4839 | } |
4786 | 4840 | ||
4787 | if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) { | 4841 | if (wl->ba_rx_session_count >= wl->ba_rx_session_count_max) { |
4788 | ret = -EBUSY; | 4842 | ret = -EBUSY; |
4789 | wl1271_error("exceeded max RX BA sessions"); | 4843 | wl1271_error("exceeded max RX BA sessions"); |
4790 | break; | 4844 | break; |
@@ -5092,6 +5146,39 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw, | |||
5092 | wlcore_hw_sta_rc_update(wl, wlvif, sta, changed); | 5146 | wlcore_hw_sta_rc_update(wl, wlvif, sta, changed); |
5093 | } | 5147 | } |
5094 | 5148 | ||
5149 | static int wlcore_op_get_rssi(struct ieee80211_hw *hw, | ||
5150 | struct ieee80211_vif *vif, | ||
5151 | struct ieee80211_sta *sta, | ||
5152 | s8 *rssi_dbm) | ||
5153 | { | ||
5154 | struct wl1271 *wl = hw->priv; | ||
5155 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
5156 | int ret = 0; | ||
5157 | |||
5158 | wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi"); | ||
5159 | |||
5160 | mutex_lock(&wl->mutex); | ||
5161 | |||
5162 | if (unlikely(wl->state != WLCORE_STATE_ON)) | ||
5163 | goto out; | ||
5164 | |||
5165 | ret = wl1271_ps_elp_wakeup(wl); | ||
5166 | if (ret < 0) | ||
5167 | goto out_sleep; | ||
5168 | |||
5169 | ret = wlcore_acx_average_rssi(wl, wlvif, rssi_dbm); | ||
5170 | if (ret < 0) | ||
5171 | goto out_sleep; | ||
5172 | |||
5173 | out_sleep: | ||
5174 | wl1271_ps_elp_sleep(wl); | ||
5175 | |||
5176 | out: | ||
5177 | mutex_unlock(&wl->mutex); | ||
5178 | |||
5179 | return ret; | ||
5180 | } | ||
5181 | |||
5095 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | 5182 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) |
5096 | { | 5183 | { |
5097 | struct wl1271 *wl = hw->priv; | 5184 | struct wl1271 *wl = hw->priv; |
@@ -5291,6 +5378,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
5291 | .assign_vif_chanctx = wlcore_op_assign_vif_chanctx, | 5378 | .assign_vif_chanctx = wlcore_op_assign_vif_chanctx, |
5292 | .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx, | 5379 | .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx, |
5293 | .sta_rc_update = wlcore_op_sta_rc_update, | 5380 | .sta_rc_update = wlcore_op_sta_rc_update, |
5381 | .get_rssi = wlcore_op_get_rssi, | ||
5294 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 5382 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
5295 | }; | 5383 | }; |
5296 | 5384 | ||
@@ -5930,35 +6018,6 @@ int wlcore_free_hw(struct wl1271 *wl) | |||
5930 | } | 6018 | } |
5931 | EXPORT_SYMBOL_GPL(wlcore_free_hw); | 6019 | EXPORT_SYMBOL_GPL(wlcore_free_hw); |
5932 | 6020 | ||
5933 | static irqreturn_t wl12xx_hardirq(int irq, void *cookie) | ||
5934 | { | ||
5935 | struct wl1271 *wl = cookie; | ||
5936 | unsigned long flags; | ||
5937 | |||
5938 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
5939 | |||
5940 | /* complete the ELP completion */ | ||
5941 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
5942 | set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | ||
5943 | if (wl->elp_compl) { | ||
5944 | complete(wl->elp_compl); | ||
5945 | wl->elp_compl = NULL; | ||
5946 | } | ||
5947 | |||
5948 | if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { | ||
5949 | /* don't enqueue a work right now. mark it as pending */ | ||
5950 | set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); | ||
5951 | wl1271_debug(DEBUG_IRQ, "should not enqueue work"); | ||
5952 | disable_irq_nosync(wl->irq); | ||
5953 | pm_wakeup_event(wl->dev, 0); | ||
5954 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
5955 | return IRQ_HANDLED; | ||
5956 | } | ||
5957 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
5958 | |||
5959 | return IRQ_WAKE_THREAD; | ||
5960 | } | ||
5961 | |||
5962 | static void wlcore_nvs_cb(const struct firmware *fw, void *context) | 6021 | static void wlcore_nvs_cb(const struct firmware *fw, void *context) |
5963 | { | 6022 | { |
5964 | struct wl1271 *wl = context; | 6023 | struct wl1271 *wl = context; |
@@ -6000,9 +6059,8 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) | |||
6000 | else | 6059 | else |
6001 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; | 6060 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; |
6002 | 6061 | ||
6003 | ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wlcore_irq, | 6062 | ret = request_threaded_irq(wl->irq, NULL, wlcore_irq, |
6004 | irqflags, | 6063 | irqflags, pdev->name, wl); |
6005 | pdev->name, wl); | ||
6006 | if (ret < 0) { | 6064 | if (ret < 0) { |
6007 | wl1271_error("request_irq() failed: %d", ret); | 6065 | wl1271_error("request_irq() failed: %d", ret); |
6008 | goto out_free_nvs; | 6066 | goto out_free_nvs; |
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 9b7b6e2e4fbc..9654577efd01 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #define WL1271_WAKEUP_TIMEOUT 500 | 29 | #define WL1271_WAKEUP_TIMEOUT 500 |
30 | 30 | ||
31 | #define ELP_ENTRY_DELAY 30 | 31 | #define ELP_ENTRY_DELAY 30 |
32 | #define ELP_ENTRY_DELAY_FORCE_PS 5 | ||
32 | 33 | ||
33 | void wl1271_elp_work(struct work_struct *work) | 34 | void wl1271_elp_work(struct work_struct *work) |
34 | { | 35 | { |
@@ -98,7 +99,8 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) | |||
98 | return; | 99 | return; |
99 | } | 100 | } |
100 | 101 | ||
101 | timeout = ELP_ENTRY_DELAY; | 102 | timeout = wl->conf.conn.forced_ps ? |
103 | ELP_ENTRY_DELAY_FORCE_PS : ELP_ENTRY_DELAY; | ||
102 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 104 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
103 | msecs_to_jiffies(timeout)); | 105 | msecs_to_jiffies(timeout)); |
104 | } | 106 | } |
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index ece392c54d9c..004d02e71f01 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/etherdevice.h> | 26 | #include <linux/etherdevice.h> |
27 | #include <linux/spinlock.h> | ||
27 | 28 | ||
28 | #include "wlcore.h" | 29 | #include "wlcore.h" |
29 | #include "debug.h" | 30 | #include "debug.h" |
@@ -104,7 +105,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, | |||
104 | struct wl12xx_vif *wlvif, | 105 | struct wl12xx_vif *wlvif, |
105 | u8 hlid) | 106 | u8 hlid) |
106 | { | 107 | { |
107 | bool fw_ps, single_link; | 108 | bool fw_ps; |
108 | u8 tx_pkts; | 109 | u8 tx_pkts; |
109 | 110 | ||
110 | if (WARN_ON(!test_bit(hlid, wlvif->links_map))) | 111 | if (WARN_ON(!test_bit(hlid, wlvif->links_map))) |
@@ -112,15 +113,19 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, | |||
112 | 113 | ||
113 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 114 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
114 | tx_pkts = wl->links[hlid].allocated_pkts; | 115 | tx_pkts = wl->links[hlid].allocated_pkts; |
115 | single_link = (wl->active_link_count == 1); | ||
116 | 116 | ||
117 | /* | 117 | /* |
118 | * if in FW PS and there is enough data in FW we can put the link | 118 | * if in FW PS and there is enough data in FW we can put the link |
119 | * into high-level PS and clean out its TX queues. | 119 | * into high-level PS and clean out its TX queues. |
120 | * Make an exception if this is the only connected link. In this | 120 | * Make an exception if this is the only connected link. In this |
121 | * case FW-memory congestion is less of a problem. | 121 | * case FW-memory congestion is less of a problem. |
122 | * Note that a single connected STA means 3 active links, since we must | ||
123 | * account for the global and broadcast AP links. The "fw_ps" check | ||
124 | * assures us the third link is a STA connected to the AP. Otherwise | ||
125 | * the FW would not set the PSM bit. | ||
122 | */ | 126 | */ |
123 | if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | 127 | if (wl->active_link_count > 3 && fw_ps && |
128 | tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | ||
124 | wl12xx_ps_link_start(wl, wlvif, hlid, true); | 129 | wl12xx_ps_link_start(wl, wlvif, hlid, true); |
125 | } | 130 | } |
126 | 131 | ||
@@ -639,6 +644,7 @@ next: | |||
639 | 644 | ||
640 | } | 645 | } |
641 | 646 | ||
647 | out: | ||
642 | if (!skb && | 648 | if (!skb && |
643 | test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { | 649 | test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { |
644 | int q; | 650 | int q; |
@@ -652,7 +658,6 @@ next: | |||
652 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 658 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
653 | } | 659 | } |
654 | 660 | ||
655 | out: | ||
656 | return skb; | 661 | return skb; |
657 | } | 662 | } |
658 | 663 | ||
@@ -928,25 +933,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
928 | 933 | ||
929 | wl->stats.retry_count += result->ack_failures; | 934 | wl->stats.retry_count += result->ack_failures; |
930 | 935 | ||
931 | /* | ||
932 | * update sequence number only when relevant, i.e. only in | ||
933 | * sessions of TKIP, AES and GEM (not in open or WEP sessions) | ||
934 | */ | ||
935 | if (info->control.hw_key && | ||
936 | (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP || | ||
937 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP || | ||
938 | info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) { | ||
939 | u8 fw_lsb = result->tx_security_sequence_number_lsb; | ||
940 | u8 cur_lsb = wlvif->tx_security_last_seq_lsb; | ||
941 | |||
942 | /* | ||
943 | * update security sequence number, taking care of potential | ||
944 | * wrap-around | ||
945 | */ | ||
946 | wlvif->tx_security_seq += (fw_lsb - cur_lsb) & 0xff; | ||
947 | wlvif->tx_security_last_seq_lsb = fw_lsb; | ||
948 | } | ||
949 | |||
950 | /* remove private header from packet */ | 936 | /* remove private header from packet */ |
951 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | 937 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); |
952 | 938 | ||
@@ -1061,7 +1047,8 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1061 | 1047 | ||
1062 | /* TX failure */ | 1048 | /* TX failure */ |
1063 | for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) { | 1049 | for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) { |
1064 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) { | 1050 | if (wlvif->bss_type == BSS_TYPE_AP_BSS && |
1051 | i != wlvif->ap.bcast_hlid && i != wlvif->ap.global_hlid) { | ||
1065 | /* this calls wl12xx_free_link */ | 1052 | /* this calls wl12xx_free_link */ |
1066 | wl1271_free_sta(wl, wlvif, i); | 1053 | wl1271_free_sta(wl, wlvif, i); |
1067 | } else { | 1054 | } else { |
@@ -1304,7 +1291,7 @@ bool wlcore_is_queue_stopped_by_reason_locked(struct wl1271 *wl, | |||
1304 | { | 1291 | { |
1305 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); | 1292 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); |
1306 | 1293 | ||
1307 | WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock)); | 1294 | assert_spin_locked(&wl->wl_lock); |
1308 | return test_bit(reason, &wl->queue_stop_reasons[hwq]); | 1295 | return test_bit(reason, &wl->queue_stop_reasons[hwq]); |
1309 | } | 1296 | } |
1310 | 1297 | ||
@@ -1313,6 +1300,6 @@ bool wlcore_is_queue_stopped_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1313 | { | 1300 | { |
1314 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); | 1301 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); |
1315 | 1302 | ||
1316 | WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock)); | 1303 | assert_spin_locked(&wl->wl_lock); |
1317 | return !!wl->queue_stop_reasons[hwq]; | 1304 | return !!wl->queue_stop_reasons[hwq]; |
1318 | } | 1305 | } |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index af9fecaefc30..0034979e97cb 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -390,6 +390,9 @@ struct wl1271 { | |||
390 | /* number of currently active RX BA sessions */ | 390 | /* number of currently active RX BA sessions */ |
391 | int ba_rx_session_count; | 391 | int ba_rx_session_count; |
392 | 392 | ||
393 | /* Maximum number of supported RX BA sessions */ | ||
394 | int ba_rx_session_count_max; | ||
395 | |||
393 | /* AP-mode - number of currently connected stations */ | 396 | /* AP-mode - number of currently connected stations */ |
394 | int active_sta_count; | 397 | int active_sta_count; |
395 | 398 | ||
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 508f5b0f8a70..e5e146435fe7 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
@@ -274,6 +274,13 @@ struct wl1271_link { | |||
274 | 274 | ||
275 | /* The wlvif this link belongs to. Might be null for global links */ | 275 | /* The wlvif this link belongs to. Might be null for global links */ |
276 | struct wl12xx_vif *wlvif; | 276 | struct wl12xx_vif *wlvif; |
277 | |||
278 | /* | ||
279 | * total freed FW packets on the link - used for tracking the | ||
280 | * AES/TKIP PN across recoveries. Re-initialized each time | ||
281 | * from the wl1271_station structure. | ||
282 | */ | ||
283 | u64 total_freed_pkts; | ||
277 | }; | 284 | }; |
278 | 285 | ||
279 | #define WL1271_MAX_RX_FILTERS 5 | 286 | #define WL1271_MAX_RX_FILTERS 5 |
@@ -318,6 +325,13 @@ struct wl12xx_rx_filter { | |||
318 | struct wl1271_station { | 325 | struct wl1271_station { |
319 | u8 hlid; | 326 | u8 hlid; |
320 | bool in_connection; | 327 | bool in_connection; |
328 | |||
329 | /* | ||
330 | * total freed FW packets on the link to the STA - used for tracking the | ||
331 | * AES/TKIP PN across recoveries. Re-initialized each time from the | ||
332 | * wl1271_station structure. | ||
333 | */ | ||
334 | u64 total_freed_pkts; | ||
321 | }; | 335 | }; |
322 | 336 | ||
323 | struct wl12xx_vif { | 337 | struct wl12xx_vif { |
@@ -449,16 +463,15 @@ struct wl12xx_vif { | |||
449 | */ | 463 | */ |
450 | struct { | 464 | struct { |
451 | u8 persistent[0]; | 465 | u8 persistent[0]; |
466 | |||
452 | /* | 467 | /* |
453 | * Security sequence number | 468 | * total freed FW packets on the link - used for |
454 | * bits 0-15: lower 16 bits part of sequence number | 469 | * storing the AES/TKIP PN during recovery, as this |
455 | * bits 16-47: higher 32 bits part of sequence number | 470 | * structure is not zeroed out. |
456 | * bits 48-63: not in use | 471 | * For STA this holds the PN of the link to the AP. |
472 | * For AP this holds the PN of the broadcast link. | ||
457 | */ | 473 | */ |
458 | u64 tx_security_seq; | 474 | u64 total_freed_pkts; |
459 | |||
460 | /* 8 bits of the last sequence number in use */ | ||
461 | u8 tx_security_last_seq_lsb; | ||
462 | }; | 475 | }; |
463 | }; | 476 | }; |
464 | 477 | ||
diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index eef38cfd812e..ca33ae193935 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/mei_bus.h> | 25 | #include <linux/mei_cl_bus.h> |
26 | 26 | ||
27 | #include <linux/nfc.h> | 27 | #include <linux/nfc.h> |
28 | #include <net/nfc/hci.h> | 28 | #include <net/nfc/hci.h> |
@@ -32,9 +32,6 @@ | |||
32 | 32 | ||
33 | #define MICROREAD_DRIVER_NAME "microread" | 33 | #define MICROREAD_DRIVER_NAME "microread" |
34 | 34 | ||
35 | #define MICROREAD_UUID UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, 0x94, \ | ||
36 | 0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c) | ||
37 | |||
38 | struct mei_nfc_hdr { | 35 | struct mei_nfc_hdr { |
39 | u8 cmd; | 36 | u8 cmd; |
40 | u8 status; | 37 | u8 status; |
@@ -48,7 +45,7 @@ struct mei_nfc_hdr { | |||
48 | #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) | 45 | #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) |
49 | 46 | ||
50 | struct microread_mei_phy { | 47 | struct microread_mei_phy { |
51 | struct mei_device *mei_device; | 48 | struct mei_cl_device *device; |
52 | struct nfc_hci_dev *hdev; | 49 | struct nfc_hci_dev *hdev; |
53 | 50 | ||
54 | int powered; | 51 | int powered; |
@@ -105,14 +102,14 @@ static int microread_mei_write(void *phy_id, struct sk_buff *skb) | |||
105 | 102 | ||
106 | MEI_DUMP_SKB_OUT("mei frame sent", skb); | 103 | MEI_DUMP_SKB_OUT("mei frame sent", skb); |
107 | 104 | ||
108 | r = mei_send(phy->device, skb->data, skb->len); | 105 | r = mei_cl_send(phy->device, skb->data, skb->len); |
109 | if (r > 0) | 106 | if (r > 0) |
110 | r = 0; | 107 | r = 0; |
111 | 108 | ||
112 | return r; | 109 | return r; |
113 | } | 110 | } |
114 | 111 | ||
115 | static void microread_event_cb(struct mei_device *device, u32 events, | 112 | static void microread_event_cb(struct mei_cl_device *device, u32 events, |
116 | void *context) | 113 | void *context) |
117 | { | 114 | { |
118 | struct microread_mei_phy *phy = context; | 115 | struct microread_mei_phy *phy = context; |
@@ -120,7 +117,7 @@ static void microread_event_cb(struct mei_device *device, u32 events, | |||
120 | if (phy->hard_fault != 0) | 117 | if (phy->hard_fault != 0) |
121 | return; | 118 | return; |
122 | 119 | ||
123 | if (events & BIT(MEI_EVENT_RX)) { | 120 | if (events & BIT(MEI_CL_EVENT_RX)) { |
124 | struct sk_buff *skb; | 121 | struct sk_buff *skb; |
125 | int reply_size; | 122 | int reply_size; |
126 | 123 | ||
@@ -128,7 +125,7 @@ static void microread_event_cb(struct mei_device *device, u32 events, | |||
128 | if (!skb) | 125 | if (!skb) |
129 | return; | 126 | return; |
130 | 127 | ||
131 | reply_size = mei_recv(device, skb->data, MEI_NFC_MAX_READ); | 128 | reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ); |
132 | if (reply_size < MEI_NFC_HEADER_SIZE) { | 129 | if (reply_size < MEI_NFC_HEADER_SIZE) { |
133 | kfree(skb); | 130 | kfree(skb); |
134 | return; | 131 | return; |
@@ -149,8 +146,8 @@ static struct nfc_phy_ops mei_phy_ops = { | |||
149 | .disable = microread_mei_disable, | 146 | .disable = microread_mei_disable, |
150 | }; | 147 | }; |
151 | 148 | ||
152 | static int microread_mei_probe(struct mei_device *device, | 149 | static int microread_mei_probe(struct mei_cl_device *device, |
153 | const struct mei_id *id) | 150 | const struct mei_cl_device_id *id) |
154 | { | 151 | { |
155 | struct microread_mei_phy *phy; | 152 | struct microread_mei_phy *phy; |
156 | int r; | 153 | int r; |
@@ -164,9 +161,9 @@ static int microread_mei_probe(struct mei_device *device, | |||
164 | } | 161 | } |
165 | 162 | ||
166 | phy->device = device; | 163 | phy->device = device; |
167 | mei_set_clientdata(device, phy); | 164 | mei_cl_set_drvdata(device, phy); |
168 | 165 | ||
169 | r = mei_register_event_cb(device, microread_event_cb, phy); | 166 | r = mei_cl_register_event_cb(device, microread_event_cb, phy); |
170 | if (r) { | 167 | if (r) { |
171 | pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n"); | 168 | pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n"); |
172 | goto err_out; | 169 | goto err_out; |
@@ -186,9 +183,9 @@ err_out: | |||
186 | return r; | 183 | return r; |
187 | } | 184 | } |
188 | 185 | ||
189 | static int microread_mei_remove(struct mei_device *device) | 186 | static int microread_mei_remove(struct mei_cl_device *device) |
190 | { | 187 | { |
191 | struct microread_mei_phy *phy = mei_get_clientdata(device); | 188 | struct microread_mei_phy *phy = mei_cl_get_drvdata(device); |
192 | 189 | ||
193 | pr_info("Removing microread\n"); | 190 | pr_info("Removing microread\n"); |
194 | 191 | ||
@@ -202,16 +199,15 @@ static int microread_mei_remove(struct mei_device *device) | |||
202 | return 0; | 199 | return 0; |
203 | } | 200 | } |
204 | 201 | ||
205 | static struct mei_id microread_mei_tbl[] = { | 202 | static struct mei_cl_device_id microread_mei_tbl[] = { |
206 | { MICROREAD_DRIVER_NAME, MICROREAD_UUID }, | 203 | { MICROREAD_DRIVER_NAME }, |
207 | 204 | ||
208 | /* required last entry */ | 205 | /* required last entry */ |
209 | { } | 206 | { } |
210 | }; | 207 | }; |
211 | |||
212 | MODULE_DEVICE_TABLE(mei, microread_mei_tbl); | 208 | MODULE_DEVICE_TABLE(mei, microread_mei_tbl); |
213 | 209 | ||
214 | static struct mei_driver microread_driver = { | 210 | static struct mei_cl_driver microread_driver = { |
215 | .id_table = microread_mei_tbl, | 211 | .id_table = microread_mei_tbl, |
216 | .name = MICROREAD_DRIVER_NAME, | 212 | .name = MICROREAD_DRIVER_NAME, |
217 | 213 | ||
@@ -225,7 +221,7 @@ static int microread_mei_init(void) | |||
225 | 221 | ||
226 | pr_debug(DRIVER_DESC ": %s\n", __func__); | 222 | pr_debug(DRIVER_DESC ": %s\n", __func__); |
227 | 223 | ||
228 | r = mei_driver_register(µread_driver); | 224 | r = mei_cl_driver_register(µread_driver); |
229 | if (r) { | 225 | if (r) { |
230 | pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n"); | 226 | pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n"); |
231 | return r; | 227 | return r; |
@@ -236,7 +232,7 @@ static int microread_mei_init(void) | |||
236 | 232 | ||
237 | static void microread_mei_exit(void) | 233 | static void microread_mei_exit(void) |
238 | { | 234 | { |
239 | mei_driver_unregister(µread_driver); | 235 | mei_cl_driver_unregister(µread_driver); |
240 | } | 236 | } |
241 | 237 | ||
242 | module_init(microread_mei_init); | 238 | module_init(microread_mei_init); |
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..a8dc95ebf2d6 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 | ||
@@ -339,10 +347,23 @@ static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, | |||
339 | return (s8)gain; | 347 | return (s8)gain; |
340 | } | 348 | } |
341 | 349 | ||
350 | static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in) | ||
351 | { | ||
352 | SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); | ||
353 | SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0); | ||
354 | SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0); | ||
355 | SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0); | ||
356 | SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0); | ||
357 | SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0); | ||
358 | SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0); | ||
359 | SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0); | ||
360 | SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0); | ||
361 | SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO, | ||
362 | SSB_SPROM2_MAXP_A_LO_SHIFT); | ||
363 | } | ||
364 | |||
342 | static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | 365 | static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) |
343 | { | 366 | { |
344 | int i; | ||
345 | u16 v; | ||
346 | u16 loc[3]; | 367 | u16 loc[3]; |
347 | 368 | ||
348 | if (out->revision == 3) /* rev 3 moved MAC */ | 369 | if (out->revision == 3) /* rev 3 moved MAC */ |
@@ -352,19 +373,10 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
352 | loc[1] = SSB_SPROM1_ET0MAC; | 373 | loc[1] = SSB_SPROM1_ET0MAC; |
353 | loc[2] = SSB_SPROM1_ET1MAC; | 374 | loc[2] = SSB_SPROM1_ET1MAC; |
354 | } | 375 | } |
355 | for (i = 0; i < 3; i++) { | 376 | 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 */ | 377 | if (out->revision < 3) { /* only rev 1-2 have et0, et1 */ |
360 | for (i = 0; i < 3; i++) { | 378 | sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]); |
361 | v = in[SPOFF(loc[1]) + i]; | 379 | 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 | } | 380 | } |
369 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); | 381 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); |
370 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, | 382 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, |
@@ -372,6 +384,7 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
372 | SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); | 384 | SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); |
373 | SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); | 385 | SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); |
374 | SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); | 386 | SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); |
387 | SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); | ||
375 | if (out->revision == 1) | 388 | if (out->revision == 1) |
376 | SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, | 389 | SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, |
377 | SSB_SPROM1_BINF_CCODE_SHIFT); | 390 | SSB_SPROM1_BINF_CCODE_SHIFT); |
@@ -398,8 +411,7 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
398 | SSB_SPROM1_ITSSI_A_SHIFT); | 411 | SSB_SPROM1_ITSSI_A_SHIFT); |
399 | SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); | 412 | SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); |
400 | SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); | 413 | SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); |
401 | if (out->revision >= 2) | 414 | |
402 | SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); | ||
403 | SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); | 415 | SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); |
404 | SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); | 416 | SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); |
405 | 417 | ||
@@ -410,6 +422,8 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
410 | out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, | 422 | out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, |
411 | SSB_SPROM1_AGAIN_A, | 423 | SSB_SPROM1_AGAIN_A, |
412 | SSB_SPROM1_AGAIN_A_SHIFT); | 424 | SSB_SPROM1_AGAIN_A_SHIFT); |
425 | if (out->revision >= 2) | ||
426 | sprom_extract_r23(out, in); | ||
413 | } | 427 | } |
414 | 428 | ||
415 | /* Revs 4 5 and 8 have partially shared layout */ | 429 | /* Revs 4 5 and 8 have partially shared layout */ |
@@ -454,23 +468,20 @@ static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) | |||
454 | 468 | ||
455 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | 469 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) |
456 | { | 470 | { |
457 | int i; | ||
458 | u16 v; | ||
459 | u16 il0mac_offset; | 471 | u16 il0mac_offset; |
460 | 472 | ||
461 | if (out->revision == 4) | 473 | if (out->revision == 4) |
462 | il0mac_offset = SSB_SPROM4_IL0MAC; | 474 | il0mac_offset = SSB_SPROM4_IL0MAC; |
463 | else | 475 | else |
464 | il0mac_offset = SSB_SPROM5_IL0MAC; | 476 | il0mac_offset = SSB_SPROM5_IL0MAC; |
465 | /* extract the MAC address */ | 477 | |
466 | for (i = 0; i < 3; i++) { | 478 | sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]); |
467 | v = in[SPOFF(il0mac_offset) + i]; | 479 | |
468 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | ||
469 | } | ||
470 | SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); | 480 | SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); |
471 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, | 481 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, |
472 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); | 482 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); |
473 | SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0); | 483 | SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0); |
484 | SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); | ||
474 | if (out->revision == 4) { | 485 | if (out->revision == 4) { |
475 | SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); | 486 | SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); |
476 | SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0); | 487 | SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0); |
@@ -530,7 +541,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) | 541 | static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) |
531 | { | 542 | { |
532 | int i; | 543 | int i; |
533 | u16 v, o; | 544 | u16 o; |
534 | u16 pwr_info_offset[] = { | 545 | u16 pwr_info_offset[] = { |
535 | SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, | 546 | SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, |
536 | SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 | 547 | SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 |
@@ -539,11 +550,10 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | |||
539 | ARRAY_SIZE(out->core_pwr_info)); | 550 | ARRAY_SIZE(out->core_pwr_info)); |
540 | 551 | ||
541 | /* extract the MAC address */ | 552 | /* extract the MAC address */ |
542 | for (i = 0; i < 3; i++) { | 553 | sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]); |
543 | v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; | 554 | |
544 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | ||
545 | } | ||
546 | SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); | 555 | SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); |
556 | SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); | ||
547 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); | 557 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); |
548 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); | 558 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); |
549 | SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); | 559 | SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); |
@@ -743,7 +753,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
743 | memset(out, 0, sizeof(*out)); | 753 | memset(out, 0, sizeof(*out)); |
744 | 754 | ||
745 | out->revision = in[size - 1] & 0x00FF; | 755 | out->revision = in[size - 1] & 0x00FF; |
746 | ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); | 756 | ssb_dbg("SPROM revision %d detected\n", out->revision); |
747 | memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ | 757 | memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ |
748 | memset(out->et1mac, 0xFF, 6); | 758 | memset(out->et1mac, 0xFF, 6); |
749 | 759 | ||
@@ -752,7 +762,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
752 | * number stored in the SPROM. | 762 | * number stored in the SPROM. |
753 | * Always extract r1. */ | 763 | * Always extract r1. */ |
754 | out->revision = 1; | 764 | out->revision = 1; |
755 | ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision); | 765 | ssb_dbg("SPROM treated as revision %d\n", out->revision); |
756 | } | 766 | } |
757 | 767 | ||
758 | switch (out->revision) { | 768 | switch (out->revision) { |
@@ -769,9 +779,8 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
769 | sprom_extract_r8(out, in); | 779 | sprom_extract_r8(out, in); |
770 | break; | 780 | break; |
771 | default: | 781 | default: |
772 | ssb_printk(KERN_WARNING PFX "Unsupported SPROM" | 782 | ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n", |
773 | " revision %d detected. Will extract" | 783 | out->revision); |
774 | " v1\n", out->revision); | ||
775 | out->revision = 1; | 784 | out->revision = 1; |
776 | sprom_extract_r123(out, in); | 785 | sprom_extract_r123(out, in); |
777 | } | 786 | } |
@@ -791,7 +800,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
791 | u16 *buf; | 800 | u16 *buf; |
792 | 801 | ||
793 | if (!ssb_is_sprom_available(bus)) { | 802 | if (!ssb_is_sprom_available(bus)) { |
794 | ssb_printk(KERN_ERR PFX "No SPROM available!\n"); | 803 | ssb_err("No SPROM available!\n"); |
795 | return -ENODEV; | 804 | return -ENODEV; |
796 | } | 805 | } |
797 | if (bus->chipco.dev) { /* can be unavailable! */ | 806 | if (bus->chipco.dev) { /* can be unavailable! */ |
@@ -810,7 +819,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
810 | } else { | 819 | } else { |
811 | bus->sprom_offset = SSB_SPROM_BASE1; | 820 | bus->sprom_offset = SSB_SPROM_BASE1; |
812 | } | 821 | } |
813 | ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset); | 822 | ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset); |
814 | 823 | ||
815 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); | 824 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); |
816 | if (!buf) | 825 | if (!buf) |
@@ -835,18 +844,15 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
835 | * available for this device in some other storage */ | 844 | * available for this device in some other storage */ |
836 | err = ssb_fill_sprom_with_fallback(bus, sprom); | 845 | err = ssb_fill_sprom_with_fallback(bus, sprom); |
837 | if (err) { | 846 | if (err) { |
838 | ssb_printk(KERN_WARNING PFX "WARNING: Using" | 847 | ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n", |
839 | " fallback SPROM failed (err %d)\n", | 848 | err); |
840 | err); | ||
841 | } else { | 849 | } else { |
842 | ssb_dprintk(KERN_DEBUG PFX "Using SPROM" | 850 | ssb_dbg("Using SPROM revision %d provided by platform\n", |
843 | " revision %d provided by" | 851 | sprom->revision); |
844 | " platform.\n", sprom->revision); | ||
845 | err = 0; | 852 | err = 0; |
846 | goto out_free; | 853 | goto out_free; |
847 | } | 854 | } |
848 | ssb_printk(KERN_WARNING PFX "WARNING: Invalid" | 855 | ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n"); |
849 | " SPROM CRC (corrupt SPROM)\n"); | ||
850 | } | 856 | } |
851 | } | 857 | } |
852 | err = sprom_extract(bus, sprom, buf, bus->sprom_size); | 858 | 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/bcma/bcma.h b/include/linux/bcma/bcma.h index e0ce311011c0..f14a98a79c9d 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
@@ -134,6 +134,7 @@ struct bcma_host_ops { | |||
134 | #define BCMA_CORE_I2S 0x834 | 134 | #define BCMA_CORE_I2S 0x834 |
135 | #define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */ | 135 | #define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */ |
136 | #define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */ | 136 | #define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */ |
137 | #define BCMA_CORE_ARM_CR4 0x83e | ||
137 | #define BCMA_CORE_DEFAULT 0xFFF | 138 | #define BCMA_CORE_DEFAULT 0xFFF |
138 | 139 | ||
139 | #define BCMA_MAX_NR_CORES 16 | 140 | #define BCMA_MAX_NR_CORES 16 |
@@ -173,6 +174,60 @@ struct bcma_host_ops { | |||
173 | #define BCMA_CHIP_ID_BCM53572 53572 | 174 | #define BCMA_CHIP_ID_BCM53572 53572 |
174 | #define BCMA_PKG_ID_BCM47188 9 | 175 | #define BCMA_PKG_ID_BCM47188 9 |
175 | 176 | ||
177 | /* Board types (on PCI usually equals to the subsystem dev id) */ | ||
178 | /* BCM4313 */ | ||
179 | #define BCMA_BOARD_TYPE_BCM94313BU 0X050F | ||
180 | #define BCMA_BOARD_TYPE_BCM94313HM 0X0510 | ||
181 | #define BCMA_BOARD_TYPE_BCM94313EPA 0X0511 | ||
182 | #define BCMA_BOARD_TYPE_BCM94313HMG 0X051C | ||
183 | /* BCM4716 */ | ||
184 | #define BCMA_BOARD_TYPE_BCM94716NR2 0X04CD | ||
185 | /* BCM43224 */ | ||
186 | #define BCMA_BOARD_TYPE_BCM943224X21 0X056E | ||
187 | #define BCMA_BOARD_TYPE_BCM943224X21_FCC 0X00D1 | ||
188 | #define BCMA_BOARD_TYPE_BCM943224X21B 0X00E9 | ||
189 | #define BCMA_BOARD_TYPE_BCM943224M93 0X008B | ||
190 | #define BCMA_BOARD_TYPE_BCM943224M93A 0X0090 | ||
191 | #define BCMA_BOARD_TYPE_BCM943224X16 0X0093 | ||
192 | #define BCMA_BOARD_TYPE_BCM94322X9 0X008D | ||
193 | #define BCMA_BOARD_TYPE_BCM94322M35E 0X008E | ||
194 | /* BCM43228 */ | ||
195 | #define BCMA_BOARD_TYPE_BCM943228BU8 0X0540 | ||
196 | #define BCMA_BOARD_TYPE_BCM943228BU9 0X0541 | ||
197 | #define BCMA_BOARD_TYPE_BCM943228BU 0X0542 | ||
198 | #define BCMA_BOARD_TYPE_BCM943227HM4L 0X0543 | ||
199 | #define BCMA_BOARD_TYPE_BCM943227HMB 0X0544 | ||
200 | #define BCMA_BOARD_TYPE_BCM943228HM4L 0X0545 | ||
201 | #define BCMA_BOARD_TYPE_BCM943228SD 0X0573 | ||
202 | /* BCM4331 */ | ||
203 | #define BCMA_BOARD_TYPE_BCM94331X19 0X00D6 | ||
204 | #define BCMA_BOARD_TYPE_BCM94331X28 0X00E4 | ||
205 | #define BCMA_BOARD_TYPE_BCM94331X28B 0X010E | ||
206 | #define BCMA_BOARD_TYPE_BCM94331PCIEBT3AX 0X00E4 | ||
207 | #define BCMA_BOARD_TYPE_BCM94331X12_2G 0X00EC | ||
208 | #define BCMA_BOARD_TYPE_BCM94331X12_5G 0X00ED | ||
209 | #define BCMA_BOARD_TYPE_BCM94331X29B 0X00EF | ||
210 | #define BCMA_BOARD_TYPE_BCM94331CSAX 0X00EF | ||
211 | #define BCMA_BOARD_TYPE_BCM94331X19C 0X00F5 | ||
212 | #define BCMA_BOARD_TYPE_BCM94331X33 0X00F4 | ||
213 | #define BCMA_BOARD_TYPE_BCM94331BU 0X0523 | ||
214 | #define BCMA_BOARD_TYPE_BCM94331S9BU 0X0524 | ||
215 | #define BCMA_BOARD_TYPE_BCM94331MC 0X0525 | ||
216 | #define BCMA_BOARD_TYPE_BCM94331MCI 0X0526 | ||
217 | #define BCMA_BOARD_TYPE_BCM94331PCIEBT4 0X0527 | ||
218 | #define BCMA_BOARD_TYPE_BCM94331HM 0X0574 | ||
219 | #define BCMA_BOARD_TYPE_BCM94331PCIEDUAL 0X059B | ||
220 | #define BCMA_BOARD_TYPE_BCM94331MCH5 0X05A9 | ||
221 | #define BCMA_BOARD_TYPE_BCM94331CS 0X05C6 | ||
222 | #define BCMA_BOARD_TYPE_BCM94331CD 0X05DA | ||
223 | /* BCM53572 */ | ||
224 | #define BCMA_BOARD_TYPE_BCM953572BU 0X058D | ||
225 | #define BCMA_BOARD_TYPE_BCM953572NR2 0X058E | ||
226 | #define BCMA_BOARD_TYPE_BCM947188NR2 0X058F | ||
227 | #define BCMA_BOARD_TYPE_BCM953572SDRNR2 0X0590 | ||
228 | /* BCM43142 */ | ||
229 | #define BCMA_BOARD_TYPE_BCM943142HM 0X05E0 | ||
230 | |||
176 | struct bcma_device { | 231 | struct bcma_device { |
177 | struct bcma_bus *bus; | 232 | struct bcma_bus *bus; |
178 | struct bcma_device_id id; | 233 | struct bcma_device_id id; |
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 8390c474f69a..b8b09eac60a4 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
@@ -104,6 +104,7 @@ | |||
104 | #define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */ | 104 | #define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */ |
105 | #define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */ | 105 | #define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */ |
106 | #define BCMA_CC_CHIPST_5357_NAND_BOOT BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */ | 106 | #define BCMA_CC_CHIPST_5357_NAND_BOOT BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */ |
107 | #define BCMA_CC_CHIPST_4360_XTAL_40MZ 0x00000001 | ||
107 | #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ | 108 | #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ |
108 | #define BCMA_CC_JCMD_START 0x80000000 | 109 | #define BCMA_CC_JCMD_START 0x80000000 |
109 | #define BCMA_CC_JCMD_BUSY 0x80000000 | 110 | #define BCMA_CC_JCMD_BUSY 0x80000000 |
@@ -315,6 +316,9 @@ | |||
315 | #define BCMA_CC_PMU_CTL 0x0600 /* PMU control */ | 316 | #define BCMA_CC_PMU_CTL 0x0600 /* PMU control */ |
316 | #define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ | 317 | #define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ |
317 | #define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16 | 318 | #define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16 |
319 | #define BCMA_CC_PMU_CTL_RES 0x00006000 /* reset control mask */ | ||
320 | #define BCMA_CC_PMU_CTL_RES_SHIFT 13 | ||
321 | #define BCMA_CC_PMU_CTL_RES_RELOAD 0x2 /* reload POR values */ | ||
318 | #define BCMA_CC_PMU_CTL_PLL_UPD 0x00000400 | 322 | #define BCMA_CC_PMU_CTL_PLL_UPD 0x00000400 |
319 | #define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ | 323 | #define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ |
320 | #define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ | 324 | #define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ |
@@ -607,6 +611,8 @@ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); | |||
607 | 611 | ||
608 | extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); | 612 | extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); |
609 | 613 | ||
614 | extern u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc); | ||
615 | |||
610 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); | 616 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); |
611 | 617 | ||
612 | u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask); | 618 | u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask); |
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h index 7e8104bb7a7e..917dcd7965e7 100644 --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h | |||
@@ -37,6 +37,7 @@ | |||
37 | #define BCMA_IOST_BIST_DONE 0x8000 | 37 | #define BCMA_IOST_BIST_DONE 0x8000 |
38 | #define BCMA_RESET_CTL 0x0800 | 38 | #define BCMA_RESET_CTL 0x0800 |
39 | #define BCMA_RESET_CTL_RESET 0x0001 | 39 | #define BCMA_RESET_CTL_RESET 0x0001 |
40 | #define BCMA_RESET_ST 0x0804 | ||
40 | 41 | ||
41 | /* BCMA PCI config space registers. */ | 42 | /* BCMA PCI config space registers. */ |
42 | #define BCMA_PCI_PMCSR 0x44 | 43 | #define BCMA_PCI_PMCSR 0x44 |
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/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/platform_data/brcmfmac-sdio.h b/include/linux/platform_data/brcmfmac-sdio.h new file mode 100644 index 000000000000..1ade657d5fc1 --- /dev/null +++ b/include/linux/platform_data/brcmfmac-sdio.h | |||
@@ -0,0 +1,124 @@ | |||
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 | |||
17 | #ifndef _LINUX_BRCMFMAC_PLATFORM_H | ||
18 | #define _LINUX_BRCMFMAC_PLATFORM_H | ||
19 | |||
20 | /* | ||
21 | * Platform specific driver functions and data. Through the platform specific | ||
22 | * device data functions can be provided to help the brcmfmac driver to | ||
23 | * operate with the device in combination with the used platform. | ||
24 | * | ||
25 | * Use the platform data in the following (similar) way: | ||
26 | * | ||
27 | * | ||
28 | #include <brcmfmac_platform.h> | ||
29 | |||
30 | |||
31 | static void brcmfmac_power_on(void) | ||
32 | { | ||
33 | } | ||
34 | |||
35 | static void brcmfmac_power_off(void) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | static void brcmfmac_reset(void) | ||
40 | { | ||
41 | } | ||
42 | |||
43 | static struct brcmfmac_sdio_platform_data brcmfmac_sdio_pdata = { | ||
44 | .power_on = brcmfmac_power_on, | ||
45 | .power_off = brcmfmac_power_off, | ||
46 | .reset = brcmfmac_reset | ||
47 | }; | ||
48 | |||
49 | static struct platform_device brcmfmac_device = { | ||
50 | .name = BRCMFMAC_SDIO_PDATA_NAME, | ||
51 | .id = PLATFORM_DEVID_NONE, | ||
52 | .dev.platform_data = &brcmfmac_sdio_pdata | ||
53 | }; | ||
54 | |||
55 | void __init brcmfmac_init_pdata(void) | ||
56 | { | ||
57 | brcmfmac_sdio_pdata.oob_irq_supported = true; | ||
58 | brcmfmac_sdio_pdata.oob_irq_nr = gpio_to_irq(GPIO_BRCMF_SDIO_OOB); | ||
59 | brcmfmac_sdio_pdata.oob_irq_flags = IORESOURCE_IRQ | | ||
60 | IORESOURCE_IRQ_HIGHLEVEL; | ||
61 | platform_device_register(&brcmfmac_device); | ||
62 | } | ||
63 | * | ||
64 | * | ||
65 | * Note: the brcmfmac can be loaded as module or be statically built-in into | ||
66 | * the kernel. If built-in then do note that it uses module_init (and | ||
67 | * module_exit) routines which equal device_initcall. So if you intend to | ||
68 | * create a module with the platform specific data for the brcmfmac and have | ||
69 | * it built-in to the kernel then use a higher initcall then device_initcall | ||
70 | * (see init.h). If this is not done then brcmfmac will load without problems | ||
71 | * but will not pickup the platform data. | ||
72 | * | ||
73 | * When the driver does not "detect" platform driver data then it will continue | ||
74 | * without reporting anything and just assume there is no data needed. Which is | ||
75 | * probably true for most platforms. | ||
76 | * | ||
77 | * Explanation of the platform_data fields: | ||
78 | * | ||
79 | * drive_strength: is the preferred drive_strength to be used for the SDIO | ||
80 | * pins. If 0 then a default value will be used. This is the target drive | ||
81 | * strength, the exact drive strength which will be used depends on the | ||
82 | * capabilities of the device. | ||
83 | * | ||
84 | * oob_irq_supported: does the board have support for OOB interrupts. SDIO | ||
85 | * in-band interrupts are relatively slow and for having less overhead on | ||
86 | * interrupt processing an out of band interrupt can be used. If the HW | ||
87 | * supports this then enable this by setting this field to true and configure | ||
88 | * the oob related fields. | ||
89 | * | ||
90 | * oob_irq_nr, oob_irq_flags: the OOB interrupt information. The values are | ||
91 | * used for registering the irq using request_irq function. | ||
92 | * | ||
93 | * power_on: This function is called by the brcmfmac when the module gets | ||
94 | * loaded. This can be particularly useful for low power devices. The platform | ||
95 | * spcific routine may for example decide to power up the complete device. | ||
96 | * If there is no use-case for this function then provide NULL. | ||
97 | * | ||
98 | * power_off: This function is called by the brcmfmac when the module gets | ||
99 | * unloaded. At this point the device can be powered down or otherwise be reset. | ||
100 | * So if an actual power_off is not supported but reset is then reset the device | ||
101 | * when this function gets called. This can be particularly useful for low power | ||
102 | * devices. If there is no use-case for this function (either power-down or | ||
103 | * reset) then provide NULL. | ||
104 | * | ||
105 | * reset: This function can get called if the device communication broke down. | ||
106 | * This functionality is particularly useful in case of SDIO type devices. It is | ||
107 | * possible to reset a dongle via sdio data interface, but it requires that | ||
108 | * this is fully functional. This function is chip/module specific and this | ||
109 | * function should return only after the complete reset has completed. | ||
110 | */ | ||
111 | |||
112 | #define BRCMFMAC_SDIO_PDATA_NAME "brcmfmac_sdio" | ||
113 | |||
114 | struct brcmfmac_sdio_platform_data { | ||
115 | unsigned int drive_strength; | ||
116 | bool oob_irq_supported; | ||
117 | unsigned int oob_irq_nr; | ||
118 | unsigned long oob_irq_flags; | ||
119 | void (*power_on)(void); | ||
120 | void (*power_off)(void); | ||
121 | void (*reset)(void); | ||
122 | }; | ||
123 | |||
124 | #endif /* _LINUX_BRCMFMAC_PLATFORM_H */ | ||
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..c64999fd1660 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 */ |
@@ -340,13 +340,61 @@ enum ssb_bustype { | |||
340 | #define SSB_BOARDVENDOR_DELL 0x1028 /* Dell */ | 340 | #define SSB_BOARDVENDOR_DELL 0x1028 /* Dell */ |
341 | #define SSB_BOARDVENDOR_HP 0x0E11 /* HP */ | 341 | #define SSB_BOARDVENDOR_HP 0x0E11 /* HP */ |
342 | /* board_type */ | 342 | /* board_type */ |
343 | #define SSB_BOARD_BCM94301CB 0x0406 | ||
344 | #define SSB_BOARD_BCM94301MP 0x0407 | ||
345 | #define SSB_BOARD_BU4309 0x040A | ||
346 | #define SSB_BOARD_BCM94309CB 0x040B | ||
347 | #define SSB_BOARD_BCM4309MP 0x040C | ||
348 | #define SSB_BOARD_BU4306 0x0416 | ||
343 | #define SSB_BOARD_BCM94306MP 0x0418 | 349 | #define SSB_BOARD_BCM94306MP 0x0418 |
344 | #define SSB_BOARD_BCM4309G 0x0421 | 350 | #define SSB_BOARD_BCM4309G 0x0421 |
345 | #define SSB_BOARD_BCM4306CB 0x0417 | 351 | #define SSB_BOARD_BCM4306CB 0x0417 |
346 | #define SSB_BOARD_BCM4309MP 0x040C | 352 | #define SSB_BOARD_BCM94306PC 0x0425 /* pcmcia 3.3v 4306 card */ |
353 | #define SSB_BOARD_BCM94306CBSG 0x042B /* with SiGe PA */ | ||
354 | #define SSB_BOARD_PCSG94306 0x042D /* with SiGe PA */ | ||
355 | #define SSB_BOARD_BU4704SD 0x042E /* with sdram */ | ||
356 | #define SSB_BOARD_BCM94704AGR 0x042F /* dual 11a/11g Router */ | ||
357 | #define SSB_BOARD_BCM94308MP 0x0430 /* 11a-only minipci */ | ||
358 | #define SSB_BOARD_BU4318 0x0447 | ||
359 | #define SSB_BOARD_CB4318 0x0448 | ||
360 | #define SSB_BOARD_MPG4318 0x0449 | ||
347 | #define SSB_BOARD_MP4318 0x044A | 361 | #define SSB_BOARD_MP4318 0x044A |
348 | #define SSB_BOARD_BU4306 0x0416 | 362 | #define SSB_BOARD_SD4318 0x044B |
349 | #define SSB_BOARD_BU4309 0x040A | 363 | #define SSB_BOARD_BCM94306P 0x044C /* with SiGe */ |
364 | #define SSB_BOARD_BCM94303MP 0x044E | ||
365 | #define SSB_BOARD_BCM94306MPM 0x0450 | ||
366 | #define SSB_BOARD_BCM94306MPL 0x0453 | ||
367 | #define SSB_BOARD_PC4303 0x0454 /* pcmcia */ | ||
368 | #define SSB_BOARD_BCM94306MPLNA 0x0457 | ||
369 | #define SSB_BOARD_BCM94306MPH 0x045B | ||
370 | #define SSB_BOARD_BCM94306PCIV 0x045C | ||
371 | #define SSB_BOARD_BCM94318MPGH 0x0463 | ||
372 | #define SSB_BOARD_BU4311 0x0464 | ||
373 | #define SSB_BOARD_BCM94311MC 0x0465 | ||
374 | #define SSB_BOARD_BCM94311MCAG 0x0466 | ||
375 | /* 4321 boards */ | ||
376 | #define SSB_BOARD_BU4321 0x046B | ||
377 | #define SSB_BOARD_BU4321E 0x047C | ||
378 | #define SSB_BOARD_MP4321 0x046C | ||
379 | #define SSB_BOARD_CB2_4321 0x046D | ||
380 | #define SSB_BOARD_CB2_4321_AG 0x0066 | ||
381 | #define SSB_BOARD_MC4321 0x046E | ||
382 | /* 4325 boards */ | ||
383 | #define SSB_BOARD_BCM94325DEVBU 0x0490 | ||
384 | #define SSB_BOARD_BCM94325BGABU 0x0491 | ||
385 | #define SSB_BOARD_BCM94325SDGWB 0x0492 | ||
386 | #define SSB_BOARD_BCM94325SDGMDL 0x04AA | ||
387 | #define SSB_BOARD_BCM94325SDGMDL2 0x04C6 | ||
388 | #define SSB_BOARD_BCM94325SDGMDL3 0x04C9 | ||
389 | #define SSB_BOARD_BCM94325SDABGWBA 0x04E1 | ||
390 | /* 4322 boards */ | ||
391 | #define SSB_BOARD_BCM94322MC 0x04A4 | ||
392 | #define SSB_BOARD_BCM94322USB 0x04A8 /* dualband */ | ||
393 | #define SSB_BOARD_BCM94322HM 0x04B0 | ||
394 | #define SSB_BOARD_BCM94322USB2D 0x04Bf /* single band discrete front end */ | ||
395 | /* 4312 boards */ | ||
396 | #define SSB_BOARD_BU4312 0x048A | ||
397 | #define SSB_BOARD_BCM4312MCGSG 0x04B5 | ||
350 | /* chip_package */ | 398 | /* chip_package */ |
351 | #define SSB_CHIPPACK_BCM4712S 1 /* Small 200pin 4712 */ | 399 | #define SSB_CHIPPACK_BCM4712S 1 /* Small 200pin 4712 */ |
352 | #define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */ | 400 | #define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */ |
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index 6ecfa02ddbac..3a7256955b10 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h | |||
@@ -289,11 +289,11 @@ | |||
289 | #define SSB_SPROM4_ETHPHY_ET1A_SHIFT 5 | 289 | #define SSB_SPROM4_ETHPHY_ET1A_SHIFT 5 |
290 | #define SSB_SPROM4_ETHPHY_ET0M (1<<14) /* MDIO for enet0 */ | 290 | #define SSB_SPROM4_ETHPHY_ET0M (1<<14) /* MDIO for enet0 */ |
291 | #define SSB_SPROM4_ETHPHY_ET1M (1<<15) /* MDIO for enet1 */ | 291 | #define SSB_SPROM4_ETHPHY_ET1M (1<<15) /* MDIO for enet1 */ |
292 | #define SSB_SPROM4_ANTAVAIL 0x005D /* Antenna available bitfields */ | 292 | #define SSB_SPROM4_ANTAVAIL 0x005C /* Antenna available bitfields */ |
293 | #define SSB_SPROM4_ANTAVAIL_A 0x00FF /* A-PHY bitfield */ | 293 | #define SSB_SPROM4_ANTAVAIL_BG 0x00FF /* B-PHY and G-PHY bitfield */ |
294 | #define SSB_SPROM4_ANTAVAIL_A_SHIFT 0 | 294 | #define SSB_SPROM4_ANTAVAIL_BG_SHIFT 0 |
295 | #define SSB_SPROM4_ANTAVAIL_BG 0xFF00 /* B-PHY and G-PHY bitfield */ | 295 | #define SSB_SPROM4_ANTAVAIL_A 0xFF00 /* A-PHY bitfield */ |
296 | #define SSB_SPROM4_ANTAVAIL_BG_SHIFT 8 | 296 | #define SSB_SPROM4_ANTAVAIL_A_SHIFT 8 |
297 | #define SSB_SPROM4_AGAIN01 0x005E /* Antenna Gain (in dBm Q5.2) */ | 297 | #define SSB_SPROM4_AGAIN01 0x005E /* Antenna Gain (in dBm Q5.2) */ |
298 | #define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */ | 298 | #define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */ |
299 | #define SSB_SPROM4_AGAIN0_SHIFT 0 | 299 | #define SSB_SPROM4_AGAIN0_SHIFT 0 |
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 9531beee09b5..ed6e9552252e 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
@@ -232,7 +232,7 @@ struct bt_sock_list { | |||
232 | }; | 232 | }; |
233 | 233 | ||
234 | int bt_sock_register(int proto, const struct net_proto_family *ops); | 234 | int bt_sock_register(int proto, const struct net_proto_family *ops); |
235 | int bt_sock_unregister(int proto); | 235 | void bt_sock_unregister(int proto); |
236 | void bt_sock_link(struct bt_sock_list *l, struct sock *s); | 236 | void bt_sock_link(struct bt_sock_list *l, struct sock *s); |
237 | void bt_sock_unlink(struct bt_sock_list *l, struct sock *s); | 237 | void bt_sock_unlink(struct bt_sock_list *l, struct sock *s); |
238 | int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | 238 | int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, |
@@ -260,12 +260,22 @@ struct l2cap_ctrl { | |||
260 | __u8 retries; | 260 | __u8 retries; |
261 | }; | 261 | }; |
262 | 262 | ||
263 | struct hci_dev; | ||
264 | |||
265 | typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status); | ||
266 | |||
267 | struct hci_req_ctrl { | ||
268 | bool start; | ||
269 | hci_req_complete_t complete; | ||
270 | }; | ||
271 | |||
263 | struct bt_skb_cb { | 272 | struct bt_skb_cb { |
264 | __u8 pkt_type; | 273 | __u8 pkt_type; |
265 | __u8 incoming; | 274 | __u8 incoming; |
266 | __u16 expect; | 275 | __u16 expect; |
267 | __u8 force_active; | 276 | __u8 force_active; |
268 | struct l2cap_ctrl control; | 277 | struct l2cap_ctrl control; |
278 | struct hci_req_ctrl req; | ||
269 | }; | 279 | }; |
270 | #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) | 280 | #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) |
271 | 281 | ||
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 7f12c25f1fca..b3308927a0a1 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -119,10 +119,16 @@ enum { | |||
119 | HCI_CONNECTABLE, | 119 | HCI_CONNECTABLE, |
120 | HCI_DISCOVERABLE, | 120 | HCI_DISCOVERABLE, |
121 | HCI_LINK_SECURITY, | 121 | HCI_LINK_SECURITY, |
122 | HCI_PENDING_CLASS, | ||
123 | HCI_PERIODIC_INQ, | 122 | HCI_PERIODIC_INQ, |
123 | HCI_FAST_CONNECTABLE, | ||
124 | }; | 124 | }; |
125 | 125 | ||
126 | /* A mask for the flags that are supposed to remain when a reset happens | ||
127 | * or the HCI device is closed. | ||
128 | */ | ||
129 | #define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \ | ||
130 | BIT(HCI_FAST_CONNECTABLE)) | ||
131 | |||
126 | /* HCI ioctl defines */ | 132 | /* HCI ioctl defines */ |
127 | #define HCIDEVUP _IOW('H', 201, int) | 133 | #define HCIDEVUP _IOW('H', 201, int) |
128 | #define HCIDEVDOWN _IOW('H', 202, int) | 134 | #define HCIDEVDOWN _IOW('H', 202, int) |
@@ -881,12 +887,25 @@ struct hci_rp_read_data_block_size { | |||
881 | __le16 num_blocks; | 887 | __le16 num_blocks; |
882 | } __packed; | 888 | } __packed; |
883 | 889 | ||
890 | #define HCI_OP_READ_PAGE_SCAN_ACTIVITY 0x0c1b | ||
891 | struct hci_rp_read_page_scan_activity { | ||
892 | __u8 status; | ||
893 | __le16 interval; | ||
894 | __le16 window; | ||
895 | } __packed; | ||
896 | |||
884 | #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c | 897 | #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c |
885 | struct hci_cp_write_page_scan_activity { | 898 | struct hci_cp_write_page_scan_activity { |
886 | __le16 interval; | 899 | __le16 interval; |
887 | __le16 window; | 900 | __le16 window; |
888 | } __packed; | 901 | } __packed; |
889 | 902 | ||
903 | #define HCI_OP_READ_PAGE_SCAN_TYPE 0x0c46 | ||
904 | struct hci_rp_read_page_scan_type { | ||
905 | __u8 status; | ||
906 | __u8 type; | ||
907 | } __packed; | ||
908 | |||
890 | #define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47 | 909 | #define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47 |
891 | #define PAGE_SCAN_TYPE_STANDARD 0x00 | 910 | #define PAGE_SCAN_TYPE_STANDARD 0x00 |
892 | #define PAGE_SCAN_TYPE_INTERLACED 0x01 | 911 | #define PAGE_SCAN_TYPE_INTERLACED 0x01 |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 90cf75afcb02..358a6983d3bb 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -165,6 +165,10 @@ struct hci_dev { | |||
165 | __u16 voice_setting; | 165 | __u16 voice_setting; |
166 | __u8 io_capability; | 166 | __u8 io_capability; |
167 | __s8 inq_tx_power; | 167 | __s8 inq_tx_power; |
168 | __u16 page_scan_interval; | ||
169 | __u16 page_scan_window; | ||
170 | __u8 page_scan_type; | ||
171 | |||
168 | __u16 devid_source; | 172 | __u16 devid_source; |
169 | __u16 devid_vendor; | 173 | __u16 devid_vendor; |
170 | __u16 devid_product; | 174 | __u16 devid_product; |
@@ -248,8 +252,6 @@ struct hci_dev { | |||
248 | __u32 req_status; | 252 | __u32 req_status; |
249 | __u32 req_result; | 253 | __u32 req_result; |
250 | 254 | ||
251 | __u16 init_last_cmd; | ||
252 | |||
253 | struct list_head mgmt_pending; | 255 | struct list_head mgmt_pending; |
254 | 256 | ||
255 | struct discovery_state discovery; | 257 | struct discovery_state discovery; |
@@ -574,7 +576,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, | |||
574 | return NULL; | 576 | return NULL; |
575 | } | 577 | } |
576 | 578 | ||
577 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason); | 579 | void hci_disconnect(struct hci_conn *conn, __u8 reason); |
578 | void hci_setup_sync(struct hci_conn *conn, __u16 handle); | 580 | void hci_setup_sync(struct hci_conn *conn, __u16 handle); |
579 | void hci_sco_setup(struct hci_conn *conn, __u8 status); | 581 | void hci_sco_setup(struct hci_conn *conn, __u8 status); |
580 | 582 | ||
@@ -742,8 +744,6 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, | |||
742 | u8 *randomizer); | 744 | u8 *randomizer); |
743 | int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); | 745 | int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); |
744 | 746 | ||
745 | int hci_update_ad(struct hci_dev *hdev); | ||
746 | |||
747 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); | 747 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); |
748 | 748 | ||
749 | int hci_recv_frame(struct sk_buff *skb); | 749 | int hci_recv_frame(struct sk_buff *skb); |
@@ -1041,6 +1041,22 @@ static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, | |||
1041 | int hci_register_cb(struct hci_cb *hcb); | 1041 | int hci_register_cb(struct hci_cb *hcb); |
1042 | int hci_unregister_cb(struct hci_cb *hcb); | 1042 | int hci_unregister_cb(struct hci_cb *hcb); |
1043 | 1043 | ||
1044 | struct hci_request { | ||
1045 | struct hci_dev *hdev; | ||
1046 | struct sk_buff_head cmd_q; | ||
1047 | |||
1048 | /* If something goes wrong when building the HCI request, the error | ||
1049 | * value is stored in this field. | ||
1050 | */ | ||
1051 | int err; | ||
1052 | }; | ||
1053 | |||
1054 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev); | ||
1055 | int hci_req_run(struct hci_request *req, hci_req_complete_t complete); | ||
1056 | void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param); | ||
1057 | void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status); | ||
1058 | void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status); | ||
1059 | |||
1044 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); | 1060 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); |
1045 | void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags); | 1061 | void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags); |
1046 | void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); | 1062 | void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); |
@@ -1153,7 +1169,7 @@ struct hci_sec_filter { | |||
1153 | #define hci_req_lock(d) mutex_lock(&d->req_lock) | 1169 | #define hci_req_lock(d) mutex_lock(&d->req_lock) |
1154 | #define hci_req_unlock(d) mutex_unlock(&d->req_lock) | 1170 | #define hci_req_unlock(d) mutex_unlock(&d->req_lock) |
1155 | 1171 | ||
1156 | void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result); | 1172 | void hci_update_ad(struct hci_request *req); |
1157 | 1173 | ||
1158 | void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, | 1174 | void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, |
1159 | u16 latency, u16 to_multiplier); | 1175 | u16 latency, u16 to_multiplier); |
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index e2e3ecad1008..7afd4199d6b6 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h | |||
@@ -158,7 +158,6 @@ struct rfcomm_session { | |||
158 | struct timer_list timer; | 158 | struct timer_list timer; |
159 | unsigned long state; | 159 | unsigned long state; |
160 | unsigned long flags; | 160 | unsigned long flags; |
161 | atomic_t refcnt; | ||
162 | int initiator; | 161 | int initiator; |
163 | 162 | ||
164 | /* Default DLC parameters */ | 163 | /* Default DLC parameters */ |
@@ -276,11 +275,6 @@ static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d) | |||
276 | void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, | 275 | void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, |
277 | bdaddr_t *dst); | 276 | bdaddr_t *dst); |
278 | 277 | ||
279 | static inline void rfcomm_session_hold(struct rfcomm_session *s) | ||
280 | { | ||
281 | atomic_inc(&s->refcnt); | ||
282 | } | ||
283 | |||
284 | /* ---- RFCOMM sockets ---- */ | 278 | /* ---- RFCOMM sockets ---- */ |
285 | struct sockaddr_rc { | 279 | struct sockaddr_rc { |
286 | sa_family_t rc_family; | 280 | sa_family_t rc_family; |
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/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/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index eb0f4b16ff09..17f33a62f6db 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -397,13 +397,12 @@ static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |||
397 | if (ctrl) { | 397 | if (ctrl) { |
398 | u8 *assoc; | 398 | u8 *assoc; |
399 | 399 | ||
400 | assoc = kzalloc(assoc_len, GFP_KERNEL); | 400 | assoc = kmemdup(rsp->amp_assoc, assoc_len, GFP_KERNEL); |
401 | if (!assoc) { | 401 | if (!assoc) { |
402 | amp_ctrl_put(ctrl); | 402 | amp_ctrl_put(ctrl); |
403 | return -ENOMEM; | 403 | return -ENOMEM; |
404 | } | 404 | } |
405 | 405 | ||
406 | memcpy(assoc, rsp->amp_assoc, assoc_len); | ||
407 | ctrl->assoc = assoc; | 406 | ctrl->assoc = assoc; |
408 | ctrl->assoc_len = assoc_len; | 407 | ctrl->assoc_len = assoc_len; |
409 | ctrl->assoc_rem_len = assoc_len; | 408 | ctrl->assoc_rem_len = assoc_len; |
@@ -472,13 +471,12 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
472 | size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req); | 471 | size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req); |
473 | u8 *assoc; | 472 | u8 *assoc; |
474 | 473 | ||
475 | assoc = kzalloc(assoc_len, GFP_KERNEL); | 474 | assoc = kmemdup(req->amp_assoc, assoc_len, GFP_KERNEL); |
476 | if (!assoc) { | 475 | if (!assoc) { |
477 | amp_ctrl_put(ctrl); | 476 | amp_ctrl_put(ctrl); |
478 | return -ENOMEM; | 477 | return -ENOMEM; |
479 | } | 478 | } |
480 | 479 | ||
481 | memcpy(assoc, req->amp_assoc, assoc_len); | ||
482 | ctrl->assoc = assoc; | 480 | ctrl->assoc = assoc; |
483 | ctrl->assoc_len = assoc_len; | 481 | ctrl->assoc_len = assoc_len; |
484 | ctrl->assoc_rem_len = assoc_len; | 482 | ctrl->assoc_rem_len = assoc_len; |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index d3ee69b35a78..81598e588f7f 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -92,23 +92,14 @@ int bt_sock_register(int proto, const struct net_proto_family *ops) | |||
92 | } | 92 | } |
93 | EXPORT_SYMBOL(bt_sock_register); | 93 | EXPORT_SYMBOL(bt_sock_register); |
94 | 94 | ||
95 | int bt_sock_unregister(int proto) | 95 | void bt_sock_unregister(int proto) |
96 | { | 96 | { |
97 | int err = 0; | ||
98 | |||
99 | if (proto < 0 || proto >= BT_MAX_PROTO) | 97 | if (proto < 0 || proto >= BT_MAX_PROTO) |
100 | return -EINVAL; | 98 | return; |
101 | 99 | ||
102 | write_lock(&bt_proto_lock); | 100 | write_lock(&bt_proto_lock); |
103 | 101 | bt_proto[proto] = NULL; | |
104 | if (!bt_proto[proto]) | ||
105 | err = -ENOENT; | ||
106 | else | ||
107 | bt_proto[proto] = NULL; | ||
108 | |||
109 | write_unlock(&bt_proto_lock); | 102 | write_unlock(&bt_proto_lock); |
110 | |||
111 | return err; | ||
112 | } | 103 | } |
113 | EXPORT_SYMBOL(bt_sock_unregister); | 104 | EXPORT_SYMBOL(bt_sock_unregister); |
114 | 105 | ||
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index e7154a58465f..5b1c04e28821 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c | |||
@@ -253,8 +253,6 @@ error: | |||
253 | void __exit bnep_sock_cleanup(void) | 253 | void __exit bnep_sock_cleanup(void) |
254 | { | 254 | { |
255 | bt_procfs_cleanup(&init_net, "bnep"); | 255 | bt_procfs_cleanup(&init_net, "bnep"); |
256 | if (bt_sock_unregister(BTPROTO_BNEP) < 0) | 256 | bt_sock_unregister(BTPROTO_BNEP); |
257 | BT_ERR("Can't unregister BNEP socket"); | ||
258 | |||
259 | proto_unregister(&bnep_proto); | 257 | proto_unregister(&bnep_proto); |
260 | } | 258 | } |
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 1c57482112b6..58d9edebab4b 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c | |||
@@ -264,8 +264,6 @@ error: | |||
264 | void cmtp_cleanup_sockets(void) | 264 | void cmtp_cleanup_sockets(void) |
265 | { | 265 | { |
266 | bt_procfs_cleanup(&init_net, "cmtp"); | 266 | bt_procfs_cleanup(&init_net, "cmtp"); |
267 | if (bt_sock_unregister(BTPROTO_CMTP) < 0) | 267 | bt_sock_unregister(BTPROTO_CMTP); |
268 | BT_ERR("Can't unregister CMTP socket"); | ||
269 | |||
270 | proto_unregister(&cmtp_proto); | 268 | proto_unregister(&cmtp_proto); |
271 | } | 269 | } |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 4925a02ae7e4..b9f90169940b 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -117,7 +117,7 @@ static void hci_acl_create_connection_cancel(struct hci_conn *conn) | |||
117 | hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp); | 117 | hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp); |
118 | } | 118 | } |
119 | 119 | ||
120 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason) | 120 | void hci_disconnect(struct hci_conn *conn, __u8 reason) |
121 | { | 121 | { |
122 | struct hci_cp_disconnect cp; | 122 | struct hci_cp_disconnect cp; |
123 | 123 | ||
@@ -253,7 +253,7 @@ static void hci_conn_disconnect(struct hci_conn *conn) | |||
253 | hci_amp_disconn(conn, reason); | 253 | hci_amp_disconn(conn, reason); |
254 | break; | 254 | break; |
255 | default: | 255 | default: |
256 | hci_acl_disconn(conn, reason); | 256 | hci_disconnect(conn, reason); |
257 | break; | 257 | break; |
258 | } | 258 | } |
259 | } | 259 | } |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 60793e7b768b..cfcad5423f1c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -57,36 +57,9 @@ static void hci_notify(struct hci_dev *hdev, int event) | |||
57 | 57 | ||
58 | /* ---- HCI requests ---- */ | 58 | /* ---- HCI requests ---- */ |
59 | 59 | ||
60 | void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result) | 60 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) |
61 | { | 61 | { |
62 | BT_DBG("%s command 0x%4.4x result 0x%2.2x", hdev->name, cmd, result); | 62 | BT_DBG("%s result 0x%2.2x", hdev->name, result); |
63 | |||
64 | /* If this is the init phase check if the completed command matches | ||
65 | * the last init command, and if not just return. | ||
66 | */ | ||
67 | if (test_bit(HCI_INIT, &hdev->flags) && hdev->init_last_cmd != cmd) { | ||
68 | struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data; | ||
69 | u16 opcode = __le16_to_cpu(sent->opcode); | ||
70 | struct sk_buff *skb; | ||
71 | |||
72 | /* Some CSR based controllers generate a spontaneous | ||
73 | * reset complete event during init and any pending | ||
74 | * command will never be completed. In such a case we | ||
75 | * need to resend whatever was the last sent | ||
76 | * command. | ||
77 | */ | ||
78 | |||
79 | if (cmd != HCI_OP_RESET || opcode == HCI_OP_RESET) | ||
80 | return; | ||
81 | |||
82 | skb = skb_clone(hdev->sent_cmd, GFP_ATOMIC); | ||
83 | if (skb) { | ||
84 | skb_queue_head(&hdev->cmd_q, skb); | ||
85 | queue_work(hdev->workqueue, &hdev->cmd_work); | ||
86 | } | ||
87 | |||
88 | return; | ||
89 | } | ||
90 | 63 | ||
91 | if (hdev->req_status == HCI_REQ_PEND) { | 64 | if (hdev->req_status == HCI_REQ_PEND) { |
92 | hdev->req_result = result; | 65 | hdev->req_result = result; |
@@ -107,21 +80,41 @@ static void hci_req_cancel(struct hci_dev *hdev, int err) | |||
107 | } | 80 | } |
108 | 81 | ||
109 | /* Execute request and wait for completion. */ | 82 | /* Execute request and wait for completion. */ |
110 | static int __hci_request(struct hci_dev *hdev, | 83 | static int __hci_req_sync(struct hci_dev *hdev, |
111 | void (*req)(struct hci_dev *hdev, unsigned long opt), | 84 | void (*func)(struct hci_request *req, |
112 | unsigned long opt, __u32 timeout) | 85 | unsigned long opt), |
86 | unsigned long opt, __u32 timeout) | ||
113 | { | 87 | { |
88 | struct hci_request req; | ||
114 | DECLARE_WAITQUEUE(wait, current); | 89 | DECLARE_WAITQUEUE(wait, current); |
115 | int err = 0; | 90 | int err = 0; |
116 | 91 | ||
117 | BT_DBG("%s start", hdev->name); | 92 | BT_DBG("%s start", hdev->name); |
118 | 93 | ||
94 | hci_req_init(&req, hdev); | ||
95 | |||
119 | hdev->req_status = HCI_REQ_PEND; | 96 | hdev->req_status = HCI_REQ_PEND; |
120 | 97 | ||
98 | func(&req, opt); | ||
99 | |||
100 | err = hci_req_run(&req, hci_req_sync_complete); | ||
101 | if (err < 0) { | ||
102 | hdev->req_status = 0; | ||
103 | |||
104 | /* ENODATA means the HCI request command queue is empty. | ||
105 | * This can happen when a request with conditionals doesn't | ||
106 | * trigger any commands to be sent. This is normal behavior | ||
107 | * and should not trigger an error return. | ||
108 | */ | ||
109 | if (err == -ENODATA) | ||
110 | return 0; | ||
111 | |||
112 | return err; | ||
113 | } | ||
114 | |||
121 | add_wait_queue(&hdev->req_wait_q, &wait); | 115 | add_wait_queue(&hdev->req_wait_q, &wait); |
122 | set_current_state(TASK_INTERRUPTIBLE); | 116 | set_current_state(TASK_INTERRUPTIBLE); |
123 | 117 | ||
124 | req(hdev, opt); | ||
125 | schedule_timeout(timeout); | 118 | schedule_timeout(timeout); |
126 | 119 | ||
127 | remove_wait_queue(&hdev->req_wait_q, &wait); | 120 | remove_wait_queue(&hdev->req_wait_q, &wait); |
@@ -150,9 +143,10 @@ static int __hci_request(struct hci_dev *hdev, | |||
150 | return err; | 143 | return err; |
151 | } | 144 | } |
152 | 145 | ||
153 | static int hci_request(struct hci_dev *hdev, | 146 | static int hci_req_sync(struct hci_dev *hdev, |
154 | void (*req)(struct hci_dev *hdev, unsigned long opt), | 147 | void (*req)(struct hci_request *req, |
155 | unsigned long opt, __u32 timeout) | 148 | unsigned long opt), |
149 | unsigned long opt, __u32 timeout) | ||
156 | { | 150 | { |
157 | int ret; | 151 | int ret; |
158 | 152 | ||
@@ -161,75 +155,86 @@ static int hci_request(struct hci_dev *hdev, | |||
161 | 155 | ||
162 | /* Serialize all requests */ | 156 | /* Serialize all requests */ |
163 | hci_req_lock(hdev); | 157 | hci_req_lock(hdev); |
164 | ret = __hci_request(hdev, req, opt, timeout); | 158 | ret = __hci_req_sync(hdev, req, opt, timeout); |
165 | hci_req_unlock(hdev); | 159 | hci_req_unlock(hdev); |
166 | 160 | ||
167 | return ret; | 161 | return ret; |
168 | } | 162 | } |
169 | 163 | ||
170 | static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) | 164 | static void hci_reset_req(struct hci_request *req, unsigned long opt) |
171 | { | 165 | { |
172 | BT_DBG("%s %ld", hdev->name, opt); | 166 | BT_DBG("%s %ld", req->hdev->name, opt); |
173 | 167 | ||
174 | /* Reset device */ | 168 | /* Reset device */ |
175 | set_bit(HCI_RESET, &hdev->flags); | 169 | set_bit(HCI_RESET, &req->hdev->flags); |
176 | hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); | 170 | hci_req_add(req, HCI_OP_RESET, 0, NULL); |
177 | } | 171 | } |
178 | 172 | ||
179 | static void bredr_init(struct hci_dev *hdev) | 173 | static void bredr_init(struct hci_request *req) |
180 | { | 174 | { |
181 | hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; | 175 | req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; |
182 | 176 | ||
183 | /* Read Local Supported Features */ | 177 | /* Read Local Supported Features */ |
184 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); | 178 | hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); |
185 | 179 | ||
186 | /* Read Local Version */ | 180 | /* Read Local Version */ |
187 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL); | 181 | hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); |
182 | |||
183 | /* Read BD Address */ | ||
184 | hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL); | ||
188 | } | 185 | } |
189 | 186 | ||
190 | static void amp_init(struct hci_dev *hdev) | 187 | static void amp_init(struct hci_request *req) |
191 | { | 188 | { |
192 | hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED; | 189 | req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED; |
193 | 190 | ||
194 | /* Read Local Version */ | 191 | /* Read Local Version */ |
195 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL); | 192 | hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); |
196 | 193 | ||
197 | /* Read Local AMP Info */ | 194 | /* Read Local AMP Info */ |
198 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); | 195 | hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); |
199 | 196 | ||
200 | /* Read Data Blk size */ | 197 | /* Read Data Blk size */ |
201 | hci_send_cmd(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); | 198 | hci_req_add(req, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); |
202 | } | 199 | } |
203 | 200 | ||
204 | static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | 201 | static void hci_init1_req(struct hci_request *req, unsigned long opt) |
205 | { | 202 | { |
203 | struct hci_dev *hdev = req->hdev; | ||
204 | struct hci_request init_req; | ||
206 | struct sk_buff *skb; | 205 | struct sk_buff *skb; |
207 | 206 | ||
208 | BT_DBG("%s %ld", hdev->name, opt); | 207 | BT_DBG("%s %ld", hdev->name, opt); |
209 | 208 | ||
210 | /* Driver initialization */ | 209 | /* Driver initialization */ |
211 | 210 | ||
211 | hci_req_init(&init_req, hdev); | ||
212 | |||
212 | /* Special commands */ | 213 | /* Special commands */ |
213 | while ((skb = skb_dequeue(&hdev->driver_init))) { | 214 | while ((skb = skb_dequeue(&hdev->driver_init))) { |
214 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; | 215 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; |
215 | skb->dev = (void *) hdev; | 216 | skb->dev = (void *) hdev; |
216 | 217 | ||
217 | skb_queue_tail(&hdev->cmd_q, skb); | 218 | if (skb_queue_empty(&init_req.cmd_q)) |
218 | queue_work(hdev->workqueue, &hdev->cmd_work); | 219 | bt_cb(skb)->req.start = true; |
220 | |||
221 | skb_queue_tail(&init_req.cmd_q, skb); | ||
219 | } | 222 | } |
220 | skb_queue_purge(&hdev->driver_init); | 223 | skb_queue_purge(&hdev->driver_init); |
221 | 224 | ||
225 | hci_req_run(&init_req, NULL); | ||
226 | |||
222 | /* Reset */ | 227 | /* Reset */ |
223 | if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) | 228 | if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) |
224 | hci_reset_req(hdev, 0); | 229 | hci_reset_req(req, 0); |
225 | 230 | ||
226 | switch (hdev->dev_type) { | 231 | switch (hdev->dev_type) { |
227 | case HCI_BREDR: | 232 | case HCI_BREDR: |
228 | bredr_init(hdev); | 233 | bredr_init(req); |
229 | break; | 234 | break; |
230 | 235 | ||
231 | case HCI_AMP: | 236 | case HCI_AMP: |
232 | amp_init(hdev); | 237 | amp_init(req); |
233 | break; | 238 | break; |
234 | 239 | ||
235 | default: | 240 | default: |
@@ -238,44 +243,327 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | |||
238 | } | 243 | } |
239 | } | 244 | } |
240 | 245 | ||
241 | static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) | 246 | static void bredr_setup(struct hci_request *req) |
247 | { | ||
248 | struct hci_cp_delete_stored_link_key cp; | ||
249 | __le16 param; | ||
250 | __u8 flt_type; | ||
251 | |||
252 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | ||
253 | hci_req_add(req, HCI_OP_READ_BUFFER_SIZE, 0, NULL); | ||
254 | |||
255 | /* Read Class of Device */ | ||
256 | hci_req_add(req, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); | ||
257 | |||
258 | /* Read Local Name */ | ||
259 | hci_req_add(req, HCI_OP_READ_LOCAL_NAME, 0, NULL); | ||
260 | |||
261 | /* Read Voice Setting */ | ||
262 | hci_req_add(req, HCI_OP_READ_VOICE_SETTING, 0, NULL); | ||
263 | |||
264 | /* Clear Event Filters */ | ||
265 | flt_type = HCI_FLT_CLEAR_ALL; | ||
266 | hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | ||
267 | |||
268 | /* Connection accept timeout ~20 secs */ | ||
269 | param = __constant_cpu_to_le16(0x7d00); | ||
270 | hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | ||
271 | |||
272 | bacpy(&cp.bdaddr, BDADDR_ANY); | ||
273 | cp.delete_all = 0x01; | ||
274 | hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); | ||
275 | |||
276 | /* Read page scan parameters */ | ||
277 | if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) { | ||
278 | hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); | ||
279 | hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | static void le_setup(struct hci_request *req) | ||
284 | { | ||
285 | /* Read LE Buffer Size */ | ||
286 | hci_req_add(req, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); | ||
287 | |||
288 | /* Read LE Local Supported Features */ | ||
289 | hci_req_add(req, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL); | ||
290 | |||
291 | /* Read LE Advertising Channel TX Power */ | ||
292 | hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | ||
293 | |||
294 | /* Read LE White List Size */ | ||
295 | hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); | ||
296 | |||
297 | /* Read LE Supported States */ | ||
298 | hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); | ||
299 | } | ||
300 | |||
301 | static u8 hci_get_inquiry_mode(struct hci_dev *hdev) | ||
302 | { | ||
303 | if (lmp_ext_inq_capable(hdev)) | ||
304 | return 0x02; | ||
305 | |||
306 | if (lmp_inq_rssi_capable(hdev)) | ||
307 | return 0x01; | ||
308 | |||
309 | if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && | ||
310 | hdev->lmp_subver == 0x0757) | ||
311 | return 0x01; | ||
312 | |||
313 | if (hdev->manufacturer == 15) { | ||
314 | if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) | ||
315 | return 0x01; | ||
316 | if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) | ||
317 | return 0x01; | ||
318 | if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) | ||
319 | return 0x01; | ||
320 | } | ||
321 | |||
322 | if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && | ||
323 | hdev->lmp_subver == 0x1805) | ||
324 | return 0x01; | ||
325 | |||
326 | return 0x00; | ||
327 | } | ||
328 | |||
329 | static void hci_setup_inquiry_mode(struct hci_request *req) | ||
330 | { | ||
331 | u8 mode; | ||
332 | |||
333 | mode = hci_get_inquiry_mode(req->hdev); | ||
334 | |||
335 | hci_req_add(req, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); | ||
336 | } | ||
337 | |||
338 | static void hci_setup_event_mask(struct hci_request *req) | ||
339 | { | ||
340 | struct hci_dev *hdev = req->hdev; | ||
341 | |||
342 | /* The second byte is 0xff instead of 0x9f (two reserved bits | ||
343 | * disabled) since a Broadcom 1.2 dongle doesn't respond to the | ||
344 | * command otherwise. | ||
345 | */ | ||
346 | u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; | ||
347 | |||
348 | /* CSR 1.1 dongles does not accept any bitfield so don't try to set | ||
349 | * any event mask for pre 1.2 devices. | ||
350 | */ | ||
351 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | ||
352 | return; | ||
353 | |||
354 | if (lmp_bredr_capable(hdev)) { | ||
355 | events[4] |= 0x01; /* Flow Specification Complete */ | ||
356 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | ||
357 | events[4] |= 0x04; /* Read Remote Extended Features Complete */ | ||
358 | events[5] |= 0x08; /* Synchronous Connection Complete */ | ||
359 | events[5] |= 0x10; /* Synchronous Connection Changed */ | ||
360 | } | ||
361 | |||
362 | if (lmp_inq_rssi_capable(hdev)) | ||
363 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | ||
364 | |||
365 | if (lmp_sniffsubr_capable(hdev)) | ||
366 | events[5] |= 0x20; /* Sniff Subrating */ | ||
367 | |||
368 | if (lmp_pause_enc_capable(hdev)) | ||
369 | events[5] |= 0x80; /* Encryption Key Refresh Complete */ | ||
370 | |||
371 | if (lmp_ext_inq_capable(hdev)) | ||
372 | events[5] |= 0x40; /* Extended Inquiry Result */ | ||
373 | |||
374 | if (lmp_no_flush_capable(hdev)) | ||
375 | events[7] |= 0x01; /* Enhanced Flush Complete */ | ||
376 | |||
377 | if (lmp_lsto_capable(hdev)) | ||
378 | events[6] |= 0x80; /* Link Supervision Timeout Changed */ | ||
379 | |||
380 | if (lmp_ssp_capable(hdev)) { | ||
381 | events[6] |= 0x01; /* IO Capability Request */ | ||
382 | events[6] |= 0x02; /* IO Capability Response */ | ||
383 | events[6] |= 0x04; /* User Confirmation Request */ | ||
384 | events[6] |= 0x08; /* User Passkey Request */ | ||
385 | events[6] |= 0x10; /* Remote OOB Data Request */ | ||
386 | events[6] |= 0x20; /* Simple Pairing Complete */ | ||
387 | events[7] |= 0x04; /* User Passkey Notification */ | ||
388 | events[7] |= 0x08; /* Keypress Notification */ | ||
389 | events[7] |= 0x10; /* Remote Host Supported | ||
390 | * Features Notification | ||
391 | */ | ||
392 | } | ||
393 | |||
394 | if (lmp_le_capable(hdev)) | ||
395 | events[7] |= 0x20; /* LE Meta-Event */ | ||
396 | |||
397 | hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events); | ||
398 | |||
399 | if (lmp_le_capable(hdev)) { | ||
400 | memset(events, 0, sizeof(events)); | ||
401 | events[0] = 0x1f; | ||
402 | hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, | ||
403 | sizeof(events), events); | ||
404 | } | ||
405 | } | ||
406 | |||
407 | static void hci_init2_req(struct hci_request *req, unsigned long opt) | ||
408 | { | ||
409 | struct hci_dev *hdev = req->hdev; | ||
410 | |||
411 | if (lmp_bredr_capable(hdev)) | ||
412 | bredr_setup(req); | ||
413 | |||
414 | if (lmp_le_capable(hdev)) | ||
415 | le_setup(req); | ||
416 | |||
417 | hci_setup_event_mask(req); | ||
418 | |||
419 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) | ||
420 | hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); | ||
421 | |||
422 | if (lmp_ssp_capable(hdev)) { | ||
423 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { | ||
424 | u8 mode = 0x01; | ||
425 | hci_req_add(req, HCI_OP_WRITE_SSP_MODE, | ||
426 | sizeof(mode), &mode); | ||
427 | } else { | ||
428 | struct hci_cp_write_eir cp; | ||
429 | |||
430 | memset(hdev->eir, 0, sizeof(hdev->eir)); | ||
431 | memset(&cp, 0, sizeof(cp)); | ||
432 | |||
433 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | if (lmp_inq_rssi_capable(hdev)) | ||
438 | hci_setup_inquiry_mode(req); | ||
439 | |||
440 | if (lmp_inq_tx_pwr_capable(hdev)) | ||
441 | hci_req_add(req, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); | ||
442 | |||
443 | if (lmp_ext_feat_capable(hdev)) { | ||
444 | struct hci_cp_read_local_ext_features cp; | ||
445 | |||
446 | cp.page = 0x01; | ||
447 | hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES, | ||
448 | sizeof(cp), &cp); | ||
449 | } | ||
450 | |||
451 | if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { | ||
452 | u8 enable = 1; | ||
453 | hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), | ||
454 | &enable); | ||
455 | } | ||
456 | } | ||
457 | |||
458 | static void hci_setup_link_policy(struct hci_request *req) | ||
459 | { | ||
460 | struct hci_dev *hdev = req->hdev; | ||
461 | struct hci_cp_write_def_link_policy cp; | ||
462 | u16 link_policy = 0; | ||
463 | |||
464 | if (lmp_rswitch_capable(hdev)) | ||
465 | link_policy |= HCI_LP_RSWITCH; | ||
466 | if (lmp_hold_capable(hdev)) | ||
467 | link_policy |= HCI_LP_HOLD; | ||
468 | if (lmp_sniff_capable(hdev)) | ||
469 | link_policy |= HCI_LP_SNIFF; | ||
470 | if (lmp_park_capable(hdev)) | ||
471 | link_policy |= HCI_LP_PARK; | ||
472 | |||
473 | cp.policy = cpu_to_le16(link_policy); | ||
474 | hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); | ||
475 | } | ||
476 | |||
477 | static void hci_set_le_support(struct hci_request *req) | ||
478 | { | ||
479 | struct hci_dev *hdev = req->hdev; | ||
480 | struct hci_cp_write_le_host_supported cp; | ||
481 | |||
482 | memset(&cp, 0, sizeof(cp)); | ||
483 | |||
484 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | ||
485 | cp.le = 0x01; | ||
486 | cp.simul = lmp_le_br_capable(hdev); | ||
487 | } | ||
488 | |||
489 | if (cp.le != lmp_host_le_capable(hdev)) | ||
490 | hci_req_add(req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), | ||
491 | &cp); | ||
492 | } | ||
493 | |||
494 | static void hci_init3_req(struct hci_request *req, unsigned long opt) | ||
495 | { | ||
496 | struct hci_dev *hdev = req->hdev; | ||
497 | |||
498 | if (hdev->commands[5] & 0x10) | ||
499 | hci_setup_link_policy(req); | ||
500 | |||
501 | if (lmp_le_capable(hdev)) { | ||
502 | hci_set_le_support(req); | ||
503 | hci_update_ad(req); | ||
504 | } | ||
505 | } | ||
506 | |||
507 | static int __hci_init(struct hci_dev *hdev) | ||
508 | { | ||
509 | int err; | ||
510 | |||
511 | err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT); | ||
512 | if (err < 0) | ||
513 | return err; | ||
514 | |||
515 | /* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode | ||
516 | * BR/EDR/LE type controllers. AMP controllers only need the | ||
517 | * first stage init. | ||
518 | */ | ||
519 | if (hdev->dev_type != HCI_BREDR) | ||
520 | return 0; | ||
521 | |||
522 | err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT); | ||
523 | if (err < 0) | ||
524 | return err; | ||
525 | |||
526 | return __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT); | ||
527 | } | ||
528 | |||
529 | static void hci_scan_req(struct hci_request *req, unsigned long opt) | ||
242 | { | 530 | { |
243 | __u8 scan = opt; | 531 | __u8 scan = opt; |
244 | 532 | ||
245 | BT_DBG("%s %x", hdev->name, scan); | 533 | BT_DBG("%s %x", req->hdev->name, scan); |
246 | 534 | ||
247 | /* Inquiry and Page scans */ | 535 | /* Inquiry and Page scans */ |
248 | hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 536 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
249 | } | 537 | } |
250 | 538 | ||
251 | static void hci_auth_req(struct hci_dev *hdev, unsigned long opt) | 539 | static void hci_auth_req(struct hci_request *req, unsigned long opt) |
252 | { | 540 | { |
253 | __u8 auth = opt; | 541 | __u8 auth = opt; |
254 | 542 | ||
255 | BT_DBG("%s %x", hdev->name, auth); | 543 | BT_DBG("%s %x", req->hdev->name, auth); |
256 | 544 | ||
257 | /* Authentication */ | 545 | /* Authentication */ |
258 | hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth); | 546 | hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth); |
259 | } | 547 | } |
260 | 548 | ||
261 | static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt) | 549 | static void hci_encrypt_req(struct hci_request *req, unsigned long opt) |
262 | { | 550 | { |
263 | __u8 encrypt = opt; | 551 | __u8 encrypt = opt; |
264 | 552 | ||
265 | BT_DBG("%s %x", hdev->name, encrypt); | 553 | BT_DBG("%s %x", req->hdev->name, encrypt); |
266 | 554 | ||
267 | /* Encryption */ | 555 | /* Encryption */ |
268 | hci_send_cmd(hdev, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); | 556 | hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); |
269 | } | 557 | } |
270 | 558 | ||
271 | static void hci_linkpol_req(struct hci_dev *hdev, unsigned long opt) | 559 | static void hci_linkpol_req(struct hci_request *req, unsigned long opt) |
272 | { | 560 | { |
273 | __le16 policy = cpu_to_le16(opt); | 561 | __le16 policy = cpu_to_le16(opt); |
274 | 562 | ||
275 | BT_DBG("%s %x", hdev->name, policy); | 563 | BT_DBG("%s %x", req->hdev->name, policy); |
276 | 564 | ||
277 | /* Default link policy */ | 565 | /* Default link policy */ |
278 | hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy); | 566 | hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy); |
279 | } | 567 | } |
280 | 568 | ||
281 | /* Get HCI device by index. | 569 | /* Get HCI device by index. |
@@ -512,9 +800,10 @@ static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf) | |||
512 | return copied; | 800 | return copied; |
513 | } | 801 | } |
514 | 802 | ||
515 | static void hci_inq_req(struct hci_dev *hdev, unsigned long opt) | 803 | static void hci_inq_req(struct hci_request *req, unsigned long opt) |
516 | { | 804 | { |
517 | struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt; | 805 | struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt; |
806 | struct hci_dev *hdev = req->hdev; | ||
518 | struct hci_cp_inquiry cp; | 807 | struct hci_cp_inquiry cp; |
519 | 808 | ||
520 | BT_DBG("%s", hdev->name); | 809 | BT_DBG("%s", hdev->name); |
@@ -526,7 +815,7 @@ static void hci_inq_req(struct hci_dev *hdev, unsigned long opt) | |||
526 | memcpy(&cp.lap, &ir->lap, 3); | 815 | memcpy(&cp.lap, &ir->lap, 3); |
527 | cp.length = ir->length; | 816 | cp.length = ir->length; |
528 | cp.num_rsp = ir->num_rsp; | 817 | cp.num_rsp = ir->num_rsp; |
529 | hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp); | 818 | hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp); |
530 | } | 819 | } |
531 | 820 | ||
532 | int hci_inquiry(void __user *arg) | 821 | int hci_inquiry(void __user *arg) |
@@ -556,7 +845,8 @@ int hci_inquiry(void __user *arg) | |||
556 | timeo = ir.length * msecs_to_jiffies(2000); | 845 | timeo = ir.length * msecs_to_jiffies(2000); |
557 | 846 | ||
558 | if (do_inquiry) { | 847 | if (do_inquiry) { |
559 | err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo); | 848 | err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir, |
849 | timeo); | ||
560 | if (err < 0) | 850 | if (err < 0) |
561 | goto done; | 851 | goto done; |
562 | } | 852 | } |
@@ -654,39 +944,29 @@ static u8 create_ad(struct hci_dev *hdev, u8 *ptr) | |||
654 | return ad_len; | 944 | return ad_len; |
655 | } | 945 | } |
656 | 946 | ||
657 | int hci_update_ad(struct hci_dev *hdev) | 947 | void hci_update_ad(struct hci_request *req) |
658 | { | 948 | { |
949 | struct hci_dev *hdev = req->hdev; | ||
659 | struct hci_cp_le_set_adv_data cp; | 950 | struct hci_cp_le_set_adv_data cp; |
660 | u8 len; | 951 | u8 len; |
661 | int err; | ||
662 | 952 | ||
663 | hci_dev_lock(hdev); | 953 | if (!lmp_le_capable(hdev)) |
664 | 954 | return; | |
665 | if (!lmp_le_capable(hdev)) { | ||
666 | err = -EINVAL; | ||
667 | goto unlock; | ||
668 | } | ||
669 | 955 | ||
670 | memset(&cp, 0, sizeof(cp)); | 956 | memset(&cp, 0, sizeof(cp)); |
671 | 957 | ||
672 | len = create_ad(hdev, cp.data); | 958 | len = create_ad(hdev, cp.data); |
673 | 959 | ||
674 | if (hdev->adv_data_len == len && | 960 | if (hdev->adv_data_len == len && |
675 | memcmp(cp.data, hdev->adv_data, len) == 0) { | 961 | memcmp(cp.data, hdev->adv_data, len) == 0) |
676 | err = 0; | 962 | return; |
677 | goto unlock; | ||
678 | } | ||
679 | 963 | ||
680 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | 964 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); |
681 | hdev->adv_data_len = len; | 965 | hdev->adv_data_len = len; |
682 | 966 | ||
683 | cp.length = len; | 967 | cp.length = len; |
684 | err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||
685 | 968 | ||
686 | unlock: | 969 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); |
687 | hci_dev_unlock(hdev); | ||
688 | |||
689 | return err; | ||
690 | } | 970 | } |
691 | 971 | ||
692 | /* ---- HCI ioctl helpers ---- */ | 972 | /* ---- HCI ioctl helpers ---- */ |
@@ -735,10 +1015,7 @@ int hci_dev_open(__u16 dev) | |||
735 | if (!test_bit(HCI_RAW, &hdev->flags)) { | 1015 | if (!test_bit(HCI_RAW, &hdev->flags)) { |
736 | atomic_set(&hdev->cmd_cnt, 1); | 1016 | atomic_set(&hdev->cmd_cnt, 1); |
737 | set_bit(HCI_INIT, &hdev->flags); | 1017 | set_bit(HCI_INIT, &hdev->flags); |
738 | hdev->init_last_cmd = 0; | 1018 | ret = __hci_init(hdev); |
739 | |||
740 | ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT); | ||
741 | |||
742 | clear_bit(HCI_INIT, &hdev->flags); | 1019 | clear_bit(HCI_INIT, &hdev->flags); |
743 | } | 1020 | } |
744 | 1021 | ||
@@ -746,7 +1023,6 @@ int hci_dev_open(__u16 dev) | |||
746 | hci_dev_hold(hdev); | 1023 | hci_dev_hold(hdev); |
747 | set_bit(HCI_UP, &hdev->flags); | 1024 | set_bit(HCI_UP, &hdev->flags); |
748 | hci_notify(hdev, HCI_DEV_UP); | 1025 | hci_notify(hdev, HCI_DEV_UP); |
749 | hci_update_ad(hdev); | ||
750 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && | 1026 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
751 | mgmt_valid_hdev(hdev)) { | 1027 | mgmt_valid_hdev(hdev)) { |
752 | hci_dev_lock(hdev); | 1028 | hci_dev_lock(hdev); |
@@ -828,7 +1104,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
828 | if (!test_bit(HCI_RAW, &hdev->flags) && | 1104 | if (!test_bit(HCI_RAW, &hdev->flags) && |
829 | test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { | 1105 | test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { |
830 | set_bit(HCI_INIT, &hdev->flags); | 1106 | set_bit(HCI_INIT, &hdev->flags); |
831 | __hci_request(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); | 1107 | __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); |
832 | clear_bit(HCI_INIT, &hdev->flags); | 1108 | clear_bit(HCI_INIT, &hdev->flags); |
833 | } | 1109 | } |
834 | 1110 | ||
@@ -851,6 +1127,10 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
851 | * and no tasks are scheduled. */ | 1127 | * and no tasks are scheduled. */ |
852 | hdev->close(hdev); | 1128 | hdev->close(hdev); |
853 | 1129 | ||
1130 | /* Clear flags */ | ||
1131 | hdev->flags = 0; | ||
1132 | hdev->dev_flags &= ~HCI_PERSISTENT_MASK; | ||
1133 | |||
854 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && | 1134 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && |
855 | mgmt_valid_hdev(hdev)) { | 1135 | mgmt_valid_hdev(hdev)) { |
856 | hci_dev_lock(hdev); | 1136 | hci_dev_lock(hdev); |
@@ -858,9 +1138,6 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
858 | hci_dev_unlock(hdev); | 1138 | hci_dev_unlock(hdev); |
859 | } | 1139 | } |
860 | 1140 | ||
861 | /* Clear flags */ | ||
862 | hdev->flags = 0; | ||
863 | |||
864 | /* Controller radio is available but is currently powered down */ | 1141 | /* Controller radio is available but is currently powered down */ |
865 | hdev->amp_status = 0; | 1142 | hdev->amp_status = 0; |
866 | 1143 | ||
@@ -921,7 +1198,7 @@ int hci_dev_reset(__u16 dev) | |||
921 | hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; | 1198 | hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; |
922 | 1199 | ||
923 | if (!test_bit(HCI_RAW, &hdev->flags)) | 1200 | if (!test_bit(HCI_RAW, &hdev->flags)) |
924 | ret = __hci_request(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); | 1201 | ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); |
925 | 1202 | ||
926 | done: | 1203 | done: |
927 | hci_req_unlock(hdev); | 1204 | hci_req_unlock(hdev); |
@@ -960,8 +1237,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
960 | 1237 | ||
961 | switch (cmd) { | 1238 | switch (cmd) { |
962 | case HCISETAUTH: | 1239 | case HCISETAUTH: |
963 | err = hci_request(hdev, hci_auth_req, dr.dev_opt, | 1240 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, |
964 | HCI_INIT_TIMEOUT); | 1241 | HCI_INIT_TIMEOUT); |
965 | break; | 1242 | break; |
966 | 1243 | ||
967 | case HCISETENCRYPT: | 1244 | case HCISETENCRYPT: |
@@ -972,24 +1249,24 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
972 | 1249 | ||
973 | if (!test_bit(HCI_AUTH, &hdev->flags)) { | 1250 | if (!test_bit(HCI_AUTH, &hdev->flags)) { |
974 | /* Auth must be enabled first */ | 1251 | /* Auth must be enabled first */ |
975 | err = hci_request(hdev, hci_auth_req, dr.dev_opt, | 1252 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, |
976 | HCI_INIT_TIMEOUT); | 1253 | HCI_INIT_TIMEOUT); |
977 | if (err) | 1254 | if (err) |
978 | break; | 1255 | break; |
979 | } | 1256 | } |
980 | 1257 | ||
981 | err = hci_request(hdev, hci_encrypt_req, dr.dev_opt, | 1258 | err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt, |
982 | HCI_INIT_TIMEOUT); | 1259 | HCI_INIT_TIMEOUT); |
983 | break; | 1260 | break; |
984 | 1261 | ||
985 | case HCISETSCAN: | 1262 | case HCISETSCAN: |
986 | err = hci_request(hdev, hci_scan_req, dr.dev_opt, | 1263 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, |
987 | HCI_INIT_TIMEOUT); | 1264 | HCI_INIT_TIMEOUT); |
988 | break; | 1265 | break; |
989 | 1266 | ||
990 | case HCISETLINKPOL: | 1267 | case HCISETLINKPOL: |
991 | err = hci_request(hdev, hci_linkpol_req, dr.dev_opt, | 1268 | err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt, |
992 | HCI_INIT_TIMEOUT); | 1269 | HCI_INIT_TIMEOUT); |
993 | break; | 1270 | break; |
994 | 1271 | ||
995 | case HCISETLINKMODE: | 1272 | case HCISETLINKMODE: |
@@ -1566,7 +1843,7 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
1566 | return mgmt_device_unblocked(hdev, bdaddr, type); | 1843 | return mgmt_device_unblocked(hdev, bdaddr, type); |
1567 | } | 1844 | } |
1568 | 1845 | ||
1569 | static void le_scan_param_req(struct hci_dev *hdev, unsigned long opt) | 1846 | static void le_scan_param_req(struct hci_request *req, unsigned long opt) |
1570 | { | 1847 | { |
1571 | struct le_scan_params *param = (struct le_scan_params *) opt; | 1848 | struct le_scan_params *param = (struct le_scan_params *) opt; |
1572 | struct hci_cp_le_set_scan_param cp; | 1849 | struct hci_cp_le_set_scan_param cp; |
@@ -1576,10 +1853,10 @@ static void le_scan_param_req(struct hci_dev *hdev, unsigned long opt) | |||
1576 | cp.interval = cpu_to_le16(param->interval); | 1853 | cp.interval = cpu_to_le16(param->interval); |
1577 | cp.window = cpu_to_le16(param->window); | 1854 | cp.window = cpu_to_le16(param->window); |
1578 | 1855 | ||
1579 | hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp); | 1856 | hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp); |
1580 | } | 1857 | } |
1581 | 1858 | ||
1582 | static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt) | 1859 | static void le_scan_enable_req(struct hci_request *req, unsigned long opt) |
1583 | { | 1860 | { |
1584 | struct hci_cp_le_set_scan_enable cp; | 1861 | struct hci_cp_le_set_scan_enable cp; |
1585 | 1862 | ||
@@ -1587,7 +1864,7 @@ static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt) | |||
1587 | cp.enable = 1; | 1864 | cp.enable = 1; |
1588 | cp.filter_dup = 1; | 1865 | cp.filter_dup = 1; |
1589 | 1866 | ||
1590 | hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | 1867 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); |
1591 | } | 1868 | } |
1592 | 1869 | ||
1593 | static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval, | 1870 | static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval, |
@@ -1608,10 +1885,10 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval, | |||
1608 | 1885 | ||
1609 | hci_req_lock(hdev); | 1886 | hci_req_lock(hdev); |
1610 | 1887 | ||
1611 | err = __hci_request(hdev, le_scan_param_req, (unsigned long) ¶m, | 1888 | err = __hci_req_sync(hdev, le_scan_param_req, (unsigned long) ¶m, |
1612 | timeo); | 1889 | timeo); |
1613 | if (!err) | 1890 | if (!err) |
1614 | err = __hci_request(hdev, le_scan_enable_req, 0, timeo); | 1891 | err = __hci_req_sync(hdev, le_scan_enable_req, 0, timeo); |
1615 | 1892 | ||
1616 | hci_req_unlock(hdev); | 1893 | hci_req_unlock(hdev); |
1617 | 1894 | ||
@@ -2160,20 +2437,55 @@ static int hci_send_frame(struct sk_buff *skb) | |||
2160 | return hdev->send(skb); | 2437 | return hdev->send(skb); |
2161 | } | 2438 | } |
2162 | 2439 | ||
2163 | /* Send HCI command */ | 2440 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev) |
2164 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) | 2441 | { |
2442 | skb_queue_head_init(&req->cmd_q); | ||
2443 | req->hdev = hdev; | ||
2444 | req->err = 0; | ||
2445 | } | ||
2446 | |||
2447 | int hci_req_run(struct hci_request *req, hci_req_complete_t complete) | ||
2448 | { | ||
2449 | struct hci_dev *hdev = req->hdev; | ||
2450 | struct sk_buff *skb; | ||
2451 | unsigned long flags; | ||
2452 | |||
2453 | BT_DBG("length %u", skb_queue_len(&req->cmd_q)); | ||
2454 | |||
2455 | /* If an error occured during request building, remove all HCI | ||
2456 | * commands queued on the HCI request queue. | ||
2457 | */ | ||
2458 | if (req->err) { | ||
2459 | skb_queue_purge(&req->cmd_q); | ||
2460 | return req->err; | ||
2461 | } | ||
2462 | |||
2463 | /* Do not allow empty requests */ | ||
2464 | if (skb_queue_empty(&req->cmd_q)) | ||
2465 | return -ENODATA; | ||
2466 | |||
2467 | skb = skb_peek_tail(&req->cmd_q); | ||
2468 | bt_cb(skb)->req.complete = complete; | ||
2469 | |||
2470 | spin_lock_irqsave(&hdev->cmd_q.lock, flags); | ||
2471 | skb_queue_splice_tail(&req->cmd_q, &hdev->cmd_q); | ||
2472 | spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); | ||
2473 | |||
2474 | queue_work(hdev->workqueue, &hdev->cmd_work); | ||
2475 | |||
2476 | return 0; | ||
2477 | } | ||
2478 | |||
2479 | static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, | ||
2480 | u32 plen, void *param) | ||
2165 | { | 2481 | { |
2166 | int len = HCI_COMMAND_HDR_SIZE + plen; | 2482 | int len = HCI_COMMAND_HDR_SIZE + plen; |
2167 | struct hci_command_hdr *hdr; | 2483 | struct hci_command_hdr *hdr; |
2168 | struct sk_buff *skb; | 2484 | struct sk_buff *skb; |
2169 | 2485 | ||
2170 | BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen); | ||
2171 | |||
2172 | skb = bt_skb_alloc(len, GFP_ATOMIC); | 2486 | skb = bt_skb_alloc(len, GFP_ATOMIC); |
2173 | if (!skb) { | 2487 | if (!skb) |
2174 | BT_ERR("%s no memory for command", hdev->name); | 2488 | return NULL; |
2175 | return -ENOMEM; | ||
2176 | } | ||
2177 | 2489 | ||
2178 | hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE); | 2490 | hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE); |
2179 | hdr->opcode = cpu_to_le16(opcode); | 2491 | hdr->opcode = cpu_to_le16(opcode); |
@@ -2187,8 +2499,26 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) | |||
2187 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; | 2499 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; |
2188 | skb->dev = (void *) hdev; | 2500 | skb->dev = (void *) hdev; |
2189 | 2501 | ||
2190 | if (test_bit(HCI_INIT, &hdev->flags)) | 2502 | return skb; |
2191 | hdev->init_last_cmd = opcode; | 2503 | } |
2504 | |||
2505 | /* Send HCI command */ | ||
2506 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) | ||
2507 | { | ||
2508 | struct sk_buff *skb; | ||
2509 | |||
2510 | BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen); | ||
2511 | |||
2512 | skb = hci_prepare_cmd(hdev, opcode, plen, param); | ||
2513 | if (!skb) { | ||
2514 | BT_ERR("%s no memory for command", hdev->name); | ||
2515 | return -ENOMEM; | ||
2516 | } | ||
2517 | |||
2518 | /* Stand-alone HCI commands must be flaged as | ||
2519 | * single-command requests. | ||
2520 | */ | ||
2521 | bt_cb(skb)->req.start = true; | ||
2192 | 2522 | ||
2193 | skb_queue_tail(&hdev->cmd_q, skb); | 2523 | skb_queue_tail(&hdev->cmd_q, skb); |
2194 | queue_work(hdev->workqueue, &hdev->cmd_work); | 2524 | queue_work(hdev->workqueue, &hdev->cmd_work); |
@@ -2196,6 +2526,34 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) | |||
2196 | return 0; | 2526 | return 0; |
2197 | } | 2527 | } |
2198 | 2528 | ||
2529 | /* Queue a command to an asynchronous HCI request */ | ||
2530 | void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param) | ||
2531 | { | ||
2532 | struct hci_dev *hdev = req->hdev; | ||
2533 | struct sk_buff *skb; | ||
2534 | |||
2535 | BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen); | ||
2536 | |||
2537 | /* If an error occured during request building, there is no point in | ||
2538 | * queueing the HCI command. We can simply return. | ||
2539 | */ | ||
2540 | if (req->err) | ||
2541 | return; | ||
2542 | |||
2543 | skb = hci_prepare_cmd(hdev, opcode, plen, param); | ||
2544 | if (!skb) { | ||
2545 | BT_ERR("%s no memory for command (opcode 0x%4.4x)", | ||
2546 | hdev->name, opcode); | ||
2547 | req->err = -ENOMEM; | ||
2548 | return; | ||
2549 | } | ||
2550 | |||
2551 | if (skb_queue_empty(&req->cmd_q)) | ||
2552 | bt_cb(skb)->req.start = true; | ||
2553 | |||
2554 | skb_queue_tail(&req->cmd_q, skb); | ||
2555 | } | ||
2556 | |||
2199 | /* Get data from the previously sent command */ | 2557 | /* Get data from the previously sent command */ |
2200 | void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode) | 2558 | void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode) |
2201 | { | 2559 | { |
@@ -2398,7 +2756,7 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type) | |||
2398 | if (c->type == type && c->sent) { | 2756 | if (c->type == type && c->sent) { |
2399 | BT_ERR("%s killing stalled connection %pMR", | 2757 | BT_ERR("%s killing stalled connection %pMR", |
2400 | hdev->name, &c->dst); | 2758 | hdev->name, &c->dst); |
2401 | hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM); | 2759 | hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); |
2402 | } | 2760 | } |
2403 | } | 2761 | } |
2404 | 2762 | ||
@@ -2860,6 +3218,123 @@ static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
2860 | kfree_skb(skb); | 3218 | kfree_skb(skb); |
2861 | } | 3219 | } |
2862 | 3220 | ||
3221 | static bool hci_req_is_complete(struct hci_dev *hdev) | ||
3222 | { | ||
3223 | struct sk_buff *skb; | ||
3224 | |||
3225 | skb = skb_peek(&hdev->cmd_q); | ||
3226 | if (!skb) | ||
3227 | return true; | ||
3228 | |||
3229 | return bt_cb(skb)->req.start; | ||
3230 | } | ||
3231 | |||
3232 | static void hci_resend_last(struct hci_dev *hdev) | ||
3233 | { | ||
3234 | struct hci_command_hdr *sent; | ||
3235 | struct sk_buff *skb; | ||
3236 | u16 opcode; | ||
3237 | |||
3238 | if (!hdev->sent_cmd) | ||
3239 | return; | ||
3240 | |||
3241 | sent = (void *) hdev->sent_cmd->data; | ||
3242 | opcode = __le16_to_cpu(sent->opcode); | ||
3243 | if (opcode == HCI_OP_RESET) | ||
3244 | return; | ||
3245 | |||
3246 | skb = skb_clone(hdev->sent_cmd, GFP_KERNEL); | ||
3247 | if (!skb) | ||
3248 | return; | ||
3249 | |||
3250 | skb_queue_head(&hdev->cmd_q, skb); | ||
3251 | queue_work(hdev->workqueue, &hdev->cmd_work); | ||
3252 | } | ||
3253 | |||
3254 | void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status) | ||
3255 | { | ||
3256 | hci_req_complete_t req_complete = NULL; | ||
3257 | struct sk_buff *skb; | ||
3258 | unsigned long flags; | ||
3259 | |||
3260 | BT_DBG("opcode 0x%04x status 0x%02x", opcode, status); | ||
3261 | |||
3262 | /* If the completed command doesn't match the last one that was | ||
3263 | * sent we need to do special handling of it. | ||
3264 | */ | ||
3265 | if (!hci_sent_cmd_data(hdev, opcode)) { | ||
3266 | /* Some CSR based controllers generate a spontaneous | ||
3267 | * reset complete event during init and any pending | ||
3268 | * command will never be completed. In such a case we | ||
3269 | * need to resend whatever was the last sent | ||
3270 | * command. | ||
3271 | */ | ||
3272 | if (test_bit(HCI_INIT, &hdev->flags) && opcode == HCI_OP_RESET) | ||
3273 | hci_resend_last(hdev); | ||
3274 | |||
3275 | return; | ||
3276 | } | ||
3277 | |||
3278 | /* If the command succeeded and there's still more commands in | ||
3279 | * this request the request is not yet complete. | ||
3280 | */ | ||
3281 | if (!status && !hci_req_is_complete(hdev)) | ||
3282 | return; | ||
3283 | |||
3284 | /* If this was the last command in a request the complete | ||
3285 | * callback would be found in hdev->sent_cmd instead of the | ||
3286 | * command queue (hdev->cmd_q). | ||
3287 | */ | ||
3288 | if (hdev->sent_cmd) { | ||
3289 | req_complete = bt_cb(hdev->sent_cmd)->req.complete; | ||
3290 | if (req_complete) | ||
3291 | goto call_complete; | ||
3292 | } | ||
3293 | |||
3294 | /* Remove all pending commands belonging to this request */ | ||
3295 | spin_lock_irqsave(&hdev->cmd_q.lock, flags); | ||
3296 | while ((skb = __skb_dequeue(&hdev->cmd_q))) { | ||
3297 | if (bt_cb(skb)->req.start) { | ||
3298 | __skb_queue_head(&hdev->cmd_q, skb); | ||
3299 | break; | ||
3300 | } | ||
3301 | |||
3302 | req_complete = bt_cb(skb)->req.complete; | ||
3303 | kfree_skb(skb); | ||
3304 | } | ||
3305 | spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); | ||
3306 | |||
3307 | call_complete: | ||
3308 | if (req_complete) | ||
3309 | req_complete(hdev, status); | ||
3310 | } | ||
3311 | |||
3312 | void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status) | ||
3313 | { | ||
3314 | hci_req_complete_t req_complete = NULL; | ||
3315 | |||
3316 | BT_DBG("opcode 0x%04x status 0x%02x", opcode, status); | ||
3317 | |||
3318 | if (status) { | ||
3319 | hci_req_cmd_complete(hdev, opcode, status); | ||
3320 | return; | ||
3321 | } | ||
3322 | |||
3323 | /* No need to handle success status if there are more commands */ | ||
3324 | if (!hci_req_is_complete(hdev)) | ||
3325 | return; | ||
3326 | |||
3327 | if (hdev->sent_cmd) | ||
3328 | req_complete = bt_cb(hdev->sent_cmd)->req.complete; | ||
3329 | |||
3330 | /* If the request doesn't have a complete callback or there | ||
3331 | * are other commands/requests in the hdev queue we consider | ||
3332 | * this request as completed. | ||
3333 | */ | ||
3334 | if (!req_complete || !skb_queue_empty(&hdev->cmd_q)) | ||
3335 | hci_req_cmd_complete(hdev, opcode, status); | ||
3336 | } | ||
3337 | |||
2863 | static void hci_rx_work(struct work_struct *work) | 3338 | static void hci_rx_work(struct work_struct *work) |
2864 | { | 3339 | { |
2865 | struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work); | 3340 | struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 477726a63512..138580745c2c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -53,7 +53,7 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) | |||
53 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | 53 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); |
54 | hci_dev_unlock(hdev); | 54 | hci_dev_unlock(hdev); |
55 | 55 | ||
56 | hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); | 56 | hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status); |
57 | 57 | ||
58 | hci_conn_check_pending(hdev); | 58 | hci_conn_check_pending(hdev); |
59 | } | 59 | } |
@@ -183,8 +183,6 @@ static void hci_cc_write_def_link_policy(struct hci_dev *hdev, | |||
183 | 183 | ||
184 | if (!status) | 184 | if (!status) |
185 | hdev->link_policy = get_unaligned_le16(sent); | 185 | hdev->link_policy = get_unaligned_le16(sent); |
186 | |||
187 | hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); | ||
188 | } | 186 | } |
189 | 187 | ||
190 | static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | 188 | static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -195,11 +193,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | |||
195 | 193 | ||
196 | clear_bit(HCI_RESET, &hdev->flags); | 194 | clear_bit(HCI_RESET, &hdev->flags); |
197 | 195 | ||
198 | hci_req_complete(hdev, HCI_OP_RESET, status); | ||
199 | |||
200 | /* Reset all non-persistent flags */ | 196 | /* Reset all non-persistent flags */ |
201 | hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) | | 197 | hdev->dev_flags &= ~HCI_PERSISTENT_MASK; |
202 | BIT(HCI_PERIODIC_INQ)); | ||
203 | 198 | ||
204 | hdev->discovery.state = DISCOVERY_STOPPED; | 199 | hdev->discovery.state = DISCOVERY_STOPPED; |
205 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; | 200 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; |
@@ -228,11 +223,6 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | |||
228 | memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); | 223 | memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); |
229 | 224 | ||
230 | hci_dev_unlock(hdev); | 225 | hci_dev_unlock(hdev); |
231 | |||
232 | if (!status && !test_bit(HCI_INIT, &hdev->flags)) | ||
233 | hci_update_ad(hdev); | ||
234 | |||
235 | hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); | ||
236 | } | 226 | } |
237 | 227 | ||
238 | static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) | 228 | static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -270,8 +260,6 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
270 | 260 | ||
271 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | 261 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) |
272 | mgmt_auth_enable_complete(hdev, status); | 262 | mgmt_auth_enable_complete(hdev, status); |
273 | |||
274 | hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); | ||
275 | } | 263 | } |
276 | 264 | ||
277 | static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) | 265 | static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -293,8 +281,6 @@ static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) | |||
293 | else | 281 | else |
294 | clear_bit(HCI_ENCRYPT, &hdev->flags); | 282 | clear_bit(HCI_ENCRYPT, &hdev->flags); |
295 | } | 283 | } |
296 | |||
297 | hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); | ||
298 | } | 284 | } |
299 | 285 | ||
300 | static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | 286 | static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -343,7 +329,6 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
343 | 329 | ||
344 | done: | 330 | done: |
345 | hci_dev_unlock(hdev); | 331 | hci_dev_unlock(hdev); |
346 | hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); | ||
347 | } | 332 | } |
348 | 333 | ||
349 | static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) | 334 | static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -435,15 +420,6 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, | |||
435 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); | 420 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); |
436 | } | 421 | } |
437 | 422 | ||
438 | static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) | ||
439 | { | ||
440 | __u8 status = *((__u8 *) skb->data); | ||
441 | |||
442 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
443 | |||
444 | hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); | ||
445 | } | ||
446 | |||
447 | static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) | 423 | static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) |
448 | { | 424 | { |
449 | __u8 status = *((__u8 *) skb->data); | 425 | __u8 status = *((__u8 *) skb->data); |
@@ -472,211 +448,6 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) | |||
472 | } | 448 | } |
473 | } | 449 | } |
474 | 450 | ||
475 | static u8 hci_get_inquiry_mode(struct hci_dev *hdev) | ||
476 | { | ||
477 | if (lmp_ext_inq_capable(hdev)) | ||
478 | return 2; | ||
479 | |||
480 | if (lmp_inq_rssi_capable(hdev)) | ||
481 | return 1; | ||
482 | |||
483 | if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && | ||
484 | hdev->lmp_subver == 0x0757) | ||
485 | return 1; | ||
486 | |||
487 | if (hdev->manufacturer == 15) { | ||
488 | if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) | ||
489 | return 1; | ||
490 | if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) | ||
491 | return 1; | ||
492 | if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) | ||
493 | return 1; | ||
494 | } | ||
495 | |||
496 | if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && | ||
497 | hdev->lmp_subver == 0x1805) | ||
498 | return 1; | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static void hci_setup_inquiry_mode(struct hci_dev *hdev) | ||
504 | { | ||
505 | u8 mode; | ||
506 | |||
507 | mode = hci_get_inquiry_mode(hdev); | ||
508 | |||
509 | hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); | ||
510 | } | ||
511 | |||
512 | static void hci_setup_event_mask(struct hci_dev *hdev) | ||
513 | { | ||
514 | /* The second byte is 0xff instead of 0x9f (two reserved bits | ||
515 | * disabled) since a Broadcom 1.2 dongle doesn't respond to the | ||
516 | * command otherwise */ | ||
517 | u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; | ||
518 | |||
519 | /* CSR 1.1 dongles does not accept any bitfield so don't try to set | ||
520 | * any event mask for pre 1.2 devices */ | ||
521 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | ||
522 | return; | ||
523 | |||
524 | if (lmp_bredr_capable(hdev)) { | ||
525 | events[4] |= 0x01; /* Flow Specification Complete */ | ||
526 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | ||
527 | events[4] |= 0x04; /* Read Remote Extended Features Complete */ | ||
528 | events[5] |= 0x08; /* Synchronous Connection Complete */ | ||
529 | events[5] |= 0x10; /* Synchronous Connection Changed */ | ||
530 | } | ||
531 | |||
532 | if (lmp_inq_rssi_capable(hdev)) | ||
533 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | ||
534 | |||
535 | if (lmp_sniffsubr_capable(hdev)) | ||
536 | events[5] |= 0x20; /* Sniff Subrating */ | ||
537 | |||
538 | if (lmp_pause_enc_capable(hdev)) | ||
539 | events[5] |= 0x80; /* Encryption Key Refresh Complete */ | ||
540 | |||
541 | if (lmp_ext_inq_capable(hdev)) | ||
542 | events[5] |= 0x40; /* Extended Inquiry Result */ | ||
543 | |||
544 | if (lmp_no_flush_capable(hdev)) | ||
545 | events[7] |= 0x01; /* Enhanced Flush Complete */ | ||
546 | |||
547 | if (lmp_lsto_capable(hdev)) | ||
548 | events[6] |= 0x80; /* Link Supervision Timeout Changed */ | ||
549 | |||
550 | if (lmp_ssp_capable(hdev)) { | ||
551 | events[6] |= 0x01; /* IO Capability Request */ | ||
552 | events[6] |= 0x02; /* IO Capability Response */ | ||
553 | events[6] |= 0x04; /* User Confirmation Request */ | ||
554 | events[6] |= 0x08; /* User Passkey Request */ | ||
555 | events[6] |= 0x10; /* Remote OOB Data Request */ | ||
556 | events[6] |= 0x20; /* Simple Pairing Complete */ | ||
557 | events[7] |= 0x04; /* User Passkey Notification */ | ||
558 | events[7] |= 0x08; /* Keypress Notification */ | ||
559 | events[7] |= 0x10; /* Remote Host Supported | ||
560 | * Features Notification */ | ||
561 | } | ||
562 | |||
563 | if (lmp_le_capable(hdev)) | ||
564 | events[7] |= 0x20; /* LE Meta-Event */ | ||
565 | |||
566 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); | ||
567 | |||
568 | if (lmp_le_capable(hdev)) { | ||
569 | memset(events, 0, sizeof(events)); | ||
570 | events[0] = 0x1f; | ||
571 | hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK, | ||
572 | sizeof(events), events); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | static void bredr_setup(struct hci_dev *hdev) | ||
577 | { | ||
578 | struct hci_cp_delete_stored_link_key cp; | ||
579 | __le16 param; | ||
580 | __u8 flt_type; | ||
581 | |||
582 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | ||
583 | hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); | ||
584 | |||
585 | /* Read Class of Device */ | ||
586 | hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); | ||
587 | |||
588 | /* Read Local Name */ | ||
589 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL); | ||
590 | |||
591 | /* Read Voice Setting */ | ||
592 | hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL); | ||
593 | |||
594 | /* Clear Event Filters */ | ||
595 | flt_type = HCI_FLT_CLEAR_ALL; | ||
596 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | ||
597 | |||
598 | /* Connection accept timeout ~20 secs */ | ||
599 | param = __constant_cpu_to_le16(0x7d00); | ||
600 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | ||
601 | |||
602 | bacpy(&cp.bdaddr, BDADDR_ANY); | ||
603 | cp.delete_all = 1; | ||
604 | hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); | ||
605 | } | ||
606 | |||
607 | static void le_setup(struct hci_dev *hdev) | ||
608 | { | ||
609 | /* Read LE Buffer Size */ | ||
610 | hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); | ||
611 | |||
612 | /* Read LE Local Supported Features */ | ||
613 | hci_send_cmd(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL); | ||
614 | |||
615 | /* Read LE Advertising Channel TX Power */ | ||
616 | hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | ||
617 | |||
618 | /* Read LE White List Size */ | ||
619 | hci_send_cmd(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); | ||
620 | |||
621 | /* Read LE Supported States */ | ||
622 | hci_send_cmd(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); | ||
623 | } | ||
624 | |||
625 | static void hci_setup(struct hci_dev *hdev) | ||
626 | { | ||
627 | if (hdev->dev_type != HCI_BREDR) | ||
628 | return; | ||
629 | |||
630 | /* Read BD Address */ | ||
631 | hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); | ||
632 | |||
633 | if (lmp_bredr_capable(hdev)) | ||
634 | bredr_setup(hdev); | ||
635 | |||
636 | if (lmp_le_capable(hdev)) | ||
637 | le_setup(hdev); | ||
638 | |||
639 | hci_setup_event_mask(hdev); | ||
640 | |||
641 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) | ||
642 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); | ||
643 | |||
644 | if (lmp_ssp_capable(hdev)) { | ||
645 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { | ||
646 | u8 mode = 0x01; | ||
647 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, | ||
648 | sizeof(mode), &mode); | ||
649 | } else { | ||
650 | struct hci_cp_write_eir cp; | ||
651 | |||
652 | memset(hdev->eir, 0, sizeof(hdev->eir)); | ||
653 | memset(&cp, 0, sizeof(cp)); | ||
654 | |||
655 | hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | ||
656 | } | ||
657 | } | ||
658 | |||
659 | if (lmp_inq_rssi_capable(hdev)) | ||
660 | hci_setup_inquiry_mode(hdev); | ||
661 | |||
662 | if (lmp_inq_tx_pwr_capable(hdev)) | ||
663 | hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); | ||
664 | |||
665 | if (lmp_ext_feat_capable(hdev)) { | ||
666 | struct hci_cp_read_local_ext_features cp; | ||
667 | |||
668 | cp.page = 0x01; | ||
669 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), | ||
670 | &cp); | ||
671 | } | ||
672 | |||
673 | if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { | ||
674 | u8 enable = 1; | ||
675 | hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), | ||
676 | &enable); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | 451 | static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) |
681 | { | 452 | { |
682 | struct hci_rp_read_local_version *rp = (void *) skb->data; | 453 | struct hci_rp_read_local_version *rp = (void *) skb->data; |
@@ -684,7 +455,7 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | |||
684 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 455 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
685 | 456 | ||
686 | if (rp->status) | 457 | if (rp->status) |
687 | goto done; | 458 | return; |
688 | 459 | ||
689 | hdev->hci_ver = rp->hci_ver; | 460 | hdev->hci_ver = rp->hci_ver; |
690 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); | 461 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); |
@@ -694,30 +465,6 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | |||
694 | 465 | ||
695 | BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, | 466 | BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, |
696 | hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); | 467 | hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); |
697 | |||
698 | if (test_bit(HCI_INIT, &hdev->flags)) | ||
699 | hci_setup(hdev); | ||
700 | |||
701 | done: | ||
702 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status); | ||
703 | } | ||
704 | |||
705 | static void hci_setup_link_policy(struct hci_dev *hdev) | ||
706 | { | ||
707 | struct hci_cp_write_def_link_policy cp; | ||
708 | u16 link_policy = 0; | ||
709 | |||
710 | if (lmp_rswitch_capable(hdev)) | ||
711 | link_policy |= HCI_LP_RSWITCH; | ||
712 | if (lmp_hold_capable(hdev)) | ||
713 | link_policy |= HCI_LP_HOLD; | ||
714 | if (lmp_sniff_capable(hdev)) | ||
715 | link_policy |= HCI_LP_SNIFF; | ||
716 | if (lmp_park_capable(hdev)) | ||
717 | link_policy |= HCI_LP_PARK; | ||
718 | |||
719 | cp.policy = cpu_to_le16(link_policy); | ||
720 | hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); | ||
721 | } | 468 | } |
722 | 469 | ||
723 | static void hci_cc_read_local_commands(struct hci_dev *hdev, | 470 | static void hci_cc_read_local_commands(struct hci_dev *hdev, |
@@ -727,16 +474,8 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev, | |||
727 | 474 | ||
728 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 475 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
729 | 476 | ||
730 | if (rp->status) | 477 | if (!rp->status) |
731 | goto done; | 478 | memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); |
732 | |||
733 | memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); | ||
734 | |||
735 | if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) | ||
736 | hci_setup_link_policy(hdev); | ||
737 | |||
738 | done: | ||
739 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); | ||
740 | } | 479 | } |
741 | 480 | ||
742 | static void hci_cc_read_local_features(struct hci_dev *hdev, | 481 | static void hci_cc_read_local_features(struct hci_dev *hdev, |
@@ -795,22 +534,6 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, | |||
795 | hdev->features[6], hdev->features[7]); | 534 | hdev->features[6], hdev->features[7]); |
796 | } | 535 | } |
797 | 536 | ||
798 | static void hci_set_le_support(struct hci_dev *hdev) | ||
799 | { | ||
800 | struct hci_cp_write_le_host_supported cp; | ||
801 | |||
802 | memset(&cp, 0, sizeof(cp)); | ||
803 | |||
804 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | ||
805 | cp.le = 1; | ||
806 | cp.simul = lmp_le_br_capable(hdev); | ||
807 | } | ||
808 | |||
809 | if (cp.le != lmp_host_le_capable(hdev)) | ||
810 | hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), | ||
811 | &cp); | ||
812 | } | ||
813 | |||
814 | static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | 537 | static void hci_cc_read_local_ext_features(struct hci_dev *hdev, |
815 | struct sk_buff *skb) | 538 | struct sk_buff *skb) |
816 | { | 539 | { |
@@ -819,7 +542,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | |||
819 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 542 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
820 | 543 | ||
821 | if (rp->status) | 544 | if (rp->status) |
822 | goto done; | 545 | return; |
823 | 546 | ||
824 | switch (rp->page) { | 547 | switch (rp->page) { |
825 | case 0: | 548 | case 0: |
@@ -829,12 +552,6 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | |||
829 | memcpy(hdev->host_features, rp->features, 8); | 552 | memcpy(hdev->host_features, rp->features, 8); |
830 | break; | 553 | break; |
831 | } | 554 | } |
832 | |||
833 | if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) | ||
834 | hci_set_le_support(hdev); | ||
835 | |||
836 | done: | ||
837 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); | ||
838 | } | 555 | } |
839 | 556 | ||
840 | static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, | 557 | static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, |
@@ -844,12 +561,8 @@ static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, | |||
844 | 561 | ||
845 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 562 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
846 | 563 | ||
847 | if (rp->status) | 564 | if (!rp->status) |
848 | return; | 565 | hdev->flow_ctl_mode = rp->mode; |
849 | |||
850 | hdev->flow_ctl_mode = rp->mode; | ||
851 | |||
852 | hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); | ||
853 | } | 566 | } |
854 | 567 | ||
855 | static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) | 568 | static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -886,8 +599,65 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) | |||
886 | 599 | ||
887 | if (!rp->status) | 600 | if (!rp->status) |
888 | bacpy(&hdev->bdaddr, &rp->bdaddr); | 601 | bacpy(&hdev->bdaddr, &rp->bdaddr); |
602 | } | ||
603 | |||
604 | static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, | ||
605 | struct sk_buff *skb) | ||
606 | { | ||
607 | struct hci_rp_read_page_scan_activity *rp = (void *) skb->data; | ||
608 | |||
609 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
610 | |||
611 | if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) { | ||
612 | hdev->page_scan_interval = __le16_to_cpu(rp->interval); | ||
613 | hdev->page_scan_window = __le16_to_cpu(rp->window); | ||
614 | } | ||
615 | } | ||
616 | |||
617 | static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, | ||
618 | struct sk_buff *skb) | ||
619 | { | ||
620 | u8 status = *((u8 *) skb->data); | ||
621 | struct hci_cp_write_page_scan_activity *sent; | ||
622 | |||
623 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
624 | |||
625 | if (status) | ||
626 | return; | ||
627 | |||
628 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); | ||
629 | if (!sent) | ||
630 | return; | ||
631 | |||
632 | hdev->page_scan_interval = __le16_to_cpu(sent->interval); | ||
633 | hdev->page_scan_window = __le16_to_cpu(sent->window); | ||
634 | } | ||
635 | |||
636 | static void hci_cc_read_page_scan_type(struct hci_dev *hdev, | ||
637 | struct sk_buff *skb) | ||
638 | { | ||
639 | struct hci_rp_read_page_scan_type *rp = (void *) skb->data; | ||
640 | |||
641 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
642 | |||
643 | if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) | ||
644 | hdev->page_scan_type = rp->type; | ||
645 | } | ||
646 | |||
647 | static void hci_cc_write_page_scan_type(struct hci_dev *hdev, | ||
648 | struct sk_buff *skb) | ||
649 | { | ||
650 | u8 status = *((u8 *) skb->data); | ||
651 | u8 *type; | ||
889 | 652 | ||
890 | hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); | 653 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
654 | |||
655 | if (status) | ||
656 | return; | ||
657 | |||
658 | type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); | ||
659 | if (type) | ||
660 | hdev->page_scan_type = *type; | ||
891 | } | 661 | } |
892 | 662 | ||
893 | static void hci_cc_read_data_block_size(struct hci_dev *hdev, | 663 | static void hci_cc_read_data_block_size(struct hci_dev *hdev, |
@@ -908,17 +678,6 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev, | |||
908 | 678 | ||
909 | BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, | 679 | BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, |
910 | hdev->block_cnt, hdev->block_len); | 680 | hdev->block_cnt, hdev->block_len); |
911 | |||
912 | hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); | ||
913 | } | ||
914 | |||
915 | static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) | ||
916 | { | ||
917 | __u8 status = *((__u8 *) skb->data); | ||
918 | |||
919 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
920 | |||
921 | hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); | ||
922 | } | 681 | } |
923 | 682 | ||
924 | static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | 683 | static void hci_cc_read_local_amp_info(struct hci_dev *hdev, |
@@ -942,8 +701,6 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | |||
942 | hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); | 701 | hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); |
943 | hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); | 702 | hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); |
944 | 703 | ||
945 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); | ||
946 | |||
947 | a2mp_rsp: | 704 | a2mp_rsp: |
948 | a2mp_send_getinfo_rsp(hdev); | 705 | a2mp_send_getinfo_rsp(hdev); |
949 | } | 706 | } |
@@ -985,35 +742,6 @@ a2mp_rsp: | |||
985 | a2mp_send_create_phy_link_req(hdev, rp->status); | 742 | a2mp_send_create_phy_link_req(hdev, rp->status); |
986 | } | 743 | } |
987 | 744 | ||
988 | static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, | ||
989 | struct sk_buff *skb) | ||
990 | { | ||
991 | __u8 status = *((__u8 *) skb->data); | ||
992 | |||
993 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
994 | |||
995 | hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); | ||
996 | } | ||
997 | |||
998 | static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) | ||
999 | { | ||
1000 | __u8 status = *((__u8 *) skb->data); | ||
1001 | |||
1002 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1003 | |||
1004 | hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); | ||
1005 | } | ||
1006 | |||
1007 | static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, | ||
1008 | struct sk_buff *skb) | ||
1009 | { | ||
1010 | __u8 status = *((__u8 *) skb->data); | ||
1011 | |||
1012 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1013 | |||
1014 | hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); | ||
1015 | } | ||
1016 | |||
1017 | static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, | 745 | static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, |
1018 | struct sk_buff *skb) | 746 | struct sk_buff *skb) |
1019 | { | 747 | { |
@@ -1023,17 +751,6 @@ static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, | |||
1023 | 751 | ||
1024 | if (!rp->status) | 752 | if (!rp->status) |
1025 | hdev->inq_tx_power = rp->tx_power; | 753 | hdev->inq_tx_power = rp->tx_power; |
1026 | |||
1027 | hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status); | ||
1028 | } | ||
1029 | |||
1030 | static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1031 | { | ||
1032 | __u8 status = *((__u8 *) skb->data); | ||
1033 | |||
1034 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1035 | |||
1036 | hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); | ||
1037 | } | 754 | } |
1038 | 755 | ||
1039 | static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) | 756 | static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1095,8 +812,6 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, | |||
1095 | hdev->le_cnt = hdev->le_pkts; | 812 | hdev->le_cnt = hdev->le_pkts; |
1096 | 813 | ||
1097 | BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); | 814 | BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); |
1098 | |||
1099 | hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); | ||
1100 | } | 815 | } |
1101 | 816 | ||
1102 | static void hci_cc_le_read_local_features(struct hci_dev *hdev, | 817 | static void hci_cc_le_read_local_features(struct hci_dev *hdev, |
@@ -1108,8 +823,6 @@ static void hci_cc_le_read_local_features(struct hci_dev *hdev, | |||
1108 | 823 | ||
1109 | if (!rp->status) | 824 | if (!rp->status) |
1110 | memcpy(hdev->le_features, rp->features, 8); | 825 | memcpy(hdev->le_features, rp->features, 8); |
1111 | |||
1112 | hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status); | ||
1113 | } | 826 | } |
1114 | 827 | ||
1115 | static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, | 828 | static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, |
@@ -1119,22 +832,8 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, | |||
1119 | 832 | ||
1120 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 833 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
1121 | 834 | ||
1122 | if (!rp->status) { | 835 | if (!rp->status) |
1123 | hdev->adv_tx_power = rp->tx_power; | 836 | hdev->adv_tx_power = rp->tx_power; |
1124 | if (!test_bit(HCI_INIT, &hdev->flags)) | ||
1125 | hci_update_ad(hdev); | ||
1126 | } | ||
1127 | |||
1128 | hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status); | ||
1129 | } | ||
1130 | |||
1131 | static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) | ||
1132 | { | ||
1133 | __u8 status = *((__u8 *) skb->data); | ||
1134 | |||
1135 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1136 | |||
1137 | hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status); | ||
1138 | } | 837 | } |
1139 | 838 | ||
1140 | static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) | 839 | static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1231,12 +930,15 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
1231 | clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | 930 | clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); |
1232 | } | 931 | } |
1233 | 932 | ||
1234 | hci_dev_unlock(hdev); | 933 | if (!test_bit(HCI_INIT, &hdev->flags)) { |
934 | struct hci_request req; | ||
1235 | 935 | ||
1236 | if (!test_bit(HCI_INIT, &hdev->flags)) | 936 | hci_req_init(&req, hdev); |
1237 | hci_update_ad(hdev); | 937 | hci_update_ad(&req); |
938 | hci_req_run(&req, NULL); | ||
939 | } | ||
1238 | 940 | ||
1239 | hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status); | 941 | hci_dev_unlock(hdev); |
1240 | } | 942 | } |
1241 | 943 | ||
1242 | static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | 944 | static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1245,8 +947,6 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | |||
1245 | 947 | ||
1246 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 948 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1247 | 949 | ||
1248 | hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); | ||
1249 | |||
1250 | if (status) { | 950 | if (status) { |
1251 | hci_dev_lock(hdev); | 951 | hci_dev_lock(hdev); |
1252 | mgmt_start_discovery_failed(hdev, status); | 952 | mgmt_start_discovery_failed(hdev, status); |
@@ -1269,8 +969,6 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
1269 | 969 | ||
1270 | switch (cp->enable) { | 970 | switch (cp->enable) { |
1271 | case LE_SCANNING_ENABLED: | 971 | case LE_SCANNING_ENABLED: |
1272 | hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); | ||
1273 | |||
1274 | if (status) { | 972 | if (status) { |
1275 | hci_dev_lock(hdev); | 973 | hci_dev_lock(hdev); |
1276 | mgmt_start_discovery_failed(hdev, status); | 974 | mgmt_start_discovery_failed(hdev, status); |
@@ -1321,32 +1019,6 @@ static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, | |||
1321 | 1019 | ||
1322 | if (!rp->status) | 1020 | if (!rp->status) |
1323 | hdev->le_white_list_size = rp->size; | 1021 | hdev->le_white_list_size = rp->size; |
1324 | |||
1325 | hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status); | ||
1326 | } | ||
1327 | |||
1328 | static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) | ||
1329 | { | ||
1330 | struct hci_rp_le_ltk_reply *rp = (void *) skb->data; | ||
1331 | |||
1332 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
1333 | |||
1334 | if (rp->status) | ||
1335 | return; | ||
1336 | |||
1337 | hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); | ||
1338 | } | ||
1339 | |||
1340 | static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) | ||
1341 | { | ||
1342 | struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; | ||
1343 | |||
1344 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
1345 | |||
1346 | if (rp->status) | ||
1347 | return; | ||
1348 | |||
1349 | hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); | ||
1350 | } | 1022 | } |
1351 | 1023 | ||
1352 | static void hci_cc_le_read_supported_states(struct hci_dev *hdev, | 1024 | static void hci_cc_le_read_supported_states(struct hci_dev *hdev, |
@@ -1358,8 +1030,6 @@ static void hci_cc_le_read_supported_states(struct hci_dev *hdev, | |||
1358 | 1030 | ||
1359 | if (!rp->status) | 1031 | if (!rp->status) |
1360 | memcpy(hdev->le_states, rp->le_states, 8); | 1032 | memcpy(hdev->le_states, rp->le_states, 8); |
1361 | |||
1362 | hci_req_complete(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, rp->status); | ||
1363 | } | 1033 | } |
1364 | 1034 | ||
1365 | static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | 1035 | static void hci_cc_write_le_host_supported(struct hci_dev *hdev, |
@@ -1389,8 +1059,6 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | |||
1389 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && | 1059 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && |
1390 | !test_bit(HCI_INIT, &hdev->flags)) | 1060 | !test_bit(HCI_INIT, &hdev->flags)) |
1391 | mgmt_le_enable_complete(hdev, sent->le, status); | 1061 | mgmt_le_enable_complete(hdev, sent->le, status); |
1392 | |||
1393 | hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); | ||
1394 | } | 1062 | } |
1395 | 1063 | ||
1396 | static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, | 1064 | static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, |
@@ -1412,7 +1080,6 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | |||
1412 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1080 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1413 | 1081 | ||
1414 | if (status) { | 1082 | if (status) { |
1415 | hci_req_complete(hdev, HCI_OP_INQUIRY, status); | ||
1416 | hci_conn_check_pending(hdev); | 1083 | hci_conn_check_pending(hdev); |
1417 | hci_dev_lock(hdev); | 1084 | hci_dev_lock(hdev); |
1418 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | 1085 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) |
@@ -1884,11 +1551,6 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) | |||
1884 | } | 1551 | } |
1885 | } | 1552 | } |
1886 | 1553 | ||
1887 | static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) | ||
1888 | { | ||
1889 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1890 | } | ||
1891 | |||
1892 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) | 1554 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) |
1893 | { | 1555 | { |
1894 | struct hci_cp_create_phy_link *cp; | 1556 | struct hci_cp_create_phy_link *cp; |
@@ -1930,11 +1592,6 @@ static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) | |||
1930 | amp_write_remote_assoc(hdev, cp->phy_handle); | 1592 | amp_write_remote_assoc(hdev, cp->phy_handle); |
1931 | } | 1593 | } |
1932 | 1594 | ||
1933 | static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status) | ||
1934 | { | ||
1935 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1936 | } | ||
1937 | |||
1938 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1595 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1939 | { | 1596 | { |
1940 | __u8 status = *((__u8 *) skb->data); | 1597 | __u8 status = *((__u8 *) skb->data); |
@@ -1943,7 +1600,7 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1943 | 1600 | ||
1944 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1601 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1945 | 1602 | ||
1946 | hci_req_complete(hdev, HCI_OP_INQUIRY, status); | 1603 | hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status); |
1947 | 1604 | ||
1948 | hci_conn_check_pending(hdev); | 1605 | hci_conn_check_pending(hdev); |
1949 | 1606 | ||
@@ -2399,7 +2056,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2399 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); | 2056 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); |
2400 | 2057 | ||
2401 | if (ev->status && conn->state == BT_CONNECTED) { | 2058 | if (ev->status && conn->state == BT_CONNECTED) { |
2402 | hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); | 2059 | hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); |
2403 | hci_conn_put(conn); | 2060 | hci_conn_put(conn); |
2404 | goto unlock; | 2061 | goto unlock; |
2405 | } | 2062 | } |
@@ -2491,20 +2148,10 @@ unlock: | |||
2491 | hci_dev_unlock(hdev); | 2148 | hci_dev_unlock(hdev); |
2492 | } | 2149 | } |
2493 | 2150 | ||
2494 | static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
2495 | { | ||
2496 | BT_DBG("%s", hdev->name); | ||
2497 | } | ||
2498 | |||
2499 | static void hci_qos_setup_complete_evt(struct hci_dev *hdev, | ||
2500 | struct sk_buff *skb) | ||
2501 | { | ||
2502 | BT_DBG("%s", hdev->name); | ||
2503 | } | ||
2504 | |||
2505 | static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2151 | static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2506 | { | 2152 | { |
2507 | struct hci_ev_cmd_complete *ev = (void *) skb->data; | 2153 | struct hci_ev_cmd_complete *ev = (void *) skb->data; |
2154 | u8 status = skb->data[sizeof(*ev)]; | ||
2508 | __u16 opcode; | 2155 | __u16 opcode; |
2509 | 2156 | ||
2510 | skb_pull(skb, sizeof(*ev)); | 2157 | skb_pull(skb, sizeof(*ev)); |
@@ -2588,10 +2235,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2588 | hci_cc_write_voice_setting(hdev, skb); | 2235 | hci_cc_write_voice_setting(hdev, skb); |
2589 | break; | 2236 | break; |
2590 | 2237 | ||
2591 | case HCI_OP_HOST_BUFFER_SIZE: | ||
2592 | hci_cc_host_buffer_size(hdev, skb); | ||
2593 | break; | ||
2594 | |||
2595 | case HCI_OP_WRITE_SSP_MODE: | 2238 | case HCI_OP_WRITE_SSP_MODE: |
2596 | hci_cc_write_ssp_mode(hdev, skb); | 2239 | hci_cc_write_ssp_mode(hdev, skb); |
2597 | break; | 2240 | break; |
@@ -2620,46 +2263,42 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2620 | hci_cc_read_bd_addr(hdev, skb); | 2263 | hci_cc_read_bd_addr(hdev, skb); |
2621 | break; | 2264 | break; |
2622 | 2265 | ||
2623 | case HCI_OP_READ_DATA_BLOCK_SIZE: | 2266 | case HCI_OP_READ_PAGE_SCAN_ACTIVITY: |
2624 | hci_cc_read_data_block_size(hdev, skb); | 2267 | hci_cc_read_page_scan_activity(hdev, skb); |
2625 | break; | 2268 | break; |
2626 | 2269 | ||
2627 | case HCI_OP_WRITE_CA_TIMEOUT: | 2270 | case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY: |
2628 | hci_cc_write_ca_timeout(hdev, skb); | 2271 | hci_cc_write_page_scan_activity(hdev, skb); |
2629 | break; | 2272 | break; |
2630 | 2273 | ||
2631 | case HCI_OP_READ_FLOW_CONTROL_MODE: | 2274 | case HCI_OP_READ_PAGE_SCAN_TYPE: |
2632 | hci_cc_read_flow_control_mode(hdev, skb); | 2275 | hci_cc_read_page_scan_type(hdev, skb); |
2633 | break; | 2276 | break; |
2634 | 2277 | ||
2635 | case HCI_OP_READ_LOCAL_AMP_INFO: | 2278 | case HCI_OP_WRITE_PAGE_SCAN_TYPE: |
2636 | hci_cc_read_local_amp_info(hdev, skb); | 2279 | hci_cc_write_page_scan_type(hdev, skb); |
2637 | break; | 2280 | break; |
2638 | 2281 | ||
2639 | case HCI_OP_READ_LOCAL_AMP_ASSOC: | 2282 | case HCI_OP_READ_DATA_BLOCK_SIZE: |
2640 | hci_cc_read_local_amp_assoc(hdev, skb); | 2283 | hci_cc_read_data_block_size(hdev, skb); |
2641 | break; | 2284 | break; |
2642 | 2285 | ||
2643 | case HCI_OP_DELETE_STORED_LINK_KEY: | 2286 | case HCI_OP_READ_FLOW_CONTROL_MODE: |
2644 | hci_cc_delete_stored_link_key(hdev, skb); | 2287 | hci_cc_read_flow_control_mode(hdev, skb); |
2645 | break; | 2288 | break; |
2646 | 2289 | ||
2647 | case HCI_OP_SET_EVENT_MASK: | 2290 | case HCI_OP_READ_LOCAL_AMP_INFO: |
2648 | hci_cc_set_event_mask(hdev, skb); | 2291 | hci_cc_read_local_amp_info(hdev, skb); |
2649 | break; | 2292 | break; |
2650 | 2293 | ||
2651 | case HCI_OP_WRITE_INQUIRY_MODE: | 2294 | case HCI_OP_READ_LOCAL_AMP_ASSOC: |
2652 | hci_cc_write_inquiry_mode(hdev, skb); | 2295 | hci_cc_read_local_amp_assoc(hdev, skb); |
2653 | break; | 2296 | break; |
2654 | 2297 | ||
2655 | case HCI_OP_READ_INQ_RSP_TX_POWER: | 2298 | case HCI_OP_READ_INQ_RSP_TX_POWER: |
2656 | hci_cc_read_inq_rsp_tx_power(hdev, skb); | 2299 | hci_cc_read_inq_rsp_tx_power(hdev, skb); |
2657 | break; | 2300 | break; |
2658 | 2301 | ||
2659 | case HCI_OP_SET_EVENT_FLT: | ||
2660 | hci_cc_set_event_flt(hdev, skb); | ||
2661 | break; | ||
2662 | |||
2663 | case HCI_OP_PIN_CODE_REPLY: | 2302 | case HCI_OP_PIN_CODE_REPLY: |
2664 | hci_cc_pin_code_reply(hdev, skb); | 2303 | hci_cc_pin_code_reply(hdev, skb); |
2665 | break; | 2304 | break; |
@@ -2684,10 +2323,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2684 | hci_cc_le_read_adv_tx_power(hdev, skb); | 2323 | hci_cc_le_read_adv_tx_power(hdev, skb); |
2685 | break; | 2324 | break; |
2686 | 2325 | ||
2687 | case HCI_OP_LE_SET_EVENT_MASK: | ||
2688 | hci_cc_le_set_event_mask(hdev, skb); | ||
2689 | break; | ||
2690 | |||
2691 | case HCI_OP_USER_CONFIRM_REPLY: | 2326 | case HCI_OP_USER_CONFIRM_REPLY: |
2692 | hci_cc_user_confirm_reply(hdev, skb); | 2327 | hci_cc_user_confirm_reply(hdev, skb); |
2693 | break; | 2328 | break; |
@@ -2720,14 +2355,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2720 | hci_cc_le_read_white_list_size(hdev, skb); | 2355 | hci_cc_le_read_white_list_size(hdev, skb); |
2721 | break; | 2356 | break; |
2722 | 2357 | ||
2723 | case HCI_OP_LE_LTK_REPLY: | ||
2724 | hci_cc_le_ltk_reply(hdev, skb); | ||
2725 | break; | ||
2726 | |||
2727 | case HCI_OP_LE_LTK_NEG_REPLY: | ||
2728 | hci_cc_le_ltk_neg_reply(hdev, skb); | ||
2729 | break; | ||
2730 | |||
2731 | case HCI_OP_LE_READ_SUPPORTED_STATES: | 2358 | case HCI_OP_LE_READ_SUPPORTED_STATES: |
2732 | hci_cc_le_read_supported_states(hdev, skb); | 2359 | hci_cc_le_read_supported_states(hdev, skb); |
2733 | break; | 2360 | break; |
@@ -2745,9 +2372,11 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2745 | break; | 2372 | break; |
2746 | } | 2373 | } |
2747 | 2374 | ||
2748 | if (ev->opcode != HCI_OP_NOP) | 2375 | if (opcode != HCI_OP_NOP) |
2749 | del_timer(&hdev->cmd_timer); | 2376 | del_timer(&hdev->cmd_timer); |
2750 | 2377 | ||
2378 | hci_req_cmd_complete(hdev, opcode, status); | ||
2379 | |||
2751 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { | 2380 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { |
2752 | atomic_set(&hdev->cmd_cnt, 1); | 2381 | atomic_set(&hdev->cmd_cnt, 1); |
2753 | if (!skb_queue_empty(&hdev->cmd_q)) | 2382 | if (!skb_queue_empty(&hdev->cmd_q)) |
@@ -2817,10 +2446,6 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2817 | hci_cs_le_create_conn(hdev, ev->status); | 2446 | hci_cs_le_create_conn(hdev, ev->status); |
2818 | break; | 2447 | break; |
2819 | 2448 | ||
2820 | case HCI_OP_LE_START_ENC: | ||
2821 | hci_cs_le_start_enc(hdev, ev->status); | ||
2822 | break; | ||
2823 | |||
2824 | case HCI_OP_CREATE_PHY_LINK: | 2449 | case HCI_OP_CREATE_PHY_LINK: |
2825 | hci_cs_create_phylink(hdev, ev->status); | 2450 | hci_cs_create_phylink(hdev, ev->status); |
2826 | break; | 2451 | break; |
@@ -2829,18 +2454,16 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2829 | hci_cs_accept_phylink(hdev, ev->status); | 2454 | hci_cs_accept_phylink(hdev, ev->status); |
2830 | break; | 2455 | break; |
2831 | 2456 | ||
2832 | case HCI_OP_CREATE_LOGICAL_LINK: | ||
2833 | hci_cs_create_logical_link(hdev, ev->status); | ||
2834 | break; | ||
2835 | |||
2836 | default: | 2457 | default: |
2837 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); | 2458 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); |
2838 | break; | 2459 | break; |
2839 | } | 2460 | } |
2840 | 2461 | ||
2841 | if (ev->opcode != HCI_OP_NOP) | 2462 | if (opcode != HCI_OP_NOP) |
2842 | del_timer(&hdev->cmd_timer); | 2463 | del_timer(&hdev->cmd_timer); |
2843 | 2464 | ||
2465 | hci_req_cmd_status(hdev, opcode, ev->status); | ||
2466 | |||
2844 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { | 2467 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { |
2845 | atomic_set(&hdev->cmd_cnt, 1); | 2468 | atomic_set(&hdev->cmd_cnt, 1); |
2846 | if (!skb_queue_empty(&hdev->cmd_q)) | 2469 | if (!skb_queue_empty(&hdev->cmd_q)) |
@@ -3391,18 +3014,6 @@ unlock: | |||
3391 | hci_dev_unlock(hdev); | 3014 | hci_dev_unlock(hdev); |
3392 | } | 3015 | } |
3393 | 3016 | ||
3394 | static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
3395 | { | ||
3396 | BT_DBG("%s", hdev->name); | ||
3397 | } | ||
3398 | |||
3399 | static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
3400 | { | ||
3401 | struct hci_ev_sniff_subrate *ev = (void *) skb->data; | ||
3402 | |||
3403 | BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); | ||
3404 | } | ||
3405 | |||
3406 | static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, | 3017 | static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, |
3407 | struct sk_buff *skb) | 3018 | struct sk_buff *skb) |
3408 | { | 3019 | { |
@@ -3472,7 +3083,7 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev, | |||
3472 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); | 3083 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); |
3473 | 3084 | ||
3474 | if (ev->status && conn->state == BT_CONNECTED) { | 3085 | if (ev->status && conn->state == BT_CONNECTED) { |
3475 | hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); | 3086 | hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); |
3476 | hci_conn_put(conn); | 3087 | hci_conn_put(conn); |
3477 | goto unlock; | 3088 | goto unlock; |
3478 | } | 3089 | } |
@@ -4130,14 +3741,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
4130 | hci_remote_features_evt(hdev, skb); | 3741 | hci_remote_features_evt(hdev, skb); |
4131 | break; | 3742 | break; |
4132 | 3743 | ||
4133 | case HCI_EV_REMOTE_VERSION: | ||
4134 | hci_remote_version_evt(hdev, skb); | ||
4135 | break; | ||
4136 | |||
4137 | case HCI_EV_QOS_SETUP_COMPLETE: | ||
4138 | hci_qos_setup_complete_evt(hdev, skb); | ||
4139 | break; | ||
4140 | |||
4141 | case HCI_EV_CMD_COMPLETE: | 3744 | case HCI_EV_CMD_COMPLETE: |
4142 | hci_cmd_complete_evt(hdev, skb); | 3745 | hci_cmd_complete_evt(hdev, skb); |
4143 | break; | 3746 | break; |
@@ -4194,14 +3797,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
4194 | hci_sync_conn_complete_evt(hdev, skb); | 3797 | hci_sync_conn_complete_evt(hdev, skb); |
4195 | break; | 3798 | break; |
4196 | 3799 | ||
4197 | case HCI_EV_SYNC_CONN_CHANGED: | ||
4198 | hci_sync_conn_changed_evt(hdev, skb); | ||
4199 | break; | ||
4200 | |||
4201 | case HCI_EV_SNIFF_SUBRATE: | ||
4202 | hci_sniff_subrate_evt(hdev, skb); | ||
4203 | break; | ||
4204 | |||
4205 | case HCI_EV_EXTENDED_INQUIRY_RESULT: | 3800 | case HCI_EV_EXTENDED_INQUIRY_RESULT: |
4206 | hci_extended_inquiry_result_evt(hdev, skb); | 3801 | hci_extended_inquiry_result_evt(hdev, skb); |
4207 | break; | 3802 | break; |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 6a93614f2c49..aa4354fca77c 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -854,6 +854,11 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
854 | skb_queue_tail(&hdev->raw_q, skb); | 854 | skb_queue_tail(&hdev->raw_q, skb); |
855 | queue_work(hdev->workqueue, &hdev->tx_work); | 855 | queue_work(hdev->workqueue, &hdev->tx_work); |
856 | } else { | 856 | } else { |
857 | /* Stand-alone HCI commands must be flaged as | ||
858 | * single-command requests. | ||
859 | */ | ||
860 | bt_cb(skb)->req.start = true; | ||
861 | |||
857 | skb_queue_tail(&hdev->cmd_q, skb); | 862 | skb_queue_tail(&hdev->cmd_q, skb); |
858 | queue_work(hdev->workqueue, &hdev->cmd_work); | 863 | queue_work(hdev->workqueue, &hdev->cmd_work); |
859 | } | 864 | } |
@@ -1121,8 +1126,6 @@ error: | |||
1121 | void hci_sock_cleanup(void) | 1126 | void hci_sock_cleanup(void) |
1122 | { | 1127 | { |
1123 | bt_procfs_cleanup(&init_net, "hci"); | 1128 | bt_procfs_cleanup(&init_net, "hci"); |
1124 | if (bt_sock_unregister(BTPROTO_HCI) < 0) | 1129 | bt_sock_unregister(BTPROTO_HCI); |
1125 | BT_ERR("HCI socket unregistration failed"); | ||
1126 | |||
1127 | proto_unregister(&hci_sk_proto); | 1130 | proto_unregister(&hci_sk_proto); |
1128 | } | 1131 | } |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 23b4e242a31a..ff38561385de 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -590,10 +590,8 @@ int __init bt_sysfs_init(void) | |||
590 | bt_debugfs = debugfs_create_dir("bluetooth", NULL); | 590 | bt_debugfs = debugfs_create_dir("bluetooth", NULL); |
591 | 591 | ||
592 | bt_class = class_create(THIS_MODULE, "bluetooth"); | 592 | bt_class = class_create(THIS_MODULE, "bluetooth"); |
593 | if (IS_ERR(bt_class)) | ||
594 | return PTR_ERR(bt_class); | ||
595 | 593 | ||
596 | return 0; | 594 | return PTR_RET(bt_class); |
597 | } | 595 | } |
598 | 596 | ||
599 | void bt_sysfs_cleanup(void) | 597 | void bt_sysfs_cleanup(void) |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index a7352ff3fd1e..2342327f3335 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -311,6 +311,9 @@ static int hidp_get_raw_report(struct hid_device *hid, | |||
311 | int numbered_reports = hid->report_enum[report_type].numbered; | 311 | int numbered_reports = hid->report_enum[report_type].numbered; |
312 | int ret; | 312 | int ret; |
313 | 313 | ||
314 | if (atomic_read(&session->terminate)) | ||
315 | return -EIO; | ||
316 | |||
314 | switch (report_type) { | 317 | switch (report_type) { |
315 | case HID_FEATURE_REPORT: | 318 | case HID_FEATURE_REPORT: |
316 | report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE; | 319 | report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE; |
@@ -722,6 +725,7 @@ static int hidp_session(void *arg) | |||
722 | set_current_state(TASK_INTERRUPTIBLE); | 725 | set_current_state(TASK_INTERRUPTIBLE); |
723 | } | 726 | } |
724 | set_current_state(TASK_RUNNING); | 727 | set_current_state(TASK_RUNNING); |
728 | atomic_inc(&session->terminate); | ||
725 | remove_wait_queue(sk_sleep(intr_sk), &intr_wait); | 729 | remove_wait_queue(sk_sleep(intr_sk), &intr_wait); |
726 | remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait); | 730 | remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait); |
727 | 731 | ||
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 82a829d90b0f..5d0f1ca0a314 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c | |||
@@ -304,8 +304,6 @@ error: | |||
304 | void __exit hidp_cleanup_sockets(void) | 304 | void __exit hidp_cleanup_sockets(void) |
305 | { | 305 | { |
306 | bt_procfs_cleanup(&init_net, "hidp"); | 306 | bt_procfs_cleanup(&init_net, "hidp"); |
307 | if (bt_sock_unregister(BTPROTO_HIDP) < 0) | 307 | bt_sock_unregister(BTPROTO_HIDP); |
308 | BT_ERR("Can't unregister HIDP socket"); | ||
309 | |||
310 | proto_unregister(&hidp_proto); | 308 | proto_unregister(&hidp_proto); |
311 | } | 309 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 1bcfb8422fdc..7f9704993b74 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -1312,8 +1312,6 @@ error: | |||
1312 | void l2cap_cleanup_sockets(void) | 1312 | void l2cap_cleanup_sockets(void) |
1313 | { | 1313 | { |
1314 | bt_procfs_cleanup(&init_net, "l2cap"); | 1314 | bt_procfs_cleanup(&init_net, "l2cap"); |
1315 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) | 1315 | bt_sock_unregister(BTPROTO_L2CAP); |
1316 | BT_ERR("L2CAP socket unregistration failed"); | ||
1317 | |||
1318 | proto_unregister(&l2cap_proto); | 1316 | proto_unregister(&l2cap_proto); |
1319 | } | 1317 | } |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 39395c7144aa..03e7e732215f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -384,7 +384,8 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
384 | 384 | ||
385 | if (lmp_bredr_capable(hdev)) { | 385 | if (lmp_bredr_capable(hdev)) { |
386 | settings |= MGMT_SETTING_CONNECTABLE; | 386 | settings |= MGMT_SETTING_CONNECTABLE; |
387 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | 387 | if (hdev->hci_ver >= BLUETOOTH_VER_1_2) |
388 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
388 | settings |= MGMT_SETTING_DISCOVERABLE; | 389 | settings |= MGMT_SETTING_DISCOVERABLE; |
389 | settings |= MGMT_SETTING_BREDR; | 390 | settings |= MGMT_SETTING_BREDR; |
390 | settings |= MGMT_SETTING_LINK_SECURITY; | 391 | settings |= MGMT_SETTING_LINK_SECURITY; |
@@ -409,6 +410,9 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
409 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 410 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) |
410 | settings |= MGMT_SETTING_CONNECTABLE; | 411 | settings |= MGMT_SETTING_CONNECTABLE; |
411 | 412 | ||
413 | if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) | ||
414 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
415 | |||
412 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 416 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) |
413 | settings |= MGMT_SETTING_DISCOVERABLE; | 417 | settings |= MGMT_SETTING_DISCOVERABLE; |
414 | 418 | ||
@@ -591,32 +595,33 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | |||
591 | ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | 595 | ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); |
592 | } | 596 | } |
593 | 597 | ||
594 | static int update_eir(struct hci_dev *hdev) | 598 | static void update_eir(struct hci_request *req) |
595 | { | 599 | { |
600 | struct hci_dev *hdev = req->hdev; | ||
596 | struct hci_cp_write_eir cp; | 601 | struct hci_cp_write_eir cp; |
597 | 602 | ||
598 | if (!hdev_is_powered(hdev)) | 603 | if (!hdev_is_powered(hdev)) |
599 | return 0; | 604 | return; |
600 | 605 | ||
601 | if (!lmp_ext_inq_capable(hdev)) | 606 | if (!lmp_ext_inq_capable(hdev)) |
602 | return 0; | 607 | return; |
603 | 608 | ||
604 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 609 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) |
605 | return 0; | 610 | return; |
606 | 611 | ||
607 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 612 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
608 | return 0; | 613 | return; |
609 | 614 | ||
610 | memset(&cp, 0, sizeof(cp)); | 615 | memset(&cp, 0, sizeof(cp)); |
611 | 616 | ||
612 | create_eir(hdev, cp.data); | 617 | create_eir(hdev, cp.data); |
613 | 618 | ||
614 | if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) | 619 | if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) |
615 | return 0; | 620 | return; |
616 | 621 | ||
617 | memcpy(hdev->eir, cp.data, sizeof(cp.data)); | 622 | memcpy(hdev->eir, cp.data, sizeof(cp.data)); |
618 | 623 | ||
619 | return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | 624 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); |
620 | } | 625 | } |
621 | 626 | ||
622 | static u8 get_service_classes(struct hci_dev *hdev) | 627 | static u8 get_service_classes(struct hci_dev *hdev) |
@@ -630,47 +635,48 @@ static u8 get_service_classes(struct hci_dev *hdev) | |||
630 | return val; | 635 | return val; |
631 | } | 636 | } |
632 | 637 | ||
633 | static int update_class(struct hci_dev *hdev) | 638 | static void update_class(struct hci_request *req) |
634 | { | 639 | { |
640 | struct hci_dev *hdev = req->hdev; | ||
635 | u8 cod[3]; | 641 | u8 cod[3]; |
636 | int err; | ||
637 | 642 | ||
638 | BT_DBG("%s", hdev->name); | 643 | BT_DBG("%s", hdev->name); |
639 | 644 | ||
640 | if (!hdev_is_powered(hdev)) | 645 | if (!hdev_is_powered(hdev)) |
641 | return 0; | 646 | return; |
642 | 647 | ||
643 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 648 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
644 | return 0; | 649 | return; |
645 | 650 | ||
646 | cod[0] = hdev->minor_class; | 651 | cod[0] = hdev->minor_class; |
647 | cod[1] = hdev->major_class; | 652 | cod[1] = hdev->major_class; |
648 | cod[2] = get_service_classes(hdev); | 653 | cod[2] = get_service_classes(hdev); |
649 | 654 | ||
650 | if (memcmp(cod, hdev->dev_class, 3) == 0) | 655 | if (memcmp(cod, hdev->dev_class, 3) == 0) |
651 | return 0; | 656 | return; |
652 | |||
653 | err = hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | ||
654 | if (err == 0) | ||
655 | set_bit(HCI_PENDING_CLASS, &hdev->dev_flags); | ||
656 | 657 | ||
657 | return err; | 658 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); |
658 | } | 659 | } |
659 | 660 | ||
660 | static void service_cache_off(struct work_struct *work) | 661 | static void service_cache_off(struct work_struct *work) |
661 | { | 662 | { |
662 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 663 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
663 | service_cache.work); | 664 | service_cache.work); |
665 | struct hci_request req; | ||
664 | 666 | ||
665 | if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 667 | if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
666 | return; | 668 | return; |
667 | 669 | ||
670 | hci_req_init(&req, hdev); | ||
671 | |||
668 | hci_dev_lock(hdev); | 672 | hci_dev_lock(hdev); |
669 | 673 | ||
670 | update_eir(hdev); | 674 | update_eir(&req); |
671 | update_class(hdev); | 675 | update_class(&req); |
672 | 676 | ||
673 | hci_dev_unlock(hdev); | 677 | hci_dev_unlock(hdev); |
678 | |||
679 | hci_req_run(&req, NULL); | ||
674 | } | 680 | } |
675 | 681 | ||
676 | static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) | 682 | static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) |
@@ -994,11 +1000,64 @@ failed: | |||
994 | return err; | 1000 | return err; |
995 | } | 1001 | } |
996 | 1002 | ||
1003 | static void write_fast_connectable(struct hci_request *req, bool enable) | ||
1004 | { | ||
1005 | struct hci_dev *hdev = req->hdev; | ||
1006 | struct hci_cp_write_page_scan_activity acp; | ||
1007 | u8 type; | ||
1008 | |||
1009 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | ||
1010 | return; | ||
1011 | |||
1012 | if (enable) { | ||
1013 | type = PAGE_SCAN_TYPE_INTERLACED; | ||
1014 | |||
1015 | /* 160 msec page scan interval */ | ||
1016 | acp.interval = __constant_cpu_to_le16(0x0100); | ||
1017 | } else { | ||
1018 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | ||
1019 | |||
1020 | /* default 1.28 sec page scan */ | ||
1021 | acp.interval = __constant_cpu_to_le16(0x0800); | ||
1022 | } | ||
1023 | |||
1024 | acp.window = __constant_cpu_to_le16(0x0012); | ||
1025 | |||
1026 | if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval || | ||
1027 | __cpu_to_le16(hdev->page_scan_window) != acp.window) | ||
1028 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, | ||
1029 | sizeof(acp), &acp); | ||
1030 | |||
1031 | if (hdev->page_scan_type != type) | ||
1032 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | ||
1033 | } | ||
1034 | |||
1035 | static void set_connectable_complete(struct hci_dev *hdev, u8 status) | ||
1036 | { | ||
1037 | struct pending_cmd *cmd; | ||
1038 | |||
1039 | BT_DBG("status 0x%02x", status); | ||
1040 | |||
1041 | hci_dev_lock(hdev); | ||
1042 | |||
1043 | cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); | ||
1044 | if (!cmd) | ||
1045 | goto unlock; | ||
1046 | |||
1047 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); | ||
1048 | |||
1049 | mgmt_pending_remove(cmd); | ||
1050 | |||
1051 | unlock: | ||
1052 | hci_dev_unlock(hdev); | ||
1053 | } | ||
1054 | |||
997 | static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | 1055 | static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, |
998 | u16 len) | 1056 | u16 len) |
999 | { | 1057 | { |
1000 | struct mgmt_mode *cp = data; | 1058 | struct mgmt_mode *cp = data; |
1001 | struct pending_cmd *cmd; | 1059 | struct pending_cmd *cmd; |
1060 | struct hci_request req; | ||
1002 | u8 scan; | 1061 | u8 scan; |
1003 | int err; | 1062 | int err; |
1004 | 1063 | ||
@@ -1065,7 +1124,20 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1065 | cancel_delayed_work(&hdev->discov_off); | 1124 | cancel_delayed_work(&hdev->discov_off); |
1066 | } | 1125 | } |
1067 | 1126 | ||
1068 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1127 | hci_req_init(&req, hdev); |
1128 | |||
1129 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
1130 | |||
1131 | /* If we're going from non-connectable to connectable or | ||
1132 | * vice-versa when fast connectable is enabled ensure that fast | ||
1133 | * connectable gets disabled. write_fast_connectable won't do | ||
1134 | * anything if the page scan parameters are already what they | ||
1135 | * should be. | ||
1136 | */ | ||
1137 | if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) | ||
1138 | write_fast_connectable(&req, false); | ||
1139 | |||
1140 | err = hci_req_run(&req, set_connectable_complete); | ||
1069 | if (err < 0) | 1141 | if (err < 0) |
1070 | mgmt_pending_remove(cmd); | 1142 | mgmt_pending_remove(cmd); |
1071 | 1143 | ||
@@ -1332,6 +1404,29 @@ unlock: | |||
1332 | return err; | 1404 | return err; |
1333 | } | 1405 | } |
1334 | 1406 | ||
1407 | /* This is a helper function to test for pending mgmt commands that can | ||
1408 | * cause CoD or EIR HCI commands. We can only allow one such pending | ||
1409 | * mgmt command at a time since otherwise we cannot easily track what | ||
1410 | * the current values are, will be, and based on that calculate if a new | ||
1411 | * HCI command needs to be sent and if yes with what value. | ||
1412 | */ | ||
1413 | static bool pending_eir_or_class(struct hci_dev *hdev) | ||
1414 | { | ||
1415 | struct pending_cmd *cmd; | ||
1416 | |||
1417 | list_for_each_entry(cmd, &hdev->mgmt_pending, list) { | ||
1418 | switch (cmd->opcode) { | ||
1419 | case MGMT_OP_ADD_UUID: | ||
1420 | case MGMT_OP_REMOVE_UUID: | ||
1421 | case MGMT_OP_SET_DEV_CLASS: | ||
1422 | case MGMT_OP_SET_POWERED: | ||
1423 | return true; | ||
1424 | } | ||
1425 | } | ||
1426 | |||
1427 | return false; | ||
1428 | } | ||
1429 | |||
1335 | static const u8 bluetooth_base_uuid[] = { | 1430 | static const u8 bluetooth_base_uuid[] = { |
1336 | 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, | 1431 | 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, |
1337 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 1432 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -1351,10 +1446,37 @@ static u8 get_uuid_size(const u8 *uuid) | |||
1351 | return 16; | 1446 | return 16; |
1352 | } | 1447 | } |
1353 | 1448 | ||
1449 | static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status) | ||
1450 | { | ||
1451 | struct pending_cmd *cmd; | ||
1452 | |||
1453 | hci_dev_lock(hdev); | ||
1454 | |||
1455 | cmd = mgmt_pending_find(mgmt_op, hdev); | ||
1456 | if (!cmd) | ||
1457 | goto unlock; | ||
1458 | |||
1459 | cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status), | ||
1460 | hdev->dev_class, 3); | ||
1461 | |||
1462 | mgmt_pending_remove(cmd); | ||
1463 | |||
1464 | unlock: | ||
1465 | hci_dev_unlock(hdev); | ||
1466 | } | ||
1467 | |||
1468 | static void add_uuid_complete(struct hci_dev *hdev, u8 status) | ||
1469 | { | ||
1470 | BT_DBG("status 0x%02x", status); | ||
1471 | |||
1472 | mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status); | ||
1473 | } | ||
1474 | |||
1354 | static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | 1475 | static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) |
1355 | { | 1476 | { |
1356 | struct mgmt_cp_add_uuid *cp = data; | 1477 | struct mgmt_cp_add_uuid *cp = data; |
1357 | struct pending_cmd *cmd; | 1478 | struct pending_cmd *cmd; |
1479 | struct hci_request req; | ||
1358 | struct bt_uuid *uuid; | 1480 | struct bt_uuid *uuid; |
1359 | int err; | 1481 | int err; |
1360 | 1482 | ||
@@ -1362,7 +1484,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1362 | 1484 | ||
1363 | hci_dev_lock(hdev); | 1485 | hci_dev_lock(hdev); |
1364 | 1486 | ||
1365 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | 1487 | if (pending_eir_or_class(hdev)) { |
1366 | err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID, | 1488 | err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID, |
1367 | MGMT_STATUS_BUSY); | 1489 | MGMT_STATUS_BUSY); |
1368 | goto failed; | 1490 | goto failed; |
@@ -1380,23 +1502,28 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1380 | 1502 | ||
1381 | list_add_tail(&uuid->list, &hdev->uuids); | 1503 | list_add_tail(&uuid->list, &hdev->uuids); |
1382 | 1504 | ||
1383 | err = update_class(hdev); | 1505 | hci_req_init(&req, hdev); |
1384 | if (err < 0) | ||
1385 | goto failed; | ||
1386 | 1506 | ||
1387 | err = update_eir(hdev); | 1507 | update_class(&req); |
1388 | if (err < 0) | 1508 | update_eir(&req); |
1389 | goto failed; | 1509 | |
1510 | err = hci_req_run(&req, add_uuid_complete); | ||
1511 | if (err < 0) { | ||
1512 | if (err != -ENODATA) | ||
1513 | goto failed; | ||
1390 | 1514 | ||
1391 | if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | ||
1392 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0, | 1515 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0, |
1393 | hdev->dev_class, 3); | 1516 | hdev->dev_class, 3); |
1394 | goto failed; | 1517 | goto failed; |
1395 | } | 1518 | } |
1396 | 1519 | ||
1397 | cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len); | 1520 | cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len); |
1398 | if (!cmd) | 1521 | if (!cmd) { |
1399 | err = -ENOMEM; | 1522 | err = -ENOMEM; |
1523 | goto failed; | ||
1524 | } | ||
1525 | |||
1526 | err = 0; | ||
1400 | 1527 | ||
1401 | failed: | 1528 | failed: |
1402 | hci_dev_unlock(hdev); | 1529 | hci_dev_unlock(hdev); |
@@ -1417,6 +1544,13 @@ static bool enable_service_cache(struct hci_dev *hdev) | |||
1417 | return false; | 1544 | return false; |
1418 | } | 1545 | } |
1419 | 1546 | ||
1547 | static void remove_uuid_complete(struct hci_dev *hdev, u8 status) | ||
1548 | { | ||
1549 | BT_DBG("status 0x%02x", status); | ||
1550 | |||
1551 | mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status); | ||
1552 | } | ||
1553 | |||
1420 | static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | 1554 | static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, |
1421 | u16 len) | 1555 | u16 len) |
1422 | { | 1556 | { |
@@ -1424,13 +1558,14 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1424 | struct pending_cmd *cmd; | 1558 | struct pending_cmd *cmd; |
1425 | struct bt_uuid *match, *tmp; | 1559 | struct bt_uuid *match, *tmp; |
1426 | u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | 1560 | u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
1561 | struct hci_request req; | ||
1427 | int err, found; | 1562 | int err, found; |
1428 | 1563 | ||
1429 | BT_DBG("request for %s", hdev->name); | 1564 | BT_DBG("request for %s", hdev->name); |
1430 | 1565 | ||
1431 | hci_dev_lock(hdev); | 1566 | hci_dev_lock(hdev); |
1432 | 1567 | ||
1433 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | 1568 | if (pending_eir_or_class(hdev)) { |
1434 | err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID, | 1569 | err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID, |
1435 | MGMT_STATUS_BUSY); | 1570 | MGMT_STATUS_BUSY); |
1436 | goto unlock; | 1571 | goto unlock; |
@@ -1466,34 +1601,47 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1466 | } | 1601 | } |
1467 | 1602 | ||
1468 | update_class: | 1603 | update_class: |
1469 | err = update_class(hdev); | 1604 | hci_req_init(&req, hdev); |
1470 | if (err < 0) | ||
1471 | goto unlock; | ||
1472 | 1605 | ||
1473 | err = update_eir(hdev); | 1606 | update_class(&req); |
1474 | if (err < 0) | 1607 | update_eir(&req); |
1475 | goto unlock; | 1608 | |
1609 | err = hci_req_run(&req, remove_uuid_complete); | ||
1610 | if (err < 0) { | ||
1611 | if (err != -ENODATA) | ||
1612 | goto unlock; | ||
1476 | 1613 | ||
1477 | if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | ||
1478 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0, | 1614 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0, |
1479 | hdev->dev_class, 3); | 1615 | hdev->dev_class, 3); |
1480 | goto unlock; | 1616 | goto unlock; |
1481 | } | 1617 | } |
1482 | 1618 | ||
1483 | cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len); | 1619 | cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len); |
1484 | if (!cmd) | 1620 | if (!cmd) { |
1485 | err = -ENOMEM; | 1621 | err = -ENOMEM; |
1622 | goto unlock; | ||
1623 | } | ||
1624 | |||
1625 | err = 0; | ||
1486 | 1626 | ||
1487 | unlock: | 1627 | unlock: |
1488 | hci_dev_unlock(hdev); | 1628 | hci_dev_unlock(hdev); |
1489 | return err; | 1629 | return err; |
1490 | } | 1630 | } |
1491 | 1631 | ||
1632 | static void set_class_complete(struct hci_dev *hdev, u8 status) | ||
1633 | { | ||
1634 | BT_DBG("status 0x%02x", status); | ||
1635 | |||
1636 | mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status); | ||
1637 | } | ||
1638 | |||
1492 | static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | 1639 | static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, |
1493 | u16 len) | 1640 | u16 len) |
1494 | { | 1641 | { |
1495 | struct mgmt_cp_set_dev_class *cp = data; | 1642 | struct mgmt_cp_set_dev_class *cp = data; |
1496 | struct pending_cmd *cmd; | 1643 | struct pending_cmd *cmd; |
1644 | struct hci_request req; | ||
1497 | int err; | 1645 | int err; |
1498 | 1646 | ||
1499 | BT_DBG("request for %s", hdev->name); | 1647 | BT_DBG("request for %s", hdev->name); |
@@ -1502,15 +1650,19 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1502 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | 1650 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, |
1503 | MGMT_STATUS_NOT_SUPPORTED); | 1651 | MGMT_STATUS_NOT_SUPPORTED); |
1504 | 1652 | ||
1505 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) | 1653 | hci_dev_lock(hdev); |
1506 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | ||
1507 | MGMT_STATUS_BUSY); | ||
1508 | 1654 | ||
1509 | if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) | 1655 | if (pending_eir_or_class(hdev)) { |
1510 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | 1656 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, |
1511 | MGMT_STATUS_INVALID_PARAMS); | 1657 | MGMT_STATUS_BUSY); |
1658 | goto unlock; | ||
1659 | } | ||
1512 | 1660 | ||
1513 | hci_dev_lock(hdev); | 1661 | if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) { |
1662 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | ||
1663 | MGMT_STATUS_INVALID_PARAMS); | ||
1664 | goto unlock; | ||
1665 | } | ||
1514 | 1666 | ||
1515 | hdev->major_class = cp->major; | 1667 | hdev->major_class = cp->major; |
1516 | hdev->minor_class = cp->minor; | 1668 | hdev->minor_class = cp->minor; |
@@ -1521,26 +1673,34 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1521 | goto unlock; | 1673 | goto unlock; |
1522 | } | 1674 | } |
1523 | 1675 | ||
1676 | hci_req_init(&req, hdev); | ||
1677 | |||
1524 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { | 1678 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { |
1525 | hci_dev_unlock(hdev); | 1679 | hci_dev_unlock(hdev); |
1526 | cancel_delayed_work_sync(&hdev->service_cache); | 1680 | cancel_delayed_work_sync(&hdev->service_cache); |
1527 | hci_dev_lock(hdev); | 1681 | hci_dev_lock(hdev); |
1528 | update_eir(hdev); | 1682 | update_eir(&req); |
1529 | } | 1683 | } |
1530 | 1684 | ||
1531 | err = update_class(hdev); | 1685 | update_class(&req); |
1532 | if (err < 0) | 1686 | |
1533 | goto unlock; | 1687 | err = hci_req_run(&req, set_class_complete); |
1688 | if (err < 0) { | ||
1689 | if (err != -ENODATA) | ||
1690 | goto unlock; | ||
1534 | 1691 | ||
1535 | if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | ||
1536 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0, | 1692 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0, |
1537 | hdev->dev_class, 3); | 1693 | hdev->dev_class, 3); |
1538 | goto unlock; | 1694 | goto unlock; |
1539 | } | 1695 | } |
1540 | 1696 | ||
1541 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len); | 1697 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len); |
1542 | if (!cmd) | 1698 | if (!cmd) { |
1543 | err = -ENOMEM; | 1699 | err = -ENOMEM; |
1700 | goto unlock; | ||
1701 | } | ||
1702 | |||
1703 | err = 0; | ||
1544 | 1704 | ||
1545 | unlock: | 1705 | unlock: |
1546 | hci_dev_unlock(hdev); | 1706 | hci_dev_unlock(hdev); |
@@ -2140,7 +2300,7 @@ unlock: | |||
2140 | } | 2300 | } |
2141 | 2301 | ||
2142 | static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, | 2302 | static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, |
2143 | bdaddr_t *bdaddr, u8 type, u16 mgmt_op, | 2303 | struct mgmt_addr_info *addr, u16 mgmt_op, |
2144 | u16 hci_op, __le32 passkey) | 2304 | u16 hci_op, __le32 passkey) |
2145 | { | 2305 | { |
2146 | struct pending_cmd *cmd; | 2306 | struct pending_cmd *cmd; |
@@ -2150,37 +2310,41 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, | |||
2150 | hci_dev_lock(hdev); | 2310 | hci_dev_lock(hdev); |
2151 | 2311 | ||
2152 | if (!hdev_is_powered(hdev)) { | 2312 | if (!hdev_is_powered(hdev)) { |
2153 | err = cmd_status(sk, hdev->id, mgmt_op, | 2313 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2154 | MGMT_STATUS_NOT_POWERED); | 2314 | MGMT_STATUS_NOT_POWERED, addr, |
2315 | sizeof(*addr)); | ||
2155 | goto done; | 2316 | goto done; |
2156 | } | 2317 | } |
2157 | 2318 | ||
2158 | if (type == BDADDR_BREDR) | 2319 | if (addr->type == BDADDR_BREDR) |
2159 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr); | 2320 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr); |
2160 | else | 2321 | else |
2161 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr); | 2322 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr); |
2162 | 2323 | ||
2163 | if (!conn) { | 2324 | if (!conn) { |
2164 | err = cmd_status(sk, hdev->id, mgmt_op, | 2325 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2165 | MGMT_STATUS_NOT_CONNECTED); | 2326 | MGMT_STATUS_NOT_CONNECTED, addr, |
2327 | sizeof(*addr)); | ||
2166 | goto done; | 2328 | goto done; |
2167 | } | 2329 | } |
2168 | 2330 | ||
2169 | if (type == BDADDR_LE_PUBLIC || type == BDADDR_LE_RANDOM) { | 2331 | if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) { |
2170 | /* Continue with pairing via SMP */ | 2332 | /* Continue with pairing via SMP */ |
2171 | err = smp_user_confirm_reply(conn, mgmt_op, passkey); | 2333 | err = smp_user_confirm_reply(conn, mgmt_op, passkey); |
2172 | 2334 | ||
2173 | if (!err) | 2335 | if (!err) |
2174 | err = cmd_status(sk, hdev->id, mgmt_op, | 2336 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2175 | MGMT_STATUS_SUCCESS); | 2337 | MGMT_STATUS_SUCCESS, addr, |
2338 | sizeof(*addr)); | ||
2176 | else | 2339 | else |
2177 | err = cmd_status(sk, hdev->id, mgmt_op, | 2340 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2178 | MGMT_STATUS_FAILED); | 2341 | MGMT_STATUS_FAILED, addr, |
2342 | sizeof(*addr)); | ||
2179 | 2343 | ||
2180 | goto done; | 2344 | goto done; |
2181 | } | 2345 | } |
2182 | 2346 | ||
2183 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr)); | 2347 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr)); |
2184 | if (!cmd) { | 2348 | if (!cmd) { |
2185 | err = -ENOMEM; | 2349 | err = -ENOMEM; |
2186 | goto done; | 2350 | goto done; |
@@ -2190,11 +2354,12 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, | |||
2190 | if (hci_op == HCI_OP_USER_PASSKEY_REPLY) { | 2354 | if (hci_op == HCI_OP_USER_PASSKEY_REPLY) { |
2191 | struct hci_cp_user_passkey_reply cp; | 2355 | struct hci_cp_user_passkey_reply cp; |
2192 | 2356 | ||
2193 | bacpy(&cp.bdaddr, bdaddr); | 2357 | bacpy(&cp.bdaddr, &addr->bdaddr); |
2194 | cp.passkey = passkey; | 2358 | cp.passkey = passkey; |
2195 | err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp); | 2359 | err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp); |
2196 | } else | 2360 | } else |
2197 | err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr); | 2361 | err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr), |
2362 | &addr->bdaddr); | ||
2198 | 2363 | ||
2199 | if (err < 0) | 2364 | if (err < 0) |
2200 | mgmt_pending_remove(cmd); | 2365 | mgmt_pending_remove(cmd); |
@@ -2211,7 +2376,7 @@ static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev, | |||
2211 | 2376 | ||
2212 | BT_DBG(""); | 2377 | BT_DBG(""); |
2213 | 2378 | ||
2214 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2379 | return user_pairing_resp(sk, hdev, &cp->addr, |
2215 | MGMT_OP_PIN_CODE_NEG_REPLY, | 2380 | MGMT_OP_PIN_CODE_NEG_REPLY, |
2216 | HCI_OP_PIN_CODE_NEG_REPLY, 0); | 2381 | HCI_OP_PIN_CODE_NEG_REPLY, 0); |
2217 | } | 2382 | } |
@@ -2227,7 +2392,7 @@ static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2227 | return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY, | 2392 | return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY, |
2228 | MGMT_STATUS_INVALID_PARAMS); | 2393 | MGMT_STATUS_INVALID_PARAMS); |
2229 | 2394 | ||
2230 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2395 | return user_pairing_resp(sk, hdev, &cp->addr, |
2231 | MGMT_OP_USER_CONFIRM_REPLY, | 2396 | MGMT_OP_USER_CONFIRM_REPLY, |
2232 | HCI_OP_USER_CONFIRM_REPLY, 0); | 2397 | HCI_OP_USER_CONFIRM_REPLY, 0); |
2233 | } | 2398 | } |
@@ -2239,7 +2404,7 @@ static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev, | |||
2239 | 2404 | ||
2240 | BT_DBG(""); | 2405 | BT_DBG(""); |
2241 | 2406 | ||
2242 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2407 | return user_pairing_resp(sk, hdev, &cp->addr, |
2243 | MGMT_OP_USER_CONFIRM_NEG_REPLY, | 2408 | MGMT_OP_USER_CONFIRM_NEG_REPLY, |
2244 | HCI_OP_USER_CONFIRM_NEG_REPLY, 0); | 2409 | HCI_OP_USER_CONFIRM_NEG_REPLY, 0); |
2245 | } | 2410 | } |
@@ -2251,7 +2416,7 @@ static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2251 | 2416 | ||
2252 | BT_DBG(""); | 2417 | BT_DBG(""); |
2253 | 2418 | ||
2254 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2419 | return user_pairing_resp(sk, hdev, &cp->addr, |
2255 | MGMT_OP_USER_PASSKEY_REPLY, | 2420 | MGMT_OP_USER_PASSKEY_REPLY, |
2256 | HCI_OP_USER_PASSKEY_REPLY, cp->passkey); | 2421 | HCI_OP_USER_PASSKEY_REPLY, cp->passkey); |
2257 | } | 2422 | } |
@@ -2263,18 +2428,47 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev, | |||
2263 | 2428 | ||
2264 | BT_DBG(""); | 2429 | BT_DBG(""); |
2265 | 2430 | ||
2266 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2431 | return user_pairing_resp(sk, hdev, &cp->addr, |
2267 | MGMT_OP_USER_PASSKEY_NEG_REPLY, | 2432 | MGMT_OP_USER_PASSKEY_NEG_REPLY, |
2268 | HCI_OP_USER_PASSKEY_NEG_REPLY, 0); | 2433 | HCI_OP_USER_PASSKEY_NEG_REPLY, 0); |
2269 | } | 2434 | } |
2270 | 2435 | ||
2271 | static int update_name(struct hci_dev *hdev, const char *name) | 2436 | static void update_name(struct hci_request *req) |
2272 | { | 2437 | { |
2438 | struct hci_dev *hdev = req->hdev; | ||
2273 | struct hci_cp_write_local_name cp; | 2439 | struct hci_cp_write_local_name cp; |
2274 | 2440 | ||
2275 | memcpy(cp.name, name, sizeof(cp.name)); | 2441 | memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); |
2442 | |||
2443 | hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp); | ||
2444 | } | ||
2445 | |||
2446 | static void set_name_complete(struct hci_dev *hdev, u8 status) | ||
2447 | { | ||
2448 | struct mgmt_cp_set_local_name *cp; | ||
2449 | struct pending_cmd *cmd; | ||
2450 | |||
2451 | BT_DBG("status 0x%02x", status); | ||
2452 | |||
2453 | hci_dev_lock(hdev); | ||
2454 | |||
2455 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); | ||
2456 | if (!cmd) | ||
2457 | goto unlock; | ||
2458 | |||
2459 | cp = cmd->param; | ||
2276 | 2460 | ||
2277 | return hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp); | 2461 | if (status) |
2462 | cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, | ||
2463 | mgmt_status(status)); | ||
2464 | else | ||
2465 | cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, | ||
2466 | cp, sizeof(*cp)); | ||
2467 | |||
2468 | mgmt_pending_remove(cmd); | ||
2469 | |||
2470 | unlock: | ||
2471 | hci_dev_unlock(hdev); | ||
2278 | } | 2472 | } |
2279 | 2473 | ||
2280 | static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | 2474 | static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, |
@@ -2282,12 +2476,24 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2282 | { | 2476 | { |
2283 | struct mgmt_cp_set_local_name *cp = data; | 2477 | struct mgmt_cp_set_local_name *cp = data; |
2284 | struct pending_cmd *cmd; | 2478 | struct pending_cmd *cmd; |
2479 | struct hci_request req; | ||
2285 | int err; | 2480 | int err; |
2286 | 2481 | ||
2287 | BT_DBG(""); | 2482 | BT_DBG(""); |
2288 | 2483 | ||
2289 | hci_dev_lock(hdev); | 2484 | hci_dev_lock(hdev); |
2290 | 2485 | ||
2486 | /* If the old values are the same as the new ones just return a | ||
2487 | * direct command complete event. | ||
2488 | */ | ||
2489 | if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) && | ||
2490 | !memcmp(hdev->short_name, cp->short_name, | ||
2491 | sizeof(hdev->short_name))) { | ||
2492 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, | ||
2493 | data, len); | ||
2494 | goto failed; | ||
2495 | } | ||
2496 | |||
2291 | memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name)); | 2497 | memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name)); |
2292 | 2498 | ||
2293 | if (!hdev_is_powered(hdev)) { | 2499 | if (!hdev_is_powered(hdev)) { |
@@ -2310,7 +2516,19 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2310 | goto failed; | 2516 | goto failed; |
2311 | } | 2517 | } |
2312 | 2518 | ||
2313 | err = update_name(hdev, cp->name); | 2519 | memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name)); |
2520 | |||
2521 | hci_req_init(&req, hdev); | ||
2522 | |||
2523 | if (lmp_bredr_capable(hdev)) { | ||
2524 | update_name(&req); | ||
2525 | update_eir(&req); | ||
2526 | } | ||
2527 | |||
2528 | if (lmp_le_capable(hdev)) | ||
2529 | hci_update_ad(&req); | ||
2530 | |||
2531 | err = hci_req_run(&req, set_name_complete); | ||
2314 | if (err < 0) | 2532 | if (err < 0) |
2315 | mgmt_pending_remove(cmd); | 2533 | mgmt_pending_remove(cmd); |
2316 | 2534 | ||
@@ -2698,6 +2916,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2698 | u16 len) | 2916 | u16 len) |
2699 | { | 2917 | { |
2700 | struct mgmt_cp_set_device_id *cp = data; | 2918 | struct mgmt_cp_set_device_id *cp = data; |
2919 | struct hci_request req; | ||
2701 | int err; | 2920 | int err; |
2702 | __u16 source; | 2921 | __u16 source; |
2703 | 2922 | ||
@@ -2718,24 +2937,59 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2718 | 2937 | ||
2719 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0); | 2938 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0); |
2720 | 2939 | ||
2721 | update_eir(hdev); | 2940 | hci_req_init(&req, hdev); |
2941 | update_eir(&req); | ||
2942 | hci_req_run(&req, NULL); | ||
2722 | 2943 | ||
2723 | hci_dev_unlock(hdev); | 2944 | hci_dev_unlock(hdev); |
2724 | 2945 | ||
2725 | return err; | 2946 | return err; |
2726 | } | 2947 | } |
2727 | 2948 | ||
2949 | static void fast_connectable_complete(struct hci_dev *hdev, u8 status) | ||
2950 | { | ||
2951 | struct pending_cmd *cmd; | ||
2952 | |||
2953 | BT_DBG("status 0x%02x", status); | ||
2954 | |||
2955 | hci_dev_lock(hdev); | ||
2956 | |||
2957 | cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev); | ||
2958 | if (!cmd) | ||
2959 | goto unlock; | ||
2960 | |||
2961 | if (status) { | ||
2962 | cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | ||
2963 | mgmt_status(status)); | ||
2964 | } else { | ||
2965 | struct mgmt_mode *cp = cmd->param; | ||
2966 | |||
2967 | if (cp->val) | ||
2968 | set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags); | ||
2969 | else | ||
2970 | clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags); | ||
2971 | |||
2972 | send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev); | ||
2973 | new_settings(hdev, cmd->sk); | ||
2974 | } | ||
2975 | |||
2976 | mgmt_pending_remove(cmd); | ||
2977 | |||
2978 | unlock: | ||
2979 | hci_dev_unlock(hdev); | ||
2980 | } | ||
2981 | |||
2728 | static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | 2982 | static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, |
2729 | void *data, u16 len) | 2983 | void *data, u16 len) |
2730 | { | 2984 | { |
2731 | struct mgmt_mode *cp = data; | 2985 | struct mgmt_mode *cp = data; |
2732 | struct hci_cp_write_page_scan_activity acp; | 2986 | struct pending_cmd *cmd; |
2733 | u8 type; | 2987 | struct hci_request req; |
2734 | int err; | 2988 | int err; |
2735 | 2989 | ||
2736 | BT_DBG("%s", hdev->name); | 2990 | BT_DBG("%s", hdev->name); |
2737 | 2991 | ||
2738 | if (!lmp_bredr_capable(hdev)) | 2992 | if (!lmp_bredr_capable(hdev) || hdev->hci_ver < BLUETOOTH_VER_1_2) |
2739 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 2993 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2740 | MGMT_STATUS_NOT_SUPPORTED); | 2994 | MGMT_STATUS_NOT_SUPPORTED); |
2741 | 2995 | ||
@@ -2753,40 +3007,39 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | |||
2753 | 3007 | ||
2754 | hci_dev_lock(hdev); | 3008 | hci_dev_lock(hdev); |
2755 | 3009 | ||
2756 | if (cp->val) { | 3010 | if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) { |
2757 | type = PAGE_SCAN_TYPE_INTERLACED; | 3011 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
3012 | MGMT_STATUS_BUSY); | ||
3013 | goto unlock; | ||
3014 | } | ||
2758 | 3015 | ||
2759 | /* 160 msec page scan interval */ | 3016 | if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) { |
2760 | acp.interval = __constant_cpu_to_le16(0x0100); | 3017 | err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE, |
2761 | } else { | 3018 | hdev); |
2762 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | 3019 | goto unlock; |
3020 | } | ||
2763 | 3021 | ||
2764 | /* default 1.28 sec page scan */ | 3022 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev, |
2765 | acp.interval = __constant_cpu_to_le16(0x0800); | 3023 | data, len); |
3024 | if (!cmd) { | ||
3025 | err = -ENOMEM; | ||
3026 | goto unlock; | ||
2766 | } | 3027 | } |
2767 | 3028 | ||
2768 | /* default 11.25 msec page scan window */ | 3029 | hci_req_init(&req, hdev); |
2769 | acp.window = __constant_cpu_to_le16(0x0012); | ||
2770 | 3030 | ||
2771 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), | 3031 | write_fast_connectable(&req, cp->val); |
2772 | &acp); | ||
2773 | if (err < 0) { | ||
2774 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | ||
2775 | MGMT_STATUS_FAILED); | ||
2776 | goto done; | ||
2777 | } | ||
2778 | 3032 | ||
2779 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | 3033 | err = hci_req_run(&req, fast_connectable_complete); |
2780 | if (err < 0) { | 3034 | if (err < 0) { |
2781 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 3035 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2782 | MGMT_STATUS_FAILED); | 3036 | MGMT_STATUS_FAILED); |
2783 | goto done; | 3037 | mgmt_pending_remove(cmd); |
2784 | } | 3038 | } |
2785 | 3039 | ||
2786 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, 0, | 3040 | unlock: |
2787 | NULL, 0); | ||
2788 | done: | ||
2789 | hci_dev_unlock(hdev); | 3041 | hci_dev_unlock(hdev); |
3042 | |||
2790 | return err; | 3043 | return err; |
2791 | } | 3044 | } |
2792 | 3045 | ||
@@ -3043,79 +3296,115 @@ static void settings_rsp(struct pending_cmd *cmd, void *data) | |||
3043 | mgmt_pending_free(cmd); | 3296 | mgmt_pending_free(cmd); |
3044 | } | 3297 | } |
3045 | 3298 | ||
3046 | static int set_bredr_scan(struct hci_dev *hdev) | 3299 | static void set_bredr_scan(struct hci_request *req) |
3047 | { | 3300 | { |
3301 | struct hci_dev *hdev = req->hdev; | ||
3048 | u8 scan = 0; | 3302 | u8 scan = 0; |
3049 | 3303 | ||
3304 | /* Ensure that fast connectable is disabled. This function will | ||
3305 | * not do anything if the page scan parameters are already what | ||
3306 | * they should be. | ||
3307 | */ | ||
3308 | write_fast_connectable(req, false); | ||
3309 | |||
3050 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 3310 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) |
3051 | scan |= SCAN_PAGE; | 3311 | scan |= SCAN_PAGE; |
3052 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 3312 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) |
3053 | scan |= SCAN_INQUIRY; | 3313 | scan |= SCAN_INQUIRY; |
3054 | 3314 | ||
3055 | if (!scan) | 3315 | if (scan) |
3056 | return 0; | 3316 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
3057 | |||
3058 | return hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
3059 | } | 3317 | } |
3060 | 3318 | ||
3061 | int mgmt_powered(struct hci_dev *hdev, u8 powered) | 3319 | static void powered_complete(struct hci_dev *hdev, u8 status) |
3062 | { | 3320 | { |
3063 | struct cmd_lookup match = { NULL, hdev }; | 3321 | struct cmd_lookup match = { NULL, hdev }; |
3064 | int err; | ||
3065 | 3322 | ||
3066 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 3323 | BT_DBG("status 0x%02x", status); |
3067 | return 0; | 3324 | |
3325 | hci_dev_lock(hdev); | ||
3068 | 3326 | ||
3069 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | 3327 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
3070 | 3328 | ||
3071 | if (powered) { | 3329 | new_settings(hdev, match.sk); |
3072 | u8 link_sec; | ||
3073 | 3330 | ||
3074 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && | 3331 | hci_dev_unlock(hdev); |
3075 | !lmp_host_ssp_capable(hdev)) { | ||
3076 | u8 ssp = 1; | ||
3077 | 3332 | ||
3078 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); | 3333 | if (match.sk) |
3079 | } | 3334 | sock_put(match.sk); |
3335 | } | ||
3080 | 3336 | ||
3081 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | 3337 | static int powered_update_hci(struct hci_dev *hdev) |
3082 | struct hci_cp_write_le_host_supported cp; | 3338 | { |
3339 | struct hci_request req; | ||
3340 | u8 link_sec; | ||
3083 | 3341 | ||
3084 | cp.le = 1; | 3342 | hci_req_init(&req, hdev); |
3085 | cp.simul = lmp_le_br_capable(hdev); | ||
3086 | 3343 | ||
3087 | /* Check first if we already have the right | 3344 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && |
3088 | * host state (host features set) | 3345 | !lmp_host_ssp_capable(hdev)) { |
3089 | */ | 3346 | u8 ssp = 1; |
3090 | if (cp.le != lmp_host_le_capable(hdev) || | ||
3091 | cp.simul != lmp_host_le_br_capable(hdev)) | ||
3092 | hci_send_cmd(hdev, | ||
3093 | HCI_OP_WRITE_LE_HOST_SUPPORTED, | ||
3094 | sizeof(cp), &cp); | ||
3095 | } | ||
3096 | 3347 | ||
3097 | link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); | 3348 | hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp); |
3098 | if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) | 3349 | } |
3099 | hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, | ||
3100 | sizeof(link_sec), &link_sec); | ||
3101 | 3350 | ||
3102 | if (lmp_bredr_capable(hdev)) { | 3351 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { |
3103 | set_bredr_scan(hdev); | 3352 | struct hci_cp_write_le_host_supported cp; |
3104 | update_class(hdev); | ||
3105 | update_name(hdev, hdev->dev_name); | ||
3106 | update_eir(hdev); | ||
3107 | } | ||
3108 | } else { | ||
3109 | u8 status = MGMT_STATUS_NOT_POWERED; | ||
3110 | u8 zero_cod[] = { 0, 0, 0 }; | ||
3111 | 3353 | ||
3112 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 3354 | cp.le = 1; |
3355 | cp.simul = lmp_le_br_capable(hdev); | ||
3113 | 3356 | ||
3114 | if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) | 3357 | /* Check first if we already have the right |
3115 | mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, | 3358 | * host state (host features set) |
3116 | zero_cod, sizeof(zero_cod), NULL); | 3359 | */ |
3360 | if (cp.le != lmp_host_le_capable(hdev) || | ||
3361 | cp.simul != lmp_host_le_br_capable(hdev)) | ||
3362 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, | ||
3363 | sizeof(cp), &cp); | ||
3117 | } | 3364 | } |
3118 | 3365 | ||
3366 | link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); | ||
3367 | if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) | ||
3368 | hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE, | ||
3369 | sizeof(link_sec), &link_sec); | ||
3370 | |||
3371 | if (lmp_bredr_capable(hdev)) { | ||
3372 | set_bredr_scan(&req); | ||
3373 | update_class(&req); | ||
3374 | update_name(&req); | ||
3375 | update_eir(&req); | ||
3376 | } | ||
3377 | |||
3378 | return hci_req_run(&req, powered_complete); | ||
3379 | } | ||
3380 | |||
3381 | int mgmt_powered(struct hci_dev *hdev, u8 powered) | ||
3382 | { | ||
3383 | struct cmd_lookup match = { NULL, hdev }; | ||
3384 | u8 status_not_powered = MGMT_STATUS_NOT_POWERED; | ||
3385 | u8 zero_cod[] = { 0, 0, 0 }; | ||
3386 | int err; | ||
3387 | |||
3388 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
3389 | return 0; | ||
3390 | |||
3391 | if (powered) { | ||
3392 | if (powered_update_hci(hdev) == 0) | ||
3393 | return 0; | ||
3394 | |||
3395 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, | ||
3396 | &match); | ||
3397 | goto new_settings; | ||
3398 | } | ||
3399 | |||
3400 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | ||
3401 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered); | ||
3402 | |||
3403 | if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) | ||
3404 | mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, | ||
3405 | zero_cod, sizeof(zero_cod), NULL); | ||
3406 | |||
3407 | new_settings: | ||
3119 | err = new_settings(hdev, match.sk); | 3408 | err = new_settings(hdev, match.sk); |
3120 | 3409 | ||
3121 | if (match.sk) | 3410 | if (match.sk) |
@@ -3152,7 +3441,7 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | |||
3152 | 3441 | ||
3153 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | 3442 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) |
3154 | { | 3443 | { |
3155 | struct cmd_lookup match = { NULL, hdev }; | 3444 | struct pending_cmd *cmd; |
3156 | bool changed = false; | 3445 | bool changed = false; |
3157 | int err = 0; | 3446 | int err = 0; |
3158 | 3447 | ||
@@ -3164,14 +3453,10 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | |||
3164 | changed = true; | 3453 | changed = true; |
3165 | } | 3454 | } |
3166 | 3455 | ||
3167 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp, | 3456 | cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); |
3168 | &match); | ||
3169 | 3457 | ||
3170 | if (changed) | 3458 | if (changed) |
3171 | err = new_settings(hdev, match.sk); | 3459 | err = new_settings(hdev, cmd ? cmd->sk : NULL); |
3172 | |||
3173 | if (match.sk) | ||
3174 | sock_put(match.sk); | ||
3175 | 3460 | ||
3176 | return err; | 3461 | return err; |
3177 | } | 3462 | } |
@@ -3555,23 +3840,25 @@ int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) | |||
3555 | return err; | 3840 | return err; |
3556 | } | 3841 | } |
3557 | 3842 | ||
3558 | static int clear_eir(struct hci_dev *hdev) | 3843 | static void clear_eir(struct hci_request *req) |
3559 | { | 3844 | { |
3845 | struct hci_dev *hdev = req->hdev; | ||
3560 | struct hci_cp_write_eir cp; | 3846 | struct hci_cp_write_eir cp; |
3561 | 3847 | ||
3562 | if (!lmp_ext_inq_capable(hdev)) | 3848 | if (!lmp_ext_inq_capable(hdev)) |
3563 | return 0; | 3849 | return; |
3564 | 3850 | ||
3565 | memset(hdev->eir, 0, sizeof(hdev->eir)); | 3851 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
3566 | 3852 | ||
3567 | memset(&cp, 0, sizeof(cp)); | 3853 | memset(&cp, 0, sizeof(cp)); |
3568 | 3854 | ||
3569 | return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | 3855 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); |
3570 | } | 3856 | } |
3571 | 3857 | ||
3572 | int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | 3858 | int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) |
3573 | { | 3859 | { |
3574 | struct cmd_lookup match = { NULL, hdev }; | 3860 | struct cmd_lookup match = { NULL, hdev }; |
3861 | struct hci_request req; | ||
3575 | bool changed = false; | 3862 | bool changed = false; |
3576 | int err = 0; | 3863 | int err = 0; |
3577 | 3864 | ||
@@ -3604,29 +3891,26 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
3604 | if (match.sk) | 3891 | if (match.sk) |
3605 | sock_put(match.sk); | 3892 | sock_put(match.sk); |
3606 | 3893 | ||
3894 | hci_req_init(&req, hdev); | ||
3895 | |||
3607 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 3896 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) |
3608 | update_eir(hdev); | 3897 | update_eir(&req); |
3609 | else | 3898 | else |
3610 | clear_eir(hdev); | 3899 | clear_eir(&req); |
3900 | |||
3901 | hci_req_run(&req, NULL); | ||
3611 | 3902 | ||
3612 | return err; | 3903 | return err; |
3613 | } | 3904 | } |
3614 | 3905 | ||
3615 | static void class_rsp(struct pending_cmd *cmd, void *data) | 3906 | static void sk_lookup(struct pending_cmd *cmd, void *data) |
3616 | { | 3907 | { |
3617 | struct cmd_lookup *match = data; | 3908 | struct cmd_lookup *match = data; |
3618 | 3909 | ||
3619 | cmd_complete(cmd->sk, cmd->index, cmd->opcode, match->mgmt_status, | ||
3620 | match->hdev->dev_class, 3); | ||
3621 | |||
3622 | list_del(&cmd->list); | ||
3623 | |||
3624 | if (match->sk == NULL) { | 3910 | if (match->sk == NULL) { |
3625 | match->sk = cmd->sk; | 3911 | match->sk = cmd->sk; |
3626 | sock_hold(match->sk); | 3912 | sock_hold(match->sk); |
3627 | } | 3913 | } |
3628 | |||
3629 | mgmt_pending_free(cmd); | ||
3630 | } | 3914 | } |
3631 | 3915 | ||
3632 | int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | 3916 | int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, |
@@ -3635,11 +3919,9 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | |||
3635 | struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; | 3919 | struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; |
3636 | int err = 0; | 3920 | int err = 0; |
3637 | 3921 | ||
3638 | clear_bit(HCI_PENDING_CLASS, &hdev->dev_flags); | 3922 | mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match); |
3639 | 3923 | mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match); | |
3640 | mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, class_rsp, &match); | 3924 | mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match); |
3641 | mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, class_rsp, &match); | ||
3642 | mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, class_rsp, &match); | ||
3643 | 3925 | ||
3644 | if (!status) | 3926 | if (!status) |
3645 | err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, | 3927 | err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, |
@@ -3653,55 +3935,29 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | |||
3653 | 3935 | ||
3654 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) | 3936 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) |
3655 | { | 3937 | { |
3656 | struct pending_cmd *cmd; | ||
3657 | struct mgmt_cp_set_local_name ev; | 3938 | struct mgmt_cp_set_local_name ev; |
3658 | bool changed = false; | 3939 | struct pending_cmd *cmd; |
3659 | int err = 0; | ||
3660 | 3940 | ||
3661 | if (memcmp(name, hdev->dev_name, sizeof(hdev->dev_name)) != 0) { | 3941 | if (status) |
3662 | memcpy(hdev->dev_name, name, sizeof(hdev->dev_name)); | 3942 | return 0; |
3663 | changed = true; | ||
3664 | } | ||
3665 | 3943 | ||
3666 | memset(&ev, 0, sizeof(ev)); | 3944 | memset(&ev, 0, sizeof(ev)); |
3667 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); | 3945 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); |
3668 | memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH); | 3946 | memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH); |
3669 | 3947 | ||
3670 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); | 3948 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); |
3671 | if (!cmd) | 3949 | if (!cmd) { |
3672 | goto send_event; | 3950 | memcpy(hdev->dev_name, name, sizeof(hdev->dev_name)); |
3673 | |||
3674 | /* Always assume that either the short or the complete name has | ||
3675 | * changed if there was a pending mgmt command */ | ||
3676 | changed = true; | ||
3677 | 3951 | ||
3678 | if (status) { | 3952 | /* If this is a HCI command related to powering on the |
3679 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, | 3953 | * HCI dev don't send any mgmt signals. |
3680 | mgmt_status(status)); | 3954 | */ |
3681 | goto failed; | 3955 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) |
3956 | return 0; | ||
3682 | } | 3957 | } |
3683 | 3958 | ||
3684 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, &ev, | 3959 | return mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev), |
3685 | sizeof(ev)); | 3960 | cmd ? cmd->sk : NULL); |
3686 | if (err < 0) | ||
3687 | goto failed; | ||
3688 | |||
3689 | send_event: | ||
3690 | if (changed) | ||
3691 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, | ||
3692 | sizeof(ev), cmd ? cmd->sk : NULL); | ||
3693 | |||
3694 | /* EIR is taken care of separately when powering on the | ||
3695 | * adapter so only update them here if this is a name change | ||
3696 | * unrelated to power on. | ||
3697 | */ | ||
3698 | if (!test_bit(HCI_INIT, &hdev->flags)) | ||
3699 | update_eir(hdev); | ||
3700 | |||
3701 | failed: | ||
3702 | if (cmd) | ||
3703 | mgmt_pending_remove(cmd); | ||
3704 | return err; | ||
3705 | } | 3961 | } |
3706 | 3962 | ||
3707 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | 3963 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index b23e2713fea8..ca957d34b0c8 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -69,7 +69,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, | |||
69 | u8 sec_level, | 69 | u8 sec_level, |
70 | int *err); | 70 | int *err); |
71 | static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst); | 71 | static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst); |
72 | static void rfcomm_session_del(struct rfcomm_session *s); | 72 | static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s); |
73 | 73 | ||
74 | /* ---- RFCOMM frame parsing macros ---- */ | 74 | /* ---- RFCOMM frame parsing macros ---- */ |
75 | #define __get_dlci(b) ((b & 0xfc) >> 2) | 75 | #define __get_dlci(b) ((b & 0xfc) >> 2) |
@@ -108,12 +108,6 @@ static void rfcomm_schedule(void) | |||
108 | wake_up_process(rfcomm_thread); | 108 | wake_up_process(rfcomm_thread); |
109 | } | 109 | } |
110 | 110 | ||
111 | static void rfcomm_session_put(struct rfcomm_session *s) | ||
112 | { | ||
113 | if (atomic_dec_and_test(&s->refcnt)) | ||
114 | rfcomm_session_del(s); | ||
115 | } | ||
116 | |||
117 | /* ---- RFCOMM FCS computation ---- */ | 111 | /* ---- RFCOMM FCS computation ---- */ |
118 | 112 | ||
119 | /* reversed, 8-bit, poly=0x07 */ | 113 | /* reversed, 8-bit, poly=0x07 */ |
@@ -249,16 +243,14 @@ static void rfcomm_session_set_timer(struct rfcomm_session *s, long timeout) | |||
249 | { | 243 | { |
250 | BT_DBG("session %p state %ld timeout %ld", s, s->state, timeout); | 244 | BT_DBG("session %p state %ld timeout %ld", s, s->state, timeout); |
251 | 245 | ||
252 | if (!mod_timer(&s->timer, jiffies + timeout)) | 246 | mod_timer(&s->timer, jiffies + timeout); |
253 | rfcomm_session_hold(s); | ||
254 | } | 247 | } |
255 | 248 | ||
256 | static void rfcomm_session_clear_timer(struct rfcomm_session *s) | 249 | static void rfcomm_session_clear_timer(struct rfcomm_session *s) |
257 | { | 250 | { |
258 | BT_DBG("session %p state %ld", s, s->state); | 251 | BT_DBG("session %p state %ld", s, s->state); |
259 | 252 | ||
260 | if (del_timer(&s->timer)) | 253 | del_timer_sync(&s->timer); |
261 | rfcomm_session_put(s); | ||
262 | } | 254 | } |
263 | 255 | ||
264 | /* ---- RFCOMM DLCs ---- */ | 256 | /* ---- RFCOMM DLCs ---- */ |
@@ -336,8 +328,6 @@ static void rfcomm_dlc_link(struct rfcomm_session *s, struct rfcomm_dlc *d) | |||
336 | { | 328 | { |
337 | BT_DBG("dlc %p session %p", d, s); | 329 | BT_DBG("dlc %p session %p", d, s); |
338 | 330 | ||
339 | rfcomm_session_hold(s); | ||
340 | |||
341 | rfcomm_session_clear_timer(s); | 331 | rfcomm_session_clear_timer(s); |
342 | rfcomm_dlc_hold(d); | 332 | rfcomm_dlc_hold(d); |
343 | list_add(&d->list, &s->dlcs); | 333 | list_add(&d->list, &s->dlcs); |
@@ -356,8 +346,6 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d) | |||
356 | 346 | ||
357 | if (list_empty(&s->dlcs)) | 347 | if (list_empty(&s->dlcs)) |
358 | rfcomm_session_set_timer(s, RFCOMM_IDLE_TIMEOUT); | 348 | rfcomm_session_set_timer(s, RFCOMM_IDLE_TIMEOUT); |
359 | |||
360 | rfcomm_session_put(s); | ||
361 | } | 349 | } |
362 | 350 | ||
363 | static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci) | 351 | static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci) |
@@ -493,12 +481,34 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) | |||
493 | 481 | ||
494 | int rfcomm_dlc_close(struct rfcomm_dlc *d, int err) | 482 | int rfcomm_dlc_close(struct rfcomm_dlc *d, int err) |
495 | { | 483 | { |
496 | int r; | 484 | int r = 0; |
485 | struct rfcomm_dlc *d_list; | ||
486 | struct rfcomm_session *s, *s_list; | ||
487 | |||
488 | BT_DBG("dlc %p state %ld dlci %d err %d", d, d->state, d->dlci, err); | ||
497 | 489 | ||
498 | rfcomm_lock(); | 490 | rfcomm_lock(); |
499 | 491 | ||
500 | r = __rfcomm_dlc_close(d, err); | 492 | s = d->session; |
493 | if (!s) | ||
494 | goto no_session; | ||
495 | |||
496 | /* after waiting on the mutex check the session still exists | ||
497 | * then check the dlc still exists | ||
498 | */ | ||
499 | list_for_each_entry(s_list, &session_list, list) { | ||
500 | if (s_list == s) { | ||
501 | list_for_each_entry(d_list, &s->dlcs, list) { | ||
502 | if (d_list == d) { | ||
503 | r = __rfcomm_dlc_close(d, err); | ||
504 | break; | ||
505 | } | ||
506 | } | ||
507 | break; | ||
508 | } | ||
509 | } | ||
501 | 510 | ||
511 | no_session: | ||
502 | rfcomm_unlock(); | 512 | rfcomm_unlock(); |
503 | return r; | 513 | return r; |
504 | } | 514 | } |
@@ -609,7 +619,7 @@ static struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state) | |||
609 | return s; | 619 | return s; |
610 | } | 620 | } |
611 | 621 | ||
612 | static void rfcomm_session_del(struct rfcomm_session *s) | 622 | static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s) |
613 | { | 623 | { |
614 | int state = s->state; | 624 | int state = s->state; |
615 | 625 | ||
@@ -617,15 +627,14 @@ static void rfcomm_session_del(struct rfcomm_session *s) | |||
617 | 627 | ||
618 | list_del(&s->list); | 628 | list_del(&s->list); |
619 | 629 | ||
620 | if (state == BT_CONNECTED) | ||
621 | rfcomm_send_disc(s, 0); | ||
622 | |||
623 | rfcomm_session_clear_timer(s); | 630 | rfcomm_session_clear_timer(s); |
624 | sock_release(s->sock); | 631 | sock_release(s->sock); |
625 | kfree(s); | 632 | kfree(s); |
626 | 633 | ||
627 | if (state != BT_LISTEN) | 634 | if (state != BT_LISTEN) |
628 | module_put(THIS_MODULE); | 635 | module_put(THIS_MODULE); |
636 | |||
637 | return NULL; | ||
629 | } | 638 | } |
630 | 639 | ||
631 | static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) | 640 | static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) |
@@ -644,17 +653,16 @@ static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) | |||
644 | return NULL; | 653 | return NULL; |
645 | } | 654 | } |
646 | 655 | ||
647 | static void rfcomm_session_close(struct rfcomm_session *s, int err) | 656 | static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s, |
657 | int err) | ||
648 | { | 658 | { |
649 | struct rfcomm_dlc *d; | 659 | struct rfcomm_dlc *d; |
650 | struct list_head *p, *n; | 660 | struct list_head *p, *n; |
651 | 661 | ||
652 | BT_DBG("session %p state %ld err %d", s, s->state, err); | ||
653 | |||
654 | rfcomm_session_hold(s); | ||
655 | |||
656 | s->state = BT_CLOSED; | 662 | s->state = BT_CLOSED; |
657 | 663 | ||
664 | BT_DBG("session %p state %ld err %d", s, s->state, err); | ||
665 | |||
658 | /* Close all dlcs */ | 666 | /* Close all dlcs */ |
659 | list_for_each_safe(p, n, &s->dlcs) { | 667 | list_for_each_safe(p, n, &s->dlcs) { |
660 | d = list_entry(p, struct rfcomm_dlc, list); | 668 | d = list_entry(p, struct rfcomm_dlc, list); |
@@ -663,7 +671,7 @@ static void rfcomm_session_close(struct rfcomm_session *s, int err) | |||
663 | } | 671 | } |
664 | 672 | ||
665 | rfcomm_session_clear_timer(s); | 673 | rfcomm_session_clear_timer(s); |
666 | rfcomm_session_put(s); | 674 | return rfcomm_session_del(s); |
667 | } | 675 | } |
668 | 676 | ||
669 | static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, | 677 | static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, |
@@ -715,8 +723,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, | |||
715 | if (*err == 0 || *err == -EINPROGRESS) | 723 | if (*err == 0 || *err == -EINPROGRESS) |
716 | return s; | 724 | return s; |
717 | 725 | ||
718 | rfcomm_session_del(s); | 726 | return rfcomm_session_del(s); |
719 | return NULL; | ||
720 | 727 | ||
721 | failed: | 728 | failed: |
722 | sock_release(sock); | 729 | sock_release(sock); |
@@ -1105,7 +1112,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr) | |||
1105 | } | 1112 | } |
1106 | 1113 | ||
1107 | /* ---- RFCOMM frame reception ---- */ | 1114 | /* ---- RFCOMM frame reception ---- */ |
1108 | static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) | 1115 | static struct rfcomm_session *rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) |
1109 | { | 1116 | { |
1110 | BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); | 1117 | BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); |
1111 | 1118 | ||
@@ -1114,7 +1121,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) | |||
1114 | struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci); | 1121 | struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci); |
1115 | if (!d) { | 1122 | if (!d) { |
1116 | rfcomm_send_dm(s, dlci); | 1123 | rfcomm_send_dm(s, dlci); |
1117 | return 0; | 1124 | return s; |
1118 | } | 1125 | } |
1119 | 1126 | ||
1120 | switch (d->state) { | 1127 | switch (d->state) { |
@@ -1150,25 +1157,14 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) | |||
1150 | break; | 1157 | break; |
1151 | 1158 | ||
1152 | case BT_DISCONN: | 1159 | case BT_DISCONN: |
1153 | /* rfcomm_session_put is called later so don't do | 1160 | s = rfcomm_session_close(s, ECONNRESET); |
1154 | * anything here otherwise we will mess up the session | ||
1155 | * reference counter: | ||
1156 | * | ||
1157 | * (a) when we are the initiator dlc_unlink will drive | ||
1158 | * the reference counter to 0 (there is no initial put | ||
1159 | * after session_add) | ||
1160 | * | ||
1161 | * (b) when we are not the initiator rfcomm_rx_process | ||
1162 | * will explicitly call put to balance the initial hold | ||
1163 | * done after session add. | ||
1164 | */ | ||
1165 | break; | 1161 | break; |
1166 | } | 1162 | } |
1167 | } | 1163 | } |
1168 | return 0; | 1164 | return s; |
1169 | } | 1165 | } |
1170 | 1166 | ||
1171 | static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci) | 1167 | static struct rfcomm_session *rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci) |
1172 | { | 1168 | { |
1173 | int err = 0; | 1169 | int err = 0; |
1174 | 1170 | ||
@@ -1192,13 +1188,13 @@ static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci) | |||
1192 | else | 1188 | else |
1193 | err = ECONNRESET; | 1189 | err = ECONNRESET; |
1194 | 1190 | ||
1195 | s->state = BT_CLOSED; | 1191 | s = rfcomm_session_close(s, err); |
1196 | rfcomm_session_close(s, err); | ||
1197 | } | 1192 | } |
1198 | return 0; | 1193 | return s; |
1199 | } | 1194 | } |
1200 | 1195 | ||
1201 | static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci) | 1196 | static struct rfcomm_session *rfcomm_recv_disc(struct rfcomm_session *s, |
1197 | u8 dlci) | ||
1202 | { | 1198 | { |
1203 | int err = 0; | 1199 | int err = 0; |
1204 | 1200 | ||
@@ -1227,11 +1223,9 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci) | |||
1227 | else | 1223 | else |
1228 | err = ECONNRESET; | 1224 | err = ECONNRESET; |
1229 | 1225 | ||
1230 | s->state = BT_CLOSED; | 1226 | s = rfcomm_session_close(s, err); |
1231 | rfcomm_session_close(s, err); | ||
1232 | } | 1227 | } |
1233 | 1228 | return s; | |
1234 | return 0; | ||
1235 | } | 1229 | } |
1236 | 1230 | ||
1237 | void rfcomm_dlc_accept(struct rfcomm_dlc *d) | 1231 | void rfcomm_dlc_accept(struct rfcomm_dlc *d) |
@@ -1652,11 +1646,18 @@ drop: | |||
1652 | return 0; | 1646 | return 0; |
1653 | } | 1647 | } |
1654 | 1648 | ||
1655 | static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb) | 1649 | static struct rfcomm_session *rfcomm_recv_frame(struct rfcomm_session *s, |
1650 | struct sk_buff *skb) | ||
1656 | { | 1651 | { |
1657 | struct rfcomm_hdr *hdr = (void *) skb->data; | 1652 | struct rfcomm_hdr *hdr = (void *) skb->data; |
1658 | u8 type, dlci, fcs; | 1653 | u8 type, dlci, fcs; |
1659 | 1654 | ||
1655 | if (!s) { | ||
1656 | /* no session, so free socket data */ | ||
1657 | kfree_skb(skb); | ||
1658 | return s; | ||
1659 | } | ||
1660 | |||
1660 | dlci = __get_dlci(hdr->addr); | 1661 | dlci = __get_dlci(hdr->addr); |
1661 | type = __get_type(hdr->ctrl); | 1662 | type = __get_type(hdr->ctrl); |
1662 | 1663 | ||
@@ -1667,7 +1668,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb) | |||
1667 | if (__check_fcs(skb->data, type, fcs)) { | 1668 | if (__check_fcs(skb->data, type, fcs)) { |
1668 | BT_ERR("bad checksum in packet"); | 1669 | BT_ERR("bad checksum in packet"); |
1669 | kfree_skb(skb); | 1670 | kfree_skb(skb); |
1670 | return -EILSEQ; | 1671 | return s; |
1671 | } | 1672 | } |
1672 | 1673 | ||
1673 | if (__test_ea(hdr->len)) | 1674 | if (__test_ea(hdr->len)) |
@@ -1683,22 +1684,23 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb) | |||
1683 | 1684 | ||
1684 | case RFCOMM_DISC: | 1685 | case RFCOMM_DISC: |
1685 | if (__test_pf(hdr->ctrl)) | 1686 | if (__test_pf(hdr->ctrl)) |
1686 | rfcomm_recv_disc(s, dlci); | 1687 | s = rfcomm_recv_disc(s, dlci); |
1687 | break; | 1688 | break; |
1688 | 1689 | ||
1689 | case RFCOMM_UA: | 1690 | case RFCOMM_UA: |
1690 | if (__test_pf(hdr->ctrl)) | 1691 | if (__test_pf(hdr->ctrl)) |
1691 | rfcomm_recv_ua(s, dlci); | 1692 | s = rfcomm_recv_ua(s, dlci); |
1692 | break; | 1693 | break; |
1693 | 1694 | ||
1694 | case RFCOMM_DM: | 1695 | case RFCOMM_DM: |
1695 | rfcomm_recv_dm(s, dlci); | 1696 | s = rfcomm_recv_dm(s, dlci); |
1696 | break; | 1697 | break; |
1697 | 1698 | ||
1698 | case RFCOMM_UIH: | 1699 | case RFCOMM_UIH: |
1699 | if (dlci) | 1700 | if (dlci) { |
1700 | return rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb); | 1701 | rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb); |
1701 | 1702 | return s; | |
1703 | } | ||
1702 | rfcomm_recv_mcc(s, skb); | 1704 | rfcomm_recv_mcc(s, skb); |
1703 | break; | 1705 | break; |
1704 | 1706 | ||
@@ -1707,7 +1709,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb) | |||
1707 | break; | 1709 | break; |
1708 | } | 1710 | } |
1709 | kfree_skb(skb); | 1711 | kfree_skb(skb); |
1710 | return 0; | 1712 | return s; |
1711 | } | 1713 | } |
1712 | 1714 | ||
1713 | /* ---- Connection and data processing ---- */ | 1715 | /* ---- Connection and data processing ---- */ |
@@ -1844,7 +1846,7 @@ static void rfcomm_process_dlcs(struct rfcomm_session *s) | |||
1844 | } | 1846 | } |
1845 | } | 1847 | } |
1846 | 1848 | ||
1847 | static void rfcomm_process_rx(struct rfcomm_session *s) | 1849 | static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s) |
1848 | { | 1850 | { |
1849 | struct socket *sock = s->sock; | 1851 | struct socket *sock = s->sock; |
1850 | struct sock *sk = sock->sk; | 1852 | struct sock *sk = sock->sk; |
@@ -1856,17 +1858,15 @@ static void rfcomm_process_rx(struct rfcomm_session *s) | |||
1856 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | 1858 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { |
1857 | skb_orphan(skb); | 1859 | skb_orphan(skb); |
1858 | if (!skb_linearize(skb)) | 1860 | if (!skb_linearize(skb)) |
1859 | rfcomm_recv_frame(s, skb); | 1861 | s = rfcomm_recv_frame(s, skb); |
1860 | else | 1862 | else |
1861 | kfree_skb(skb); | 1863 | kfree_skb(skb); |
1862 | } | 1864 | } |
1863 | 1865 | ||
1864 | if (sk->sk_state == BT_CLOSED) { | 1866 | if (s && (sk->sk_state == BT_CLOSED)) |
1865 | if (!s->initiator) | 1867 | s = rfcomm_session_close(s, sk->sk_err); |
1866 | rfcomm_session_put(s); | ||
1867 | 1868 | ||
1868 | rfcomm_session_close(s, sk->sk_err); | 1869 | return s; |
1869 | } | ||
1870 | } | 1870 | } |
1871 | 1871 | ||
1872 | static void rfcomm_accept_connection(struct rfcomm_session *s) | 1872 | static void rfcomm_accept_connection(struct rfcomm_session *s) |
@@ -1891,8 +1891,6 @@ static void rfcomm_accept_connection(struct rfcomm_session *s) | |||
1891 | 1891 | ||
1892 | s = rfcomm_session_add(nsock, BT_OPEN); | 1892 | s = rfcomm_session_add(nsock, BT_OPEN); |
1893 | if (s) { | 1893 | if (s) { |
1894 | rfcomm_session_hold(s); | ||
1895 | |||
1896 | /* We should adjust MTU on incoming sessions. | 1894 | /* We should adjust MTU on incoming sessions. |
1897 | * L2CAP MTU minus UIH header and FCS. */ | 1895 | * L2CAP MTU minus UIH header and FCS. */ |
1898 | s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu, | 1896 | s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu, |
@@ -1903,7 +1901,7 @@ static void rfcomm_accept_connection(struct rfcomm_session *s) | |||
1903 | sock_release(nsock); | 1901 | sock_release(nsock); |
1904 | } | 1902 | } |
1905 | 1903 | ||
1906 | static void rfcomm_check_connection(struct rfcomm_session *s) | 1904 | static struct rfcomm_session *rfcomm_check_connection(struct rfcomm_session *s) |
1907 | { | 1905 | { |
1908 | struct sock *sk = s->sock->sk; | 1906 | struct sock *sk = s->sock->sk; |
1909 | 1907 | ||
@@ -1921,10 +1919,10 @@ static void rfcomm_check_connection(struct rfcomm_session *s) | |||
1921 | break; | 1919 | break; |
1922 | 1920 | ||
1923 | case BT_CLOSED: | 1921 | case BT_CLOSED: |
1924 | s->state = BT_CLOSED; | 1922 | s = rfcomm_session_close(s, sk->sk_err); |
1925 | rfcomm_session_close(s, sk->sk_err); | ||
1926 | break; | 1923 | break; |
1927 | } | 1924 | } |
1925 | return s; | ||
1928 | } | 1926 | } |
1929 | 1927 | ||
1930 | static void rfcomm_process_sessions(void) | 1928 | static void rfcomm_process_sessions(void) |
@@ -1940,7 +1938,6 @@ static void rfcomm_process_sessions(void) | |||
1940 | if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) { | 1938 | if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) { |
1941 | s->state = BT_DISCONN; | 1939 | s->state = BT_DISCONN; |
1942 | rfcomm_send_disc(s, 0); | 1940 | rfcomm_send_disc(s, 0); |
1943 | rfcomm_session_put(s); | ||
1944 | continue; | 1941 | continue; |
1945 | } | 1942 | } |
1946 | 1943 | ||
@@ -1949,21 +1946,18 @@ static void rfcomm_process_sessions(void) | |||
1949 | continue; | 1946 | continue; |
1950 | } | 1947 | } |
1951 | 1948 | ||
1952 | rfcomm_session_hold(s); | ||
1953 | |||
1954 | switch (s->state) { | 1949 | switch (s->state) { |
1955 | case BT_BOUND: | 1950 | case BT_BOUND: |
1956 | rfcomm_check_connection(s); | 1951 | s = rfcomm_check_connection(s); |
1957 | break; | 1952 | break; |
1958 | 1953 | ||
1959 | default: | 1954 | default: |
1960 | rfcomm_process_rx(s); | 1955 | s = rfcomm_process_rx(s); |
1961 | break; | 1956 | break; |
1962 | } | 1957 | } |
1963 | 1958 | ||
1964 | rfcomm_process_dlcs(s); | 1959 | if (s) |
1965 | 1960 | rfcomm_process_dlcs(s); | |
1966 | rfcomm_session_put(s); | ||
1967 | } | 1961 | } |
1968 | 1962 | ||
1969 | rfcomm_unlock(); | 1963 | rfcomm_unlock(); |
@@ -2010,10 +2004,11 @@ static int rfcomm_add_listener(bdaddr_t *ba) | |||
2010 | 2004 | ||
2011 | /* Add listening session */ | 2005 | /* Add listening session */ |
2012 | s = rfcomm_session_add(sock, BT_LISTEN); | 2006 | s = rfcomm_session_add(sock, BT_LISTEN); |
2013 | if (!s) | 2007 | if (!s) { |
2008 | err = -ENOMEM; | ||
2014 | goto failed; | 2009 | goto failed; |
2010 | } | ||
2015 | 2011 | ||
2016 | rfcomm_session_hold(s); | ||
2017 | return 0; | 2012 | return 0; |
2018 | failed: | 2013 | failed: |
2019 | sock_release(sock); | 2014 | sock_release(sock); |
@@ -2071,8 +2066,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
2071 | if (!s) | 2066 | if (!s) |
2072 | return; | 2067 | return; |
2073 | 2068 | ||
2074 | rfcomm_session_hold(s); | ||
2075 | |||
2076 | list_for_each_safe(p, n, &s->dlcs) { | 2069 | list_for_each_safe(p, n, &s->dlcs) { |
2077 | d = list_entry(p, struct rfcomm_dlc, list); | 2070 | d = list_entry(p, struct rfcomm_dlc, list); |
2078 | 2071 | ||
@@ -2104,8 +2097,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
2104 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); | 2097 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); |
2105 | } | 2098 | } |
2106 | 2099 | ||
2107 | rfcomm_session_put(s); | ||
2108 | |||
2109 | rfcomm_schedule(); | 2100 | rfcomm_schedule(); |
2110 | } | 2101 | } |
2111 | 2102 | ||
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index c23bae86263b..3786ddc45152 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -1065,8 +1065,7 @@ void __exit rfcomm_cleanup_sockets(void) | |||
1065 | 1065 | ||
1066 | debugfs_remove(rfcomm_sock_debugfs); | 1066 | debugfs_remove(rfcomm_sock_debugfs); |
1067 | 1067 | ||
1068 | if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) | 1068 | bt_sock_unregister(BTPROTO_RFCOMM); |
1069 | BT_ERR("RFCOMM socket layer unregistration failed"); | ||
1070 | 1069 | ||
1071 | proto_unregister(&rfcomm_proto); | 1070 | proto_unregister(&rfcomm_proto); |
1072 | } | 1071 | } |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 79d87d8d4f51..d919d1161ab4 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -359,6 +359,7 @@ static void __sco_sock_close(struct sock *sk) | |||
359 | sco_chan_del(sk, ECONNRESET); | 359 | sco_chan_del(sk, ECONNRESET); |
360 | break; | 360 | break; |
361 | 361 | ||
362 | case BT_CONNECT2: | ||
362 | case BT_CONNECT: | 363 | case BT_CONNECT: |
363 | case BT_DISCONN: | 364 | case BT_DISCONN: |
364 | sco_chan_del(sk, ECONNRESET); | 365 | sco_chan_del(sk, ECONNRESET); |
@@ -1111,8 +1112,7 @@ void __exit sco_exit(void) | |||
1111 | 1112 | ||
1112 | debugfs_remove(sco_debugfs); | 1113 | debugfs_remove(sco_debugfs); |
1113 | 1114 | ||
1114 | if (bt_sock_unregister(BTPROTO_SCO) < 0) | 1115 | bt_sock_unregister(BTPROTO_SCO); |
1115 | BT_ERR("SCO socket unregistration failed"); | ||
1116 | 1116 | ||
1117 | proto_unregister(&sco_proto); | 1117 | proto_unregister(&sco_proto); |
1118 | } | 1118 | } |
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 72ab1c0e3ca7..490990e3fc38 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2661,7 +2661,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2661 | list_del(&dep->list); | 2661 | list_del(&dep->list); |
2662 | mutex_unlock(&local->mtx); | 2662 | mutex_unlock(&local->mtx); |
2663 | 2663 | ||
2664 | ieee80211_roc_notify_destroy(dep); | 2664 | ieee80211_roc_notify_destroy(dep, true); |
2665 | return 0; | 2665 | return 0; |
2666 | } | 2666 | } |
2667 | 2667 | ||
@@ -2701,7 +2701,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2701 | ieee80211_start_next_roc(local); | 2701 | ieee80211_start_next_roc(local); |
2702 | mutex_unlock(&local->mtx); | 2702 | mutex_unlock(&local->mtx); |
2703 | 2703 | ||
2704 | ieee80211_roc_notify_destroy(found); | 2704 | ieee80211_roc_notify_destroy(found, true); |
2705 | } else { | 2705 | } else { |
2706 | /* work may be pending so use it all the time */ | 2706 | /* work may be pending so use it all the time */ |
2707 | found->abort = true; | 2707 | found->abort = true; |
@@ -2711,6 +2711,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2711 | 2711 | ||
2712 | /* work will clean up etc */ | 2712 | /* work will clean up etc */ |
2713 | flush_delayed_work(&found->work); | 2713 | flush_delayed_work(&found->work); |
2714 | WARN_ON(!found->to_be_freed); | ||
2715 | kfree(found); | ||
2714 | } | 2716 | } |
2715 | 2717 | ||
2716 | return 0; | 2718 | return 0; |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 166165efd8e2..03e8d2e3270e 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -79,6 +79,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
79 | enum ieee80211_chanctx_mode mode) | 79 | enum ieee80211_chanctx_mode mode) |
80 | { | 80 | { |
81 | struct ieee80211_chanctx *ctx; | 81 | struct ieee80211_chanctx *ctx; |
82 | u32 changed; | ||
82 | int err; | 83 | int err; |
83 | 84 | ||
84 | lockdep_assert_held(&local->chanctx_mtx); | 85 | lockdep_assert_held(&local->chanctx_mtx); |
@@ -95,6 +96,13 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
95 | if (!local->use_chanctx) | 96 | if (!local->use_chanctx) |
96 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; | 97 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; |
97 | 98 | ||
99 | /* acquire mutex to prevent idle from changing */ | ||
100 | mutex_lock(&local->mtx); | ||
101 | /* turn idle off *before* setting channel -- some drivers need that */ | ||
102 | changed = ieee80211_idle_off(local); | ||
103 | if (changed) | ||
104 | ieee80211_hw_config(local, changed); | ||
105 | |||
98 | if (!local->use_chanctx) { | 106 | if (!local->use_chanctx) { |
99 | local->_oper_chandef = *chandef; | 107 | local->_oper_chandef = *chandef; |
100 | ieee80211_hw_config(local, 0); | 108 | ieee80211_hw_config(local, 0); |
@@ -102,14 +110,17 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
102 | err = drv_add_chanctx(local, ctx); | 110 | err = drv_add_chanctx(local, ctx); |
103 | if (err) { | 111 | if (err) { |
104 | kfree(ctx); | 112 | kfree(ctx); |
105 | return ERR_PTR(err); | 113 | ctx = ERR_PTR(err); |
114 | |||
115 | ieee80211_recalc_idle(local); | ||
116 | goto out; | ||
106 | } | 117 | } |
107 | } | 118 | } |
108 | 119 | ||
120 | /* and keep the mutex held until the new chanctx is on the list */ | ||
109 | list_add_rcu(&ctx->list, &local->chanctx_list); | 121 | list_add_rcu(&ctx->list, &local->chanctx_list); |
110 | 122 | ||
111 | mutex_lock(&local->mtx); | 123 | out: |
112 | ieee80211_recalc_idle(local); | ||
113 | mutex_unlock(&local->mtx); | 124 | mutex_unlock(&local->mtx); |
114 | 125 | ||
115 | return ctx; | 126 | return ctx; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 21c1720eee00..af8410e1291e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -309,6 +309,7 @@ struct ieee80211_roc_work { | |||
309 | struct ieee80211_channel *chan; | 309 | struct ieee80211_channel *chan; |
310 | 310 | ||
311 | bool started, abort, hw_begun, notified; | 311 | bool started, abort, hw_begun, notified; |
312 | bool to_be_freed; | ||
312 | 313 | ||
313 | unsigned long hw_start_time; | 314 | unsigned long hw_start_time; |
314 | 315 | ||
@@ -1318,7 +1319,7 @@ void ieee80211_roc_setup(struct ieee80211_local *local); | |||
1318 | void ieee80211_start_next_roc(struct ieee80211_local *local); | 1319 | void ieee80211_start_next_roc(struct ieee80211_local *local); |
1319 | void ieee80211_roc_purge(struct ieee80211_local *local, | 1320 | void ieee80211_roc_purge(struct ieee80211_local *local, |
1320 | struct ieee80211_sub_if_data *sdata); | 1321 | struct ieee80211_sub_if_data *sdata); |
1321 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc); | 1322 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free); |
1322 | void ieee80211_sw_roc_work(struct work_struct *work); | 1323 | void ieee80211_sw_roc_work(struct work_struct *work); |
1323 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); | 1324 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); |
1324 | 1325 | ||
@@ -1332,6 +1333,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1332 | enum nl80211_iftype type); | 1333 | enum nl80211_iftype type); |
1333 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); | 1334 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); |
1334 | void ieee80211_remove_interfaces(struct ieee80211_local *local); | 1335 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
1336 | u32 ieee80211_idle_off(struct ieee80211_local *local); | ||
1335 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 1337 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
1336 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | 1338 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, |
1337 | const int offset); | 1339 | const int offset); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b6abaaa3676f..146b1320af4e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | |||
78 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); | 78 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); |
79 | } | 79 | } |
80 | 80 | ||
81 | static u32 ieee80211_idle_off(struct ieee80211_local *local) | 81 | u32 ieee80211_idle_off(struct ieee80211_local *local) |
82 | { | 82 | { |
83 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) | 83 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) |
84 | return 0; | 84 | return 0; |
@@ -349,21 +349,19 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | |||
349 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | 349 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) |
350 | { | 350 | { |
351 | struct ieee80211_sub_if_data *sdata; | 351 | struct ieee80211_sub_if_data *sdata; |
352 | int ret = 0; | 352 | int ret; |
353 | 353 | ||
354 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | 354 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) |
355 | return 0; | 355 | return 0; |
356 | 356 | ||
357 | mutex_lock(&local->iflist_mtx); | 357 | ASSERT_RTNL(); |
358 | 358 | ||
359 | if (local->monitor_sdata) | 359 | if (local->monitor_sdata) |
360 | goto out_unlock; | 360 | return 0; |
361 | 361 | ||
362 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); | 362 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); |
363 | if (!sdata) { | 363 | if (!sdata) |
364 | ret = -ENOMEM; | 364 | return -ENOMEM; |
365 | goto out_unlock; | ||
366 | } | ||
367 | 365 | ||
368 | /* set up data */ | 366 | /* set up data */ |
369 | sdata->local = local; | 367 | sdata->local = local; |
@@ -377,13 +375,13 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
377 | if (WARN_ON(ret)) { | 375 | if (WARN_ON(ret)) { |
378 | /* ok .. stupid driver, it asked for this! */ | 376 | /* ok .. stupid driver, it asked for this! */ |
379 | kfree(sdata); | 377 | kfree(sdata); |
380 | goto out_unlock; | 378 | return ret; |
381 | } | 379 | } |
382 | 380 | ||
383 | ret = ieee80211_check_queues(sdata); | 381 | ret = ieee80211_check_queues(sdata); |
384 | if (ret) { | 382 | if (ret) { |
385 | kfree(sdata); | 383 | kfree(sdata); |
386 | goto out_unlock; | 384 | return ret; |
387 | } | 385 | } |
388 | 386 | ||
389 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, | 387 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, |
@@ -391,13 +389,14 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
391 | if (ret) { | 389 | if (ret) { |
392 | drv_remove_interface(local, sdata); | 390 | drv_remove_interface(local, sdata); |
393 | kfree(sdata); | 391 | kfree(sdata); |
394 | goto out_unlock; | 392 | return ret; |
395 | } | 393 | } |
396 | 394 | ||
395 | mutex_lock(&local->iflist_mtx); | ||
397 | rcu_assign_pointer(local->monitor_sdata, sdata); | 396 | rcu_assign_pointer(local->monitor_sdata, sdata); |
398 | out_unlock: | ||
399 | mutex_unlock(&local->iflist_mtx); | 397 | mutex_unlock(&local->iflist_mtx); |
400 | return ret; | 398 | |
399 | return 0; | ||
401 | } | 400 | } |
402 | 401 | ||
403 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | 402 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local) |
@@ -407,14 +406,20 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
407 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | 406 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) |
408 | return; | 407 | return; |
409 | 408 | ||
409 | ASSERT_RTNL(); | ||
410 | |||
410 | mutex_lock(&local->iflist_mtx); | 411 | mutex_lock(&local->iflist_mtx); |
411 | 412 | ||
412 | sdata = rcu_dereference_protected(local->monitor_sdata, | 413 | sdata = rcu_dereference_protected(local->monitor_sdata, |
413 | lockdep_is_held(&local->iflist_mtx)); | 414 | lockdep_is_held(&local->iflist_mtx)); |
414 | if (!sdata) | 415 | if (!sdata) { |
415 | goto out_unlock; | 416 | mutex_unlock(&local->iflist_mtx); |
417 | return; | ||
418 | } | ||
416 | 419 | ||
417 | rcu_assign_pointer(local->monitor_sdata, NULL); | 420 | rcu_assign_pointer(local->monitor_sdata, NULL); |
421 | mutex_unlock(&local->iflist_mtx); | ||
422 | |||
418 | synchronize_net(); | 423 | synchronize_net(); |
419 | 424 | ||
420 | ieee80211_vif_release_channel(sdata); | 425 | ieee80211_vif_release_channel(sdata); |
@@ -422,8 +427,6 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
422 | drv_remove_interface(local, sdata); | 427 | drv_remove_interface(local, sdata); |
423 | 428 | ||
424 | kfree(sdata); | 429 | kfree(sdata); |
425 | out_unlock: | ||
426 | mutex_unlock(&local->iflist_mtx); | ||
427 | } | 430 | } |
428 | 431 | ||
429 | /* | 432 | /* |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 4b984765d62d..6952760881c8 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -1004,7 +1004,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | |||
1004 | 1004 | ||
1005 | rcu_read_lock(); | 1005 | rcu_read_lock(); |
1006 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 1006 | list_for_each_entry_rcu(sdata, &local->interfaces, list) |
1007 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1007 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
1008 | ieee80211_sdata_running(sdata)) | ||
1008 | ieee80211_queue_work(&local->hw, &sdata->work); | 1009 | ieee80211_queue_work(&local->hw, &sdata->work); |
1009 | rcu_read_unlock(); | 1010 | rcu_read_unlock(); |
1010 | } | 1011 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c7860d0450dd..f7beb12abde2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -3665,8 +3665,10 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | |||
3665 | 3665 | ||
3666 | /* Restart STA timers */ | 3666 | /* Restart STA timers */ |
3667 | rcu_read_lock(); | 3667 | rcu_read_lock(); |
3668 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 3668 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
3669 | ieee80211_restart_sta_timer(sdata); | 3669 | if (ieee80211_sdata_running(sdata)) |
3670 | ieee80211_restart_sta_timer(sdata); | ||
3671 | } | ||
3670 | rcu_read_unlock(); | 3672 | rcu_read_unlock(); |
3671 | } | 3673 | } |
3672 | 3674 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index e19d6cf26dde..acd1f71adc03 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -297,10 +297,13 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) | |||
297 | } | 297 | } |
298 | } | 298 | } |
299 | 299 | ||
300 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | 300 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free) |
301 | { | 301 | { |
302 | struct ieee80211_roc_work *dep, *tmp; | 302 | struct ieee80211_roc_work *dep, *tmp; |
303 | 303 | ||
304 | if (WARN_ON(roc->to_be_freed)) | ||
305 | return; | ||
306 | |||
304 | /* was never transmitted */ | 307 | /* was never transmitted */ |
305 | if (roc->frame) { | 308 | if (roc->frame) { |
306 | cfg80211_mgmt_tx_status(&roc->sdata->wdev, | 309 | cfg80211_mgmt_tx_status(&roc->sdata->wdev, |
@@ -316,9 +319,12 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | |||
316 | GFP_KERNEL); | 319 | GFP_KERNEL); |
317 | 320 | ||
318 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) | 321 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) |
319 | ieee80211_roc_notify_destroy(dep); | 322 | ieee80211_roc_notify_destroy(dep, true); |
320 | 323 | ||
321 | kfree(roc); | 324 | if (free) |
325 | kfree(roc); | ||
326 | else | ||
327 | roc->to_be_freed = true; | ||
322 | } | 328 | } |
323 | 329 | ||
324 | void ieee80211_sw_roc_work(struct work_struct *work) | 330 | void ieee80211_sw_roc_work(struct work_struct *work) |
@@ -331,6 +337,9 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
331 | 337 | ||
332 | mutex_lock(&local->mtx); | 338 | mutex_lock(&local->mtx); |
333 | 339 | ||
340 | if (roc->to_be_freed) | ||
341 | goto out_unlock; | ||
342 | |||
334 | if (roc->abort) | 343 | if (roc->abort) |
335 | goto finish; | 344 | goto finish; |
336 | 345 | ||
@@ -370,7 +379,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
370 | finish: | 379 | finish: |
371 | list_del(&roc->list); | 380 | list_del(&roc->list); |
372 | started = roc->started; | 381 | started = roc->started; |
373 | ieee80211_roc_notify_destroy(roc); | 382 | ieee80211_roc_notify_destroy(roc, !roc->abort); |
374 | 383 | ||
375 | if (started) { | 384 | if (started) { |
376 | ieee80211_flush_queues(local, NULL); | 385 | ieee80211_flush_queues(local, NULL); |
@@ -410,7 +419,7 @@ static void ieee80211_hw_roc_done(struct work_struct *work) | |||
410 | 419 | ||
411 | list_del(&roc->list); | 420 | list_del(&roc->list); |
412 | 421 | ||
413 | ieee80211_roc_notify_destroy(roc); | 422 | ieee80211_roc_notify_destroy(roc, true); |
414 | 423 | ||
415 | /* if there's another roc, start it now */ | 424 | /* if there's another roc, start it now */ |
416 | ieee80211_start_next_roc(local); | 425 | ieee80211_start_next_roc(local); |
@@ -460,12 +469,14 @@ void ieee80211_roc_purge(struct ieee80211_local *local, | |||
460 | list_for_each_entry_safe(roc, tmp, &tmp_list, list) { | 469 | list_for_each_entry_safe(roc, tmp, &tmp_list, list) { |
461 | if (local->ops->remain_on_channel) { | 470 | if (local->ops->remain_on_channel) { |
462 | list_del(&roc->list); | 471 | list_del(&roc->list); |
463 | ieee80211_roc_notify_destroy(roc); | 472 | ieee80211_roc_notify_destroy(roc, true); |
464 | } else { | 473 | } else { |
465 | ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); | 474 | ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); |
466 | 475 | ||
467 | /* work will clean up etc */ | 476 | /* work will clean up etc */ |
468 | flush_delayed_work(&roc->work); | 477 | flush_delayed_work(&roc->work); |
478 | WARN_ON(!roc->to_be_freed); | ||
479 | kfree(roc); | ||
469 | } | 480 | } |
470 | } | 481 | } |
471 | 482 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 14b32a4cd7bb..c8447af76ead 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2679,7 +2679,19 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) | |||
2679 | 2679 | ||
2680 | memset(nskb->cb, 0, sizeof(nskb->cb)); | 2680 | memset(nskb->cb, 0, sizeof(nskb->cb)); |
2681 | 2681 | ||
2682 | ieee80211_tx_skb(rx->sdata, nskb); | 2682 | if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { |
2683 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb); | ||
2684 | |||
2685 | info->flags = IEEE80211_TX_CTL_TX_OFFCHAN | | ||
2686 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK | | ||
2687 | IEEE80211_TX_CTL_NO_CCK_RATE; | ||
2688 | if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) | ||
2689 | info->hw_queue = | ||
2690 | local->hw.offchannel_tx_hw_queue; | ||
2691 | } | ||
2692 | |||
2693 | __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7, | ||
2694 | status->band); | ||
2683 | } | 2695 | } |
2684 | dev_kfree_skb(rx->skb); | 2696 | dev_kfree_skb(rx->skb); |
2685 | return RX_QUEUED; | 2697 | return RX_QUEUED; |
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..7de0368aff0c 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,11 +101,12 @@ 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 | |||
107 | sock_orphan(accept_sk); | ||
108 | } | 110 | } |
109 | 111 | ||
110 | if (listen == true) { | 112 | if (listen == true) { |
@@ -123,16 +125,45 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
123 | continue; | 125 | continue; |
124 | } | 126 | } |
125 | 127 | ||
128 | if (err) | ||
129 | sk->sk_err = err; | ||
126 | sk->sk_state = LLCP_CLOSED; | 130 | sk->sk_state = LLCP_CLOSED; |
131 | sk->sk_state_change(sk); | ||
127 | 132 | ||
128 | bh_unlock_sock(sk); | 133 | bh_unlock_sock(sk); |
129 | 134 | ||
130 | sock_orphan(sk); | ||
131 | |||
132 | sk_del_node_init(sk); | 135 | sk_del_node_init(sk); |
133 | } | 136 | } |
134 | 137 | ||
135 | write_unlock(&local->sockets.lock); | 138 | write_unlock(&local->sockets.lock); |
139 | |||
140 | /* | ||
141 | * If we want to keep the listening sockets alive, | ||
142 | * we don't touch the RAW ones. | ||
143 | */ | ||
144 | if (listen == true) | ||
145 | return; | ||
146 | |||
147 | write_lock(&local->raw_sockets.lock); | ||
148 | |||
149 | sk_for_each_safe(sk, tmp, &local->raw_sockets.head) { | ||
150 | llcp_sock = nfc_llcp_sock(sk); | ||
151 | |||
152 | bh_lock_sock(sk); | ||
153 | |||
154 | nfc_llcp_socket_purge(llcp_sock); | ||
155 | |||
156 | if (err) | ||
157 | sk->sk_err = err; | ||
158 | sk->sk_state = LLCP_CLOSED; | ||
159 | sk->sk_state_change(sk); | ||
160 | |||
161 | bh_unlock_sock(sk); | ||
162 | |||
163 | sk_del_node_init(sk); | ||
164 | } | ||
165 | |||
166 | write_unlock(&local->raw_sockets.lock); | ||
136 | } | 167 | } |
137 | 168 | ||
138 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | 169 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) |
@@ -142,20 +173,28 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | |||
142 | return local; | 173 | return local; |
143 | } | 174 | } |
144 | 175 | ||
145 | static void local_release(struct kref *ref) | 176 | static void local_cleanup(struct nfc_llcp_local *local, bool listen) |
146 | { | 177 | { |
147 | struct nfc_llcp_local *local; | 178 | 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); | 179 | del_timer_sync(&local->link_timer); |
154 | skb_queue_purge(&local->tx_queue); | 180 | skb_queue_purge(&local->tx_queue); |
155 | cancel_work_sync(&local->tx_work); | 181 | cancel_work_sync(&local->tx_work); |
156 | cancel_work_sync(&local->rx_work); | 182 | cancel_work_sync(&local->rx_work); |
157 | cancel_work_sync(&local->timeout_work); | 183 | cancel_work_sync(&local->timeout_work); |
158 | kfree_skb(local->rx_pending); | 184 | kfree_skb(local->rx_pending); |
185 | del_timer_sync(&local->sdreq_timer); | ||
186 | cancel_work_sync(&local->sdreq_timeout_work); | ||
187 | nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs); | ||
188 | } | ||
189 | |||
190 | static void local_release(struct kref *ref) | ||
191 | { | ||
192 | struct nfc_llcp_local *local; | ||
193 | |||
194 | local = container_of(ref, struct nfc_llcp_local, ref); | ||
195 | |||
196 | list_del(&local->list); | ||
197 | local_cleanup(local, false); | ||
159 | kfree(local); | 198 | kfree(local); |
160 | } | 199 | } |
161 | 200 | ||
@@ -223,6 +262,47 @@ static void nfc_llcp_symm_timer(unsigned long data) | |||
223 | schedule_work(&local->timeout_work); | 262 | schedule_work(&local->timeout_work); |
224 | } | 263 | } |
225 | 264 | ||
265 | static void nfc_llcp_sdreq_timeout_work(struct work_struct *work) | ||
266 | { | ||
267 | unsigned long time; | ||
268 | HLIST_HEAD(nl_sdres_list); | ||
269 | struct hlist_node *n; | ||
270 | struct nfc_llcp_sdp_tlv *sdp; | ||
271 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
272 | sdreq_timeout_work); | ||
273 | |||
274 | mutex_lock(&local->sdreq_lock); | ||
275 | |||
276 | time = jiffies - msecs_to_jiffies(3 * local->remote_lto); | ||
277 | |||
278 | hlist_for_each_entry_safe(sdp, n, &local->pending_sdreqs, node) { | ||
279 | if (time_after(sdp->time, time)) | ||
280 | continue; | ||
281 | |||
282 | sdp->sap = LLCP_SDP_UNBOUND; | ||
283 | |||
284 | hlist_del(&sdp->node); | ||
285 | |||
286 | hlist_add_head(&sdp->node, &nl_sdres_list); | ||
287 | } | ||
288 | |||
289 | if (!hlist_empty(&local->pending_sdreqs)) | ||
290 | mod_timer(&local->sdreq_timer, | ||
291 | jiffies + msecs_to_jiffies(3 * local->remote_lto)); | ||
292 | |||
293 | mutex_unlock(&local->sdreq_lock); | ||
294 | |||
295 | if (!hlist_empty(&nl_sdres_list)) | ||
296 | nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list); | ||
297 | } | ||
298 | |||
299 | static void nfc_llcp_sdreq_timer(unsigned long data) | ||
300 | { | ||
301 | struct nfc_llcp_local *local = (struct nfc_llcp_local *) data; | ||
302 | |||
303 | schedule_work(&local->sdreq_timeout_work); | ||
304 | } | ||
305 | |||
226 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) | 306 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) |
227 | { | 307 | { |
228 | struct nfc_llcp_local *local, *n; | 308 | struct nfc_llcp_local *local, *n; |
@@ -766,8 +846,6 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, | |||
766 | ui_cb->dsap = dsap; | 846 | ui_cb->dsap = dsap; |
767 | ui_cb->ssap = ssap; | 847 | ui_cb->ssap = ssap; |
768 | 848 | ||
769 | printk("%s %d %d\n", __func__, dsap, ssap); | ||
770 | |||
771 | pr_debug("%d %d\n", dsap, ssap); | 849 | pr_debug("%d %d\n", dsap, ssap); |
772 | 850 | ||
773 | /* We're looking for a bound socket, not a client one */ | 851 | /* We're looking for a bound socket, not a client one */ |
@@ -785,7 +863,6 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, | |||
785 | skb_get(skb); | 863 | skb_get(skb); |
786 | } else { | 864 | } else { |
787 | pr_err("Receive queue is full\n"); | 865 | pr_err("Receive queue is full\n"); |
788 | kfree_skb(skb); | ||
789 | } | 866 | } |
790 | 867 | ||
791 | nfc_llcp_sock_put(llcp_sock); | 868 | nfc_llcp_sock_put(llcp_sock); |
@@ -865,7 +942,9 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
865 | new_sock = nfc_llcp_sock(new_sk); | 942 | new_sock = nfc_llcp_sock(new_sk); |
866 | new_sock->dev = local->dev; | 943 | new_sock->dev = local->dev; |
867 | new_sock->local = nfc_llcp_local_get(local); | 944 | new_sock->local = nfc_llcp_local_get(local); |
868 | new_sock->miu = local->remote_miu; | 945 | new_sock->rw = sock->rw; |
946 | new_sock->miux = sock->miux; | ||
947 | new_sock->remote_miu = local->remote_miu; | ||
869 | new_sock->nfc_protocol = sock->nfc_protocol; | 948 | new_sock->nfc_protocol = sock->nfc_protocol; |
870 | new_sock->dsap = ssap; | 949 | new_sock->dsap = ssap; |
871 | new_sock->target_idx = local->target_idx; | 950 | new_sock->target_idx = local->target_idx; |
@@ -919,11 +998,11 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
919 | 998 | ||
920 | pr_debug("Remote ready %d tx queue len %d remote rw %d", | 999 | pr_debug("Remote ready %d tx queue len %d remote rw %d", |
921 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), | 1000 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), |
922 | sock->rw); | 1001 | sock->remote_rw); |
923 | 1002 | ||
924 | /* Try to queue some I frames for transmission */ | 1003 | /* Try to queue some I frames for transmission */ |
925 | while (sock->remote_ready && | 1004 | while (sock->remote_ready && |
926 | skb_queue_len(&sock->tx_pending_queue) < sock->rw) { | 1005 | skb_queue_len(&sock->tx_pending_queue) < sock->remote_rw) { |
927 | struct sk_buff *pdu; | 1006 | struct sk_buff *pdu; |
928 | 1007 | ||
929 | pdu = skb_dequeue(&sock->tx_queue); | 1008 | pdu = skb_dequeue(&sock->tx_queue); |
@@ -986,7 +1065,6 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
986 | skb_get(skb); | 1065 | skb_get(skb); |
987 | } else { | 1066 | } else { |
988 | pr_err("Receive queue is full\n"); | 1067 | pr_err("Receive queue is full\n"); |
989 | kfree_skb(skb); | ||
990 | } | 1068 | } |
991 | } | 1069 | } |
992 | 1070 | ||
@@ -1144,6 +1222,10 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1144 | u16 tlv_len, offset; | 1222 | u16 tlv_len, offset; |
1145 | char *service_name; | 1223 | char *service_name; |
1146 | size_t service_name_len; | 1224 | size_t service_name_len; |
1225 | struct nfc_llcp_sdp_tlv *sdp; | ||
1226 | HLIST_HEAD(llc_sdres_list); | ||
1227 | size_t sdres_tlvs_len; | ||
1228 | HLIST_HEAD(nl_sdres_list); | ||
1147 | 1229 | ||
1148 | dsap = nfc_llcp_dsap(skb); | 1230 | dsap = nfc_llcp_dsap(skb); |
1149 | ssap = nfc_llcp_ssap(skb); | 1231 | ssap = nfc_llcp_ssap(skb); |
@@ -1158,6 +1240,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1158 | tlv = &skb->data[LLCP_HEADER_SIZE]; | 1240 | tlv = &skb->data[LLCP_HEADER_SIZE]; |
1159 | tlv_len = skb->len - LLCP_HEADER_SIZE; | 1241 | tlv_len = skb->len - LLCP_HEADER_SIZE; |
1160 | offset = 0; | 1242 | offset = 0; |
1243 | sdres_tlvs_len = 0; | ||
1161 | 1244 | ||
1162 | while (offset < tlv_len) { | 1245 | while (offset < tlv_len) { |
1163 | type = tlv[0]; | 1246 | type = tlv[0]; |
@@ -1175,14 +1258,14 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1175 | !strncmp(service_name, "urn:nfc:sn:sdp", | 1258 | !strncmp(service_name, "urn:nfc:sn:sdp", |
1176 | service_name_len)) { | 1259 | service_name_len)) { |
1177 | sap = 1; | 1260 | sap = 1; |
1178 | goto send_snl; | 1261 | goto add_snl; |
1179 | } | 1262 | } |
1180 | 1263 | ||
1181 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, | 1264 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, |
1182 | service_name_len); | 1265 | service_name_len); |
1183 | if (!llcp_sock) { | 1266 | if (!llcp_sock) { |
1184 | sap = 0; | 1267 | sap = 0; |
1185 | goto send_snl; | 1268 | goto add_snl; |
1186 | } | 1269 | } |
1187 | 1270 | ||
1188 | /* | 1271 | /* |
@@ -1199,7 +1282,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1199 | 1282 | ||
1200 | if (sap == LLCP_SAP_MAX) { | 1283 | if (sap == LLCP_SAP_MAX) { |
1201 | sap = 0; | 1284 | sap = 0; |
1202 | goto send_snl; | 1285 | goto add_snl; |
1203 | } | 1286 | } |
1204 | 1287 | ||
1205 | client_count = | 1288 | client_count = |
@@ -1216,8 +1299,37 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1216 | 1299 | ||
1217 | pr_debug("%p %d\n", llcp_sock, sap); | 1300 | pr_debug("%p %d\n", llcp_sock, sap); |
1218 | 1301 | ||
1219 | send_snl: | 1302 | add_snl: |
1220 | nfc_llcp_send_snl(local, tid, sap); | 1303 | sdp = nfc_llcp_build_sdres_tlv(tid, sap); |
1304 | if (sdp == NULL) | ||
1305 | goto exit; | ||
1306 | |||
1307 | sdres_tlvs_len += sdp->tlv_len; | ||
1308 | hlist_add_head(&sdp->node, &llc_sdres_list); | ||
1309 | break; | ||
1310 | |||
1311 | case LLCP_TLV_SDRES: | ||
1312 | mutex_lock(&local->sdreq_lock); | ||
1313 | |||
1314 | pr_debug("LLCP_TLV_SDRES: searching tid %d\n", tlv[2]); | ||
1315 | |||
1316 | hlist_for_each_entry(sdp, &local->pending_sdreqs, node) { | ||
1317 | if (sdp->tid != tlv[2]) | ||
1318 | continue; | ||
1319 | |||
1320 | sdp->sap = tlv[3]; | ||
1321 | |||
1322 | pr_debug("Found: uri=%s, sap=%d\n", | ||
1323 | sdp->uri, sdp->sap); | ||
1324 | |||
1325 | hlist_del(&sdp->node); | ||
1326 | |||
1327 | hlist_add_head(&sdp->node, &nl_sdres_list); | ||
1328 | |||
1329 | break; | ||
1330 | } | ||
1331 | |||
1332 | mutex_unlock(&local->sdreq_lock); | ||
1221 | break; | 1333 | break; |
1222 | 1334 | ||
1223 | default: | 1335 | default: |
@@ -1228,6 +1340,13 @@ send_snl: | |||
1228 | offset += length + 2; | 1340 | offset += length + 2; |
1229 | tlv += length + 2; | 1341 | tlv += length + 2; |
1230 | } | 1342 | } |
1343 | |||
1344 | exit: | ||
1345 | if (!hlist_empty(&nl_sdres_list)) | ||
1346 | nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list); | ||
1347 | |||
1348 | if (!hlist_empty(&llc_sdres_list)) | ||
1349 | nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len); | ||
1231 | } | 1350 | } |
1232 | 1351 | ||
1233 | static void nfc_llcp_rx_work(struct work_struct *work) | 1352 | static void nfc_llcp_rx_work(struct work_struct *work) |
@@ -1348,7 +1467,7 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev) | |||
1348 | return; | 1467 | return; |
1349 | 1468 | ||
1350 | /* Close and purge all existing sockets */ | 1469 | /* Close and purge all existing sockets */ |
1351 | nfc_llcp_socket_release(local, true); | 1470 | nfc_llcp_socket_release(local, true, 0); |
1352 | } | 1471 | } |
1353 | 1472 | ||
1354 | void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | 1473 | void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, |
@@ -1413,6 +1532,13 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
1413 | local->remote_miu = LLCP_DEFAULT_MIU; | 1532 | local->remote_miu = LLCP_DEFAULT_MIU; |
1414 | local->remote_lto = LLCP_DEFAULT_LTO; | 1533 | local->remote_lto = LLCP_DEFAULT_LTO; |
1415 | 1534 | ||
1535 | mutex_init(&local->sdreq_lock); | ||
1536 | INIT_HLIST_HEAD(&local->pending_sdreqs); | ||
1537 | init_timer(&local->sdreq_timer); | ||
1538 | local->sdreq_timer.data = (unsigned long) local; | ||
1539 | local->sdreq_timer.function = nfc_llcp_sdreq_timer; | ||
1540 | INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); | ||
1541 | |||
1416 | list_add(&local->list, &llcp_devices); | 1542 | list_add(&local->list, &llcp_devices); |
1417 | 1543 | ||
1418 | return 0; | 1544 | return 0; |
@@ -1427,6 +1553,8 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) | |||
1427 | return; | 1553 | return; |
1428 | } | 1554 | } |
1429 | 1555 | ||
1556 | local_cleanup(local, false); | ||
1557 | |||
1430 | nfc_llcp_local_put(local); | 1558 | nfc_llcp_local_put(local); |
1431 | } | 1559 | } |
1432 | 1560 | ||
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..6fa76704cb13 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); |
@@ -270,7 +388,9 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent, | |||
270 | } | 388 | } |
271 | 389 | ||
272 | if (sk->sk_state == LLCP_CONNECTED || !newsock) { | 390 | if (sk->sk_state == LLCP_CONNECTED || !newsock) { |
273 | nfc_llcp_accept_unlink(sk); | 391 | list_del_init(&lsk->accept_queue); |
392 | sock_put(sk); | ||
393 | |||
274 | if (newsock) | 394 | if (newsock) |
275 | sock_graft(sk, newsock); | 395 | sock_graft(sk, newsock); |
276 | 396 | ||
@@ -278,6 +398,8 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent, | |||
278 | 398 | ||
279 | pr_debug("Returning sk state %d\n", sk->sk_state); | 399 | pr_debug("Returning sk state %d\n", sk->sk_state); |
280 | 400 | ||
401 | sk_acceptq_removed(parent); | ||
402 | |||
281 | return sk; | 403 | return sk; |
282 | } | 404 | } |
283 | 405 | ||
@@ -462,8 +584,6 @@ static int llcp_sock_release(struct socket *sock) | |||
462 | nfc_llcp_accept_unlink(accept_sk); | 584 | nfc_llcp_accept_unlink(accept_sk); |
463 | 585 | ||
464 | release_sock(accept_sk); | 586 | release_sock(accept_sk); |
465 | |||
466 | sock_orphan(accept_sk); | ||
467 | } | 587 | } |
468 | } | 588 | } |
469 | 589 | ||
@@ -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/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/core.c b/net/wireless/core.c index 92e3fd44e3b0..84c9ad7e1dca 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -212,6 +212,39 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) | |||
212 | rdev_rfkill_poll(rdev); | 212 | rdev_rfkill_poll(rdev); |
213 | } | 213 | } |
214 | 214 | ||
215 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | ||
216 | struct wireless_dev *wdev) | ||
217 | { | ||
218 | lockdep_assert_held(&rdev->devlist_mtx); | ||
219 | lockdep_assert_held(&rdev->sched_scan_mtx); | ||
220 | |||
221 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) | ||
222 | return; | ||
223 | |||
224 | if (!wdev->p2p_started) | ||
225 | return; | ||
226 | |||
227 | rdev_stop_p2p_device(rdev, wdev); | ||
228 | wdev->p2p_started = false; | ||
229 | |||
230 | rdev->opencount--; | ||
231 | |||
232 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { | ||
233 | bool busy = work_busy(&rdev->scan_done_wk); | ||
234 | |||
235 | /* | ||
236 | * If the work isn't pending or running (in which case it would | ||
237 | * be waiting for the lock we hold) the driver didn't properly | ||
238 | * cancel the scan when the interface was removed. In this case | ||
239 | * warn and leak the scan request object to not crash later. | ||
240 | */ | ||
241 | WARN_ON(!busy); | ||
242 | |||
243 | rdev->scan_req->aborted = true; | ||
244 | ___cfg80211_scan_done(rdev, !busy); | ||
245 | } | ||
246 | } | ||
247 | |||
215 | static int cfg80211_rfkill_set_block(void *data, bool blocked) | 248 | static int cfg80211_rfkill_set_block(void *data, bool blocked) |
216 | { | 249 | { |
217 | struct cfg80211_registered_device *rdev = data; | 250 | struct cfg80211_registered_device *rdev = data; |
@@ -221,7 +254,8 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | |||
221 | return 0; | 254 | return 0; |
222 | 255 | ||
223 | rtnl_lock(); | 256 | rtnl_lock(); |
224 | mutex_lock(&rdev->devlist_mtx); | 257 | |
258 | /* read-only iteration need not hold the devlist_mtx */ | ||
225 | 259 | ||
226 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 260 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
227 | if (wdev->netdev) { | 261 | if (wdev->netdev) { |
@@ -231,18 +265,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | |||
231 | /* otherwise, check iftype */ | 265 | /* otherwise, check iftype */ |
232 | switch (wdev->iftype) { | 266 | switch (wdev->iftype) { |
233 | case NL80211_IFTYPE_P2P_DEVICE: | 267 | case NL80211_IFTYPE_P2P_DEVICE: |
234 | if (!wdev->p2p_started) | 268 | /* but this requires it */ |
235 | break; | 269 | mutex_lock(&rdev->devlist_mtx); |
236 | rdev_stop_p2p_device(rdev, wdev); | 270 | mutex_lock(&rdev->sched_scan_mtx); |
237 | wdev->p2p_started = false; | 271 | cfg80211_stop_p2p_device(rdev, wdev); |
238 | rdev->opencount--; | 272 | mutex_unlock(&rdev->sched_scan_mtx); |
273 | mutex_unlock(&rdev->devlist_mtx); | ||
239 | break; | 274 | break; |
240 | default: | 275 | default: |
241 | break; | 276 | break; |
242 | } | 277 | } |
243 | } | 278 | } |
244 | 279 | ||
245 | mutex_unlock(&rdev->devlist_mtx); | ||
246 | rtnl_unlock(); | 280 | rtnl_unlock(); |
247 | 281 | ||
248 | return 0; | 282 | return 0; |
@@ -745,17 +779,13 @@ static void wdev_cleanup_work(struct work_struct *work) | |||
745 | wdev = container_of(work, struct wireless_dev, cleanup_work); | 779 | wdev = container_of(work, struct wireless_dev, cleanup_work); |
746 | rdev = wiphy_to_dev(wdev->wiphy); | 780 | rdev = wiphy_to_dev(wdev->wiphy); |
747 | 781 | ||
748 | cfg80211_lock_rdev(rdev); | 782 | mutex_lock(&rdev->sched_scan_mtx); |
749 | 783 | ||
750 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | 784 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { |
751 | rdev->scan_req->aborted = true; | 785 | rdev->scan_req->aborted = true; |
752 | ___cfg80211_scan_done(rdev, true); | 786 | ___cfg80211_scan_done(rdev, true); |
753 | } | 787 | } |
754 | 788 | ||
755 | cfg80211_unlock_rdev(rdev); | ||
756 | |||
757 | mutex_lock(&rdev->sched_scan_mtx); | ||
758 | |||
759 | if (WARN_ON(rdev->sched_scan_req && | 789 | if (WARN_ON(rdev->sched_scan_req && |
760 | rdev->sched_scan_req->dev == wdev->netdev)) { | 790 | rdev->sched_scan_req->dev == wdev->netdev)) { |
761 | __cfg80211_stop_sched_scan(rdev, false); | 791 | __cfg80211_stop_sched_scan(rdev, false); |
@@ -781,21 +811,19 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) | |||
781 | return; | 811 | return; |
782 | 812 | ||
783 | mutex_lock(&rdev->devlist_mtx); | 813 | mutex_lock(&rdev->devlist_mtx); |
814 | mutex_lock(&rdev->sched_scan_mtx); | ||
784 | list_del_rcu(&wdev->list); | 815 | list_del_rcu(&wdev->list); |
785 | rdev->devlist_generation++; | 816 | rdev->devlist_generation++; |
786 | 817 | ||
787 | switch (wdev->iftype) { | 818 | switch (wdev->iftype) { |
788 | case NL80211_IFTYPE_P2P_DEVICE: | 819 | case NL80211_IFTYPE_P2P_DEVICE: |
789 | if (!wdev->p2p_started) | 820 | cfg80211_stop_p2p_device(rdev, wdev); |
790 | break; | ||
791 | rdev_stop_p2p_device(rdev, wdev); | ||
792 | wdev->p2p_started = false; | ||
793 | rdev->opencount--; | ||
794 | break; | 821 | break; |
795 | default: | 822 | default: |
796 | WARN_ON_ONCE(1); | 823 | WARN_ON_ONCE(1); |
797 | break; | 824 | break; |
798 | } | 825 | } |
826 | mutex_unlock(&rdev->sched_scan_mtx); | ||
799 | mutex_unlock(&rdev->devlist_mtx); | 827 | mutex_unlock(&rdev->devlist_mtx); |
800 | } | 828 | } |
801 | EXPORT_SYMBOL(cfg80211_unregister_wdev); | 829 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
@@ -945,6 +973,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
945 | cfg80211_update_iface_num(rdev, wdev->iftype, 1); | 973 | cfg80211_update_iface_num(rdev, wdev->iftype, 1); |
946 | cfg80211_lock_rdev(rdev); | 974 | cfg80211_lock_rdev(rdev); |
947 | mutex_lock(&rdev->devlist_mtx); | 975 | mutex_lock(&rdev->devlist_mtx); |
976 | mutex_lock(&rdev->sched_scan_mtx); | ||
948 | wdev_lock(wdev); | 977 | wdev_lock(wdev); |
949 | switch (wdev->iftype) { | 978 | switch (wdev->iftype) { |
950 | #ifdef CONFIG_CFG80211_WEXT | 979 | #ifdef CONFIG_CFG80211_WEXT |
@@ -976,6 +1005,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
976 | break; | 1005 | break; |
977 | } | 1006 | } |
978 | wdev_unlock(wdev); | 1007 | wdev_unlock(wdev); |
1008 | mutex_unlock(&rdev->sched_scan_mtx); | ||
979 | rdev->opencount++; | 1009 | rdev->opencount++; |
980 | mutex_unlock(&rdev->devlist_mtx); | 1010 | mutex_unlock(&rdev->devlist_mtx); |
981 | cfg80211_unlock_rdev(rdev); | 1011 | cfg80211_unlock_rdev(rdev); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index d5d06fdea961..124e5e773fbc 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -503,6 +503,9 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | |||
503 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | 503 | void cfg80211_leave(struct cfg80211_registered_device *rdev, |
504 | struct wireless_dev *wdev); | 504 | struct wireless_dev *wdev); |
505 | 505 | ||
506 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | ||
507 | struct wireless_dev *wdev); | ||
508 | |||
506 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 | 509 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 |
507 | 510 | ||
508 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | 511 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8c8a57937b22..212d2aa7a1c5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -5060,14 +5060,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5060 | if (!rdev->ops->scan) | 5060 | if (!rdev->ops->scan) |
5061 | return -EOPNOTSUPP; | 5061 | return -EOPNOTSUPP; |
5062 | 5062 | ||
5063 | if (rdev->scan_req) | 5063 | mutex_lock(&rdev->sched_scan_mtx); |
5064 | return -EBUSY; | 5064 | if (rdev->scan_req) { |
5065 | err = -EBUSY; | ||
5066 | goto unlock; | ||
5067 | } | ||
5065 | 5068 | ||
5066 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | 5069 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { |
5067 | n_channels = validate_scan_freqs( | 5070 | n_channels = validate_scan_freqs( |
5068 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); | 5071 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); |
5069 | if (!n_channels) | 5072 | if (!n_channels) { |
5070 | return -EINVAL; | 5073 | err = -EINVAL; |
5074 | goto unlock; | ||
5075 | } | ||
5071 | } else { | 5076 | } else { |
5072 | enum ieee80211_band band; | 5077 | enum ieee80211_band band; |
5073 | n_channels = 0; | 5078 | n_channels = 0; |
@@ -5081,23 +5086,29 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5081 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) | 5086 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) |
5082 | n_ssids++; | 5087 | n_ssids++; |
5083 | 5088 | ||
5084 | if (n_ssids > wiphy->max_scan_ssids) | 5089 | if (n_ssids > wiphy->max_scan_ssids) { |
5085 | return -EINVAL; | 5090 | err = -EINVAL; |
5091 | goto unlock; | ||
5092 | } | ||
5086 | 5093 | ||
5087 | if (info->attrs[NL80211_ATTR_IE]) | 5094 | if (info->attrs[NL80211_ATTR_IE]) |
5088 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 5095 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
5089 | else | 5096 | else |
5090 | ie_len = 0; | 5097 | ie_len = 0; |
5091 | 5098 | ||
5092 | if (ie_len > wiphy->max_scan_ie_len) | 5099 | if (ie_len > wiphy->max_scan_ie_len) { |
5093 | return -EINVAL; | 5100 | err = -EINVAL; |
5101 | goto unlock; | ||
5102 | } | ||
5094 | 5103 | ||
5095 | request = kzalloc(sizeof(*request) | 5104 | request = kzalloc(sizeof(*request) |
5096 | + sizeof(*request->ssids) * n_ssids | 5105 | + sizeof(*request->ssids) * n_ssids |
5097 | + sizeof(*request->channels) * n_channels | 5106 | + sizeof(*request->channels) * n_channels |
5098 | + ie_len, GFP_KERNEL); | 5107 | + ie_len, GFP_KERNEL); |
5099 | if (!request) | 5108 | if (!request) { |
5100 | return -ENOMEM; | 5109 | err = -ENOMEM; |
5110 | goto unlock; | ||
5111 | } | ||
5101 | 5112 | ||
5102 | if (n_ssids) | 5113 | if (n_ssids) |
5103 | request->ssids = (void *)&request->channels[n_channels]; | 5114 | request->ssids = (void *)&request->channels[n_channels]; |
@@ -5234,6 +5245,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5234 | kfree(request); | 5245 | kfree(request); |
5235 | } | 5246 | } |
5236 | 5247 | ||
5248 | unlock: | ||
5249 | mutex_unlock(&rdev->sched_scan_mtx); | ||
5237 | return err; | 5250 | return err; |
5238 | } | 5251 | } |
5239 | 5252 | ||
@@ -8146,20 +8159,9 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
8146 | if (!rdev->ops->stop_p2p_device) | 8159 | if (!rdev->ops->stop_p2p_device) |
8147 | return -EOPNOTSUPP; | 8160 | return -EOPNOTSUPP; |
8148 | 8161 | ||
8149 | if (!wdev->p2p_started) | 8162 | mutex_lock(&rdev->sched_scan_mtx); |
8150 | return 0; | 8163 | cfg80211_stop_p2p_device(rdev, wdev); |
8151 | 8164 | mutex_unlock(&rdev->sched_scan_mtx); | |
8152 | rdev_stop_p2p_device(rdev, wdev); | ||
8153 | wdev->p2p_started = false; | ||
8154 | |||
8155 | mutex_lock(&rdev->devlist_mtx); | ||
8156 | rdev->opencount--; | ||
8157 | mutex_unlock(&rdev->devlist_mtx); | ||
8158 | |||
8159 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | ||
8160 | rdev->scan_req->aborted = true; | ||
8161 | ___cfg80211_scan_done(rdev, true); | ||
8162 | } | ||
8163 | 8165 | ||
8164 | return 0; | 8166 | return 0; |
8165 | } | 8167 | } |
@@ -8945,7 +8947,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg, | |||
8945 | struct nlattr *nest; | 8947 | struct nlattr *nest; |
8946 | int i; | 8948 | int i; |
8947 | 8949 | ||
8948 | ASSERT_RDEV_LOCK(rdev); | 8950 | lockdep_assert_held(&rdev->sched_scan_mtx); |
8949 | 8951 | ||
8950 | if (WARN_ON(!req)) | 8952 | if (WARN_ON(!req)) |
8951 | return 0; | 8953 | return 0; |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 674aadca0079..fd99ea495b7e 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) | |||
169 | union iwreq_data wrqu; | 169 | union iwreq_data wrqu; |
170 | #endif | 170 | #endif |
171 | 171 | ||
172 | ASSERT_RDEV_LOCK(rdev); | 172 | lockdep_assert_held(&rdev->sched_scan_mtx); |
173 | 173 | ||
174 | request = rdev->scan_req; | 174 | request = rdev->scan_req; |
175 | 175 | ||
@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk) | |||
230 | rdev = container_of(wk, struct cfg80211_registered_device, | 230 | rdev = container_of(wk, struct cfg80211_registered_device, |
231 | scan_done_wk); | 231 | scan_done_wk); |
232 | 232 | ||
233 | cfg80211_lock_rdev(rdev); | 233 | mutex_lock(&rdev->sched_scan_mtx); |
234 | ___cfg80211_scan_done(rdev, false); | 234 | ___cfg80211_scan_done(rdev, false); |
235 | cfg80211_unlock_rdev(rdev); | 235 | mutex_unlock(&rdev->sched_scan_mtx); |
236 | } | 236 | } |
237 | 237 | ||
238 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | 238 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) |
@@ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
698 | found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR); | 698 | found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR); |
699 | 699 | ||
700 | if (found) { | 700 | if (found) { |
701 | found->pub.beacon_interval = tmp->pub.beacon_interval; | ||
702 | found->pub.signal = tmp->pub.signal; | ||
703 | found->pub.capability = tmp->pub.capability; | ||
704 | found->ts = tmp->ts; | ||
705 | |||
706 | /* Update IEs */ | 701 | /* Update IEs */ |
707 | if (rcu_access_pointer(tmp->pub.proberesp_ies)) { | 702 | if (rcu_access_pointer(tmp->pub.proberesp_ies)) { |
708 | const struct cfg80211_bss_ies *old; | 703 | const struct cfg80211_bss_ies *old; |
@@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
723 | 718 | ||
724 | if (found->pub.hidden_beacon_bss && | 719 | if (found->pub.hidden_beacon_bss && |
725 | !list_empty(&found->hidden_list)) { | 720 | !list_empty(&found->hidden_list)) { |
721 | const struct cfg80211_bss_ies *f; | ||
722 | |||
726 | /* | 723 | /* |
727 | * The found BSS struct is one of the probe | 724 | * The found BSS struct is one of the probe |
728 | * response members of a group, but we're | 725 | * response members of a group, but we're |
@@ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
732 | * SSID to showing it, which is confusing so | 729 | * SSID to showing it, which is confusing so |
733 | * drop this information. | 730 | * drop this information. |
734 | */ | 731 | */ |
732 | |||
733 | f = rcu_access_pointer(tmp->pub.beacon_ies); | ||
734 | kfree_rcu((struct cfg80211_bss_ies *)f, | ||
735 | rcu_head); | ||
735 | goto drop; | 736 | goto drop; |
736 | } | 737 | } |
737 | 738 | ||
@@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
761 | kfree_rcu((struct cfg80211_bss_ies *)old, | 762 | kfree_rcu((struct cfg80211_bss_ies *)old, |
762 | rcu_head); | 763 | rcu_head); |
763 | } | 764 | } |
765 | |||
766 | found->pub.beacon_interval = tmp->pub.beacon_interval; | ||
767 | found->pub.signal = tmp->pub.signal; | ||
768 | found->pub.capability = tmp->pub.capability; | ||
769 | found->ts = tmp->ts; | ||
764 | } else { | 770 | } else { |
765 | struct cfg80211_internal_bss *new; | 771 | struct cfg80211_internal_bss *new; |
766 | struct cfg80211_internal_bss *hidden; | 772 | struct cfg80211_internal_bss *hidden; |
@@ -1056,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1056 | if (IS_ERR(rdev)) | 1062 | if (IS_ERR(rdev)) |
1057 | return PTR_ERR(rdev); | 1063 | return PTR_ERR(rdev); |
1058 | 1064 | ||
1065 | mutex_lock(&rdev->sched_scan_mtx); | ||
1059 | if (rdev->scan_req) { | 1066 | if (rdev->scan_req) { |
1060 | err = -EBUSY; | 1067 | err = -EBUSY; |
1061 | goto out; | 1068 | goto out; |
@@ -1162,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1162 | dev_hold(dev); | 1169 | dev_hold(dev); |
1163 | } | 1170 | } |
1164 | out: | 1171 | out: |
1172 | mutex_unlock(&rdev->sched_scan_mtx); | ||
1165 | kfree(creq); | 1173 | kfree(creq); |
1166 | cfg80211_unlock_rdev(rdev); | 1174 | cfg80211_unlock_rdev(rdev); |
1167 | return err; | 1175 | return err; |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 88fc9aa54fe0..a9dc5c736df0 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -85,6 +85,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | |||
85 | ASSERT_RTNL(); | 85 | ASSERT_RTNL(); |
86 | ASSERT_RDEV_LOCK(rdev); | 86 | ASSERT_RDEV_LOCK(rdev); |
87 | ASSERT_WDEV_LOCK(wdev); | 87 | ASSERT_WDEV_LOCK(wdev); |
88 | lockdep_assert_held(&rdev->sched_scan_mtx); | ||
88 | 89 | ||
89 | if (rdev->scan_req) | 90 | if (rdev->scan_req) |
90 | return -EBUSY; | 91 | return -EBUSY; |
@@ -227,6 +228,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
227 | rtnl_lock(); | 228 | rtnl_lock(); |
228 | cfg80211_lock_rdev(rdev); | 229 | cfg80211_lock_rdev(rdev); |
229 | mutex_lock(&rdev->devlist_mtx); | 230 | mutex_lock(&rdev->devlist_mtx); |
231 | mutex_lock(&rdev->sched_scan_mtx); | ||
230 | 232 | ||
231 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 233 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
232 | wdev_lock(wdev); | 234 | wdev_lock(wdev); |
@@ -251,6 +253,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
251 | wdev_unlock(wdev); | 253 | wdev_unlock(wdev); |
252 | } | 254 | } |
253 | 255 | ||
256 | mutex_unlock(&rdev->sched_scan_mtx); | ||
254 | mutex_unlock(&rdev->devlist_mtx); | 257 | mutex_unlock(&rdev->devlist_mtx); |
255 | cfg80211_unlock_rdev(rdev); | 258 | cfg80211_unlock_rdev(rdev); |
256 | rtnl_unlock(); | 259 | rtnl_unlock(); |
@@ -324,11 +327,9 @@ void cfg80211_sme_scan_done(struct net_device *dev) | |||
324 | { | 327 | { |
325 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 328 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
326 | 329 | ||
327 | mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); | ||
328 | wdev_lock(wdev); | 330 | wdev_lock(wdev); |
329 | __cfg80211_sme_scan_done(dev); | 331 | __cfg80211_sme_scan_done(dev); |
330 | wdev_unlock(wdev); | 332 | wdev_unlock(wdev); |
331 | mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); | ||
332 | } | 333 | } |
333 | 334 | ||
334 | void cfg80211_sme_rx_auth(struct net_device *dev, | 335 | void cfg80211_sme_rx_auth(struct net_device *dev, |
@@ -928,9 +929,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
928 | int err; | 929 | int err; |
929 | 930 | ||
930 | mutex_lock(&rdev->devlist_mtx); | 931 | mutex_lock(&rdev->devlist_mtx); |
932 | /* might request scan - scan_mtx -> wdev_mtx dependency */ | ||
933 | mutex_lock(&rdev->sched_scan_mtx); | ||
931 | wdev_lock(dev->ieee80211_ptr); | 934 | wdev_lock(dev->ieee80211_ptr); |
932 | err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); | 935 | err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); |
933 | wdev_unlock(dev->ieee80211_ptr); | 936 | wdev_unlock(dev->ieee80211_ptr); |
937 | mutex_unlock(&rdev->sched_scan_mtx); | ||
934 | mutex_unlock(&rdev->devlist_mtx); | 938 | mutex_unlock(&rdev->devlist_mtx); |
935 | 939 | ||
936 | return err; | 940 | return err; |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ccadef2106ac..3c2033b8f596 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -27,7 +27,8 @@ | |||
27 | #define WIPHY_PR_ARG __entry->wiphy_name | 27 | #define WIPHY_PR_ARG __entry->wiphy_name |
28 | 28 | ||
29 | #define WDEV_ENTRY __field(u32, id) | 29 | #define WDEV_ENTRY __field(u32, id) |
30 | #define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0) | 30 | #define WDEV_ASSIGN (__entry->id) = (!IS_ERR_OR_NULL(wdev) \ |
31 | ? wdev->identifier : 0) | ||
31 | #define WDEV_PR_FMT "wdev(%u)" | 32 | #define WDEV_PR_FMT "wdev(%u)" |
32 | #define WDEV_PR_ARG (__entry->id) | 33 | #define WDEV_PR_ARG (__entry->id) |
33 | 34 | ||
@@ -1778,7 +1779,7 @@ TRACE_EVENT(rdev_set_mac_acl, | |||
1778 | ), | 1779 | ), |
1779 | TP_fast_assign( | 1780 | TP_fast_assign( |
1780 | WIPHY_ASSIGN; | 1781 | WIPHY_ASSIGN; |
1781 | WIPHY_ASSIGN; | 1782 | NETDEV_ASSIGN; |
1782 | __entry->acl_policy = params->acl_policy; | 1783 | __entry->acl_policy = params->acl_policy; |
1783 | ), | 1784 | ), |
1784 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d", | 1785 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d", |
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index fb9622f6d99c..e79cb5c0655a 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -89,6 +89,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
89 | 89 | ||
90 | cfg80211_lock_rdev(rdev); | 90 | cfg80211_lock_rdev(rdev); |
91 | mutex_lock(&rdev->devlist_mtx); | 91 | mutex_lock(&rdev->devlist_mtx); |
92 | mutex_lock(&rdev->sched_scan_mtx); | ||
92 | wdev_lock(wdev); | 93 | wdev_lock(wdev); |
93 | 94 | ||
94 | if (wdev->sme_state != CFG80211_SME_IDLE) { | 95 | if (wdev->sme_state != CFG80211_SME_IDLE) { |
@@ -135,6 +136,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
135 | err = cfg80211_mgd_wext_connect(rdev, wdev); | 136 | err = cfg80211_mgd_wext_connect(rdev, wdev); |
136 | out: | 137 | out: |
137 | wdev_unlock(wdev); | 138 | wdev_unlock(wdev); |
139 | mutex_unlock(&rdev->sched_scan_mtx); | ||
138 | mutex_unlock(&rdev->devlist_mtx); | 140 | mutex_unlock(&rdev->devlist_mtx); |
139 | cfg80211_unlock_rdev(rdev); | 141 | cfg80211_unlock_rdev(rdev); |
140 | return err; | 142 | return err; |
@@ -190,6 +192,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | |||
190 | 192 | ||
191 | cfg80211_lock_rdev(rdev); | 193 | cfg80211_lock_rdev(rdev); |
192 | mutex_lock(&rdev->devlist_mtx); | 194 | mutex_lock(&rdev->devlist_mtx); |
195 | mutex_lock(&rdev->sched_scan_mtx); | ||
193 | wdev_lock(wdev); | 196 | wdev_lock(wdev); |
194 | 197 | ||
195 | err = 0; | 198 | err = 0; |
@@ -223,6 +226,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | |||
223 | err = cfg80211_mgd_wext_connect(rdev, wdev); | 226 | err = cfg80211_mgd_wext_connect(rdev, wdev); |
224 | out: | 227 | out: |
225 | wdev_unlock(wdev); | 228 | wdev_unlock(wdev); |
229 | mutex_unlock(&rdev->sched_scan_mtx); | ||
226 | mutex_unlock(&rdev->devlist_mtx); | 230 | mutex_unlock(&rdev->devlist_mtx); |
227 | cfg80211_unlock_rdev(rdev); | 231 | cfg80211_unlock_rdev(rdev); |
228 | return err; | 232 | return err; |
@@ -285,6 +289,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | |||
285 | 289 | ||
286 | cfg80211_lock_rdev(rdev); | 290 | cfg80211_lock_rdev(rdev); |
287 | mutex_lock(&rdev->devlist_mtx); | 291 | mutex_lock(&rdev->devlist_mtx); |
292 | mutex_lock(&rdev->sched_scan_mtx); | ||
288 | wdev_lock(wdev); | 293 | wdev_lock(wdev); |
289 | 294 | ||
290 | if (wdev->sme_state != CFG80211_SME_IDLE) { | 295 | if (wdev->sme_state != CFG80211_SME_IDLE) { |
@@ -313,6 +318,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | |||
313 | err = cfg80211_mgd_wext_connect(rdev, wdev); | 318 | err = cfg80211_mgd_wext_connect(rdev, wdev); |
314 | out: | 319 | out: |
315 | wdev_unlock(wdev); | 320 | wdev_unlock(wdev); |
321 | mutex_unlock(&rdev->sched_scan_mtx); | ||
316 | mutex_unlock(&rdev->devlist_mtx); | 322 | mutex_unlock(&rdev->devlist_mtx); |
317 | cfg80211_unlock_rdev(rdev); | 323 | cfg80211_unlock_rdev(rdev); |
318 | return err; | 324 | return err; |