* Bug in iw ... scan output for Ad-Hoc (IBSS) output
From: Bill Unruh @ 2019-07-25 20:04 UTC (permalink / raw)
To: linux-wireless
[-- Attachment #1: Type: TEXT/PLAIN, Size: 744 bytes --]
The output of iw .. scan output for Ad-Hoc (IBSS) does not have a carriage
return running it into the next access point output
BSS f6:63:9f:d1:f9:17(on wlp58s0)
TSF: 0 usec (0d, 00:00:00)
freq: 2437
beacon interval: 100 TUs
capability: IBSS ShortPreamble (0x0022)
signal: -69.00 dBm
last seen: 6040 ms ago
Information elements from Probe Response frame:
SSID: hpsetup
Supported rates: 1.0* 2.0* 5.5* 11.0*
DS Parameter set: channel 6
IBSS ATIM window: 0 TUsBSS 34:31:c4:39:63:ef(on wlp58s0)
Note the last line-- that is the BSS of the next access point output of iw
See attachments for full iw wlps58s0 scan output and iwlist scan output.
[-- Attachment #2: Type: TEXT/PLAIN, Size: 35500 bytes --]
BSS 4c:12:65:01:1f:7f(on wlp58s0) -- associated
TSF: 25828446720 usec (0d, 07:10:28)
freq: 2437
beacon interval: 100 TUs
capability: ESS Privacy ShortPreamble ShortSlotTime (0x0431)
signal: -31.00 dBm
last seen: 30 ms ago
Information elements from Probe Response frame:
SSID: Vodafone-A5A0
Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0
DS Parameter set: channel 6
Country: EU Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
ERP: <no flags>
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0x6f
RX LDPC
HT20/HT40
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
No RX STBC
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 4 usec (0x05)
HT Max RX data rate: 450 Mbps
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: no
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* HT Information Exchange Supported
* SSID List
* Operating Mode Notification
* Reserved Reserved Channel Schedule Management
* Reserved Channel Schedule Management
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS b0:98:2b:72:71:65(on wlp58s0)
TSF: 12182903418011 usec (141d, 00:08:23)
freq: 2412
beacon interval: 100 TUs
capability: ESS Privacy ShortPreamble ShortSlotTime (0x0431)
signal: -73.00 dBm
last seen: 6670 ms ago
Information elements from Probe Response frame:
SSID: KabelBox-7160
Supported rates: 1.0* 2.0* 5.5* 11.0* 6.0* 9.0 12.0* 18.0
DS Parameter set: channel 1
Country: DE Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
ERP: <no flags>
Extended supported rates: 24.0* 36.0 48.0 54.0
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 1
* HT protection: no
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Overlapping BSS scan params:
* passive dwell: 20 TUs
* active dwell: 10 TUs
* channel width trigger scan interval: 300 s
* scan passive total per channel: 200 TUs
* scan active total per channel: 20 TUs
* BSS width channel transition delay factor: 5
* OBSS Scan Activity Threshold: 0.25 %
Extended capabilities:
* HT Information Exchange Supported
* SSID List
* Operating Mode Notification
WMM: * Parameter version 1
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
WPS: * Version: 1.0
* Wi-Fi Protected Setup State: 2 (Configured)
* Response Type: 3 (AP)
* UUID: d3e1ca20-9810-b19c-5a30-fba345bb88f6
* Manufacturer: Sagemcom
* Model: SagemcomFAST5460
* Model Number: 1.1-1.1
* Serial Number: LK1731105000215
* Primary Device Type: 6-0050f204-1
* Device name: SagemcomFAST5460-LK17
* Config methods:
* Unknown TLV (0x1049, 6 bytes): 00 37 2a 00 01 20
BSS 5c:a4:8a:dd:66:e0(on wlp58s0)
TSF: 6769178530200 usec (78d, 08:19:38)
freq: 2412
beacon interval: 102 TUs
capability: ESS ShortPreamble ShortSlotTime RadioMeasure (0x1421)
signal: -72.00 dBm
last seen: 6670 ms ago
Information elements from Probe Response frame:
SSID: STUDENTEN-PORTAL
Supported rates: 1.0* 2.0* 5.5* 6.0 9.0 11.0* 12.0 18.0
DS Parameter set: channel 1
Country: DE Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
BSS Load:
* station count: 0
* channel utilisation: 180/255
* available admission capacity: 23437 [*32us]
ERP: <no flags>
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
Extended supported rates: 24.0 36.0 48.0 54.0
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: nonmember
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS 5c:a4:8a:dd:66:e4(on wlp58s0)
TSF: 6769178525529 usec (78d, 08:19:38)
freq: 2412
beacon interval: 102 TUs
capability: ESS Privacy ShortPreamble ShortSlotTime RadioMeasure (0x1431)
signal: -75.00 dBm
last seen: 6660 ms ago
Information elements from Probe Response frame:
SSID: eduroam
Supported rates: 1.0* 2.0* 5.5* 6.0 9.0 11.0* 12.0 18.0
DS Parameter set: channel 1
Country: DE Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
BSS Load:
* station count: 0
* channel utilisation: 180/255
* available admission capacity: 23437 [*32us]
ERP: <no flags>
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: IEEE 802.1X
* Capabilities: 4-PTKSA-RC 4-GTKSA-RC (0x0028)
Extended supported rates: 24.0 36.0 48.0 54.0
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: nonmember
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS 98:9b:cb:1c:9c:7b(on wlp58s0)
TSF: 4070432425458 usec (47d, 02:40:32)
freq: 2437
beacon interval: 100 TUs
capability: ESS Privacy ShortPreamble ShortSlotTime (0x0431)
signal: -33.00 dBm
last seen: 5820 ms ago
Information elements from Probe Response frame:
SSID: FRITZ!Box 4020 TO
Supported rates: 1.0* 2.0* 5.5* 11.0* 6.0* 9.0 12.0* 18.0
DS Parameter set: channel 6
Country: DE Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
ERP: <no flags>
Extended supported rates: 24.0* 36.0 48.0 54.0
HT capabilities:
Capabilities: 0x1ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: nonmember
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Operating Mode Notification
WMM: * Parameter version 1
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
WPS: * Version: 1.0
* Wi-Fi Protected Setup State: 2 (Configured)
* Response Type: 3 (AP)
* UUID: 37890ccc-cf1c-4f19-c6d4-989bcb1c9c7b
* Manufacturer: AVM
* Model: FBox
* Model Number: 0000
* Serial Number: 0000
* Primary Device Type: 6-0050f204-1
* Device name: FBox
* Config methods: Display, PBC, Keypad
* RF Bands: 0x1
* Unknown TLV (0x1049, 6 bytes): 00 37 2a 00 01 20
BSS 9a:9b:cb:1c:9c:7b(on wlp58s0)
TSF: 4070432431659 usec (47d, 02:40:32)
freq: 2437
beacon interval: 100 TUs
capability: ESS Privacy ShortPreamble ShortSlotTime (0x0431)
signal: -31.00 dBm
last seen: 5820 ms ago
Information elements from Probe Response frame:
SSID: Hilger-Rentals
Supported rates: 1.0* 2.0* 5.5* 11.0* 6.0* 9.0 12.0* 18.0
DS Parameter set: channel 6
Country: DE Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
ERP: <no flags>
Extended supported rates: 24.0* 36.0 48.0 54.0
HT capabilities:
Capabilities: 0x1ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: nonmember
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Operating Mode Notification
WMM: * Parameter version 1
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
WPS: * Version: 1.0
* Wi-Fi Protected Setup State: 2 (Configured)
* Response Type: 3 (AP)
* UUID: 7662f430-cbc3-bf7c-bd9a-5d6cedf1272e
* Manufacturer: AVM
* Model: FBox
* Model Number: 0000
* Serial Number: 0000
* Primary Device Type: 6-0050f204-1
* Device name: FBox
* Config methods: Display, PBC, Keypad
* RF Bands: 0x1
* Unknown TLV (0x1049, 6 bytes): 00 37 2a 00 01 20
BSS f6:63:9f:d1:f9:17(on wlp58s0)
TSF: 0 usec (0d, 00:00:00)
freq: 2437
beacon interval: 100 TUs
capability: IBSS ShortPreamble (0x0022)
signal: -69.00 dBm
last seen: 6040 ms ago
Information elements from Probe Response frame:
SSID: hpsetup
Supported rates: 1.0* 2.0* 5.5* 11.0*
DS Parameter set: channel 6
IBSS ATIM window: 0 TUsBSS 34:31:c4:39:63:ef(on wlp58s0)
TSF: 18437528569 usec (0d, 05:07:17)
freq: 2462
beacon interval: 100 TUs
capability: ESS Privacy ShortPreamble ShortSlotTime RadioMeasure (0x1431)
signal: -84.00 dBm
last seen: 5610 ms ago
Information elements from Probe Response frame:
SSID: Skynet
Supported rates: 1.0* 2.0* 5.5* 11.0* 6.0* 9.0 12.0* 18.0
DS Parameter set: channel 11
Country: DE Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
ERP: <no flags>
Extended supported rates: 24.0* 36.0 48.0 54.0
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 11
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 1
* HT protection: no
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Extended Channel Switching
* TFS
* WNM-Sleep Mode
* TIM Broadcast
* BSS Transition
* Operating Mode Notification
WMM: * Parameter version 1
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
WPS: * Version: 1.0
* Wi-Fi Protected Setup State: 2 (Configured)
* Response Type: 3 (AP)
* UUID: 4c74884d-53e4-2c7c-7d15-3431c43963ef
* Manufacturer: AVM
* Model: FBox
* Model Number: 0000
* Serial Number: 0000
* Primary Device Type: 6-0050f204-1
* Device name: FBox
* Config methods: Display, PBC, Keypad
* Unknown TLV (0x1049, 6 bytes): 00 37 2a 00 01 20
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 5c:a4:8a:dd:66:ec(on wlp58s0)
TSF: 6769175027762 usec (78d, 08:19:35)
freq: 5180
beacon interval: 102 TUs
capability: ESS Privacy SpectrumMgmt RadioMeasure (0x1111)
signal: -77.00 dBm
last seen: 5280 ms ago
SSID: \x00
Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0
TIM: DTIM Count 0 DTIM Period 1 Bitmap Control 0x0 Bitmap[0] 0x0
Country: DE Environment: Indoor/Outdoor
Channels [36 - 64] @ 23 dBm
Channels [100 - 116] @ 23 dBm
Channels [132 - 140] @ 30 dBm
BSS Load:
* station count: 1
* channel utilisation: 25/255
* available admission capacity: 23437 [*32us]
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 4-PTKSA-RC 4-GTKSA-RC (0x0028)
HT operation:
* primary channel: 36
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: no
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS 5c:a4:8a:dd:66:ea(on wlp58s0)
TSF: 6769175027762 usec (78d, 08:19:35)
freq: 5180
beacon interval: 102 TUs
capability: ESS Privacy SpectrumMgmt RadioMeasure (0x1111)
signal: -78.00 dBm
last seen: 5270 ms ago
SSID: display
Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0
TIM: DTIM Count 0 DTIM Period 1 Bitmap Control 0x0 Bitmap[0] 0x0
Country: DE Environment: Indoor/Outdoor
Channels [36 - 64] @ 23 dBm
Channels [100 - 116] @ 23 dBm
Channels [132 - 140] @ 30 dBm
BSS Load:
* station count: 1
* channel utilisation: 25/255
* available admission capacity: 23437 [*32us]
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 4-PTKSA-RC 4-GTKSA-RC (0x0028)
HT operation:
* primary channel: 36
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: no
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS 5c:a4:8a:dd:66:ef(on wlp58s0)
TSF: 6769175027762 usec (78d, 08:19:35)
freq: 5180
beacon interval: 102 TUs
capability: ESS SpectrumMgmt RadioMeasure (0x1101)
signal: -78.00 dBm
last seen: 5250 ms ago
SSID: STUDENTEN-PORTAL
Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0
TIM: DTIM Count 0 DTIM Period 1 Bitmap Control 0x0 Bitmap[0] 0x0
Country: DE Environment: Indoor/Outdoor
Channels [36 - 64] @ 23 dBm
Channels [100 - 116] @ 23 dBm
Channels [132 - 140] @ 30 dBm
BSS Load:
* station count: 1
* channel utilisation: 25/255
* available admission capacity: 23437 [*32us]
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 36
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: no
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS 5c:a4:8a:dd:66:eb(on wlp58s0)
TSF: 6769175027762 usec (78d, 08:19:35)
freq: 5180
beacon interval: 102 TUs
capability: ESS Privacy SpectrumMgmt RadioMeasure (0x1111)
signal: -77.00 dBm
last seen: 5230 ms ago
SSID: eduroam
Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0
TIM: DTIM Count 0 DTIM Period 1 Bitmap Control 0x0 Bitmap[0] 0x0
Country: DE Environment: Indoor/Outdoor
Channels [36 - 64] @ 23 dBm
Channels [100 - 116] @ 23 dBm
Channels [132 - 140] @ 30 dBm
BSS Load:
* station count: 1
* channel utilisation: 25/255
* available admission capacity: 23437 [*32us]
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: IEEE 802.1X
* Capabilities: 4-PTKSA-RC 4-GTKSA-RC (0x0028)
HT operation:
* primary channel: 36
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: no
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS 5c:a4:8a:dd:66:ed(on wlp58s0)
TSF: 6769175027762 usec (78d, 08:19:35)
freq: 5180
beacon interval: 102 TUs
capability: ESS SpectrumMgmt RadioMeasure (0x1101)
signal: -78.00 dBm
last seen: 5220 ms ago
SSID: \x00
Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0
TIM: DTIM Count 0 DTIM Period 1 Bitmap Control 0x0 Bitmap[0] 0x0
Country: DE Environment: Indoor/Outdoor
Channels [36 - 64] @ 23 dBm
Channels [100 - 116] @ 23 dBm
Channels [132 - 140] @ 30 dBm
BSS Load:
* station count: 1
* channel utilisation: 25/255
* available admission capacity: 23437 [*32us]
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 36
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: no
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS 5c:a4:8a:dd:66:ee(on wlp58s0)
TSF: 6769175027762 usec (78d, 08:19:35)
freq: 5180
beacon interval: 102 TUs
capability: ESS Privacy SpectrumMgmt RadioMeasure (0x1111)
signal: -78.00 dBm
last seen: 5300 ms ago
SSID: \x00
Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0
TIM: DTIM Count 0 DTIM Period 1 Bitmap Control 0x0 Bitmap[0] 0x0
Country: DE Environment: Indoor/Outdoor
Channels [36 - 64] @ 23 dBm
Channels [100 - 116] @ 23 dBm
Channels [132 - 140] @ 30 dBm
BSS Load:
* station count: 1
* channel utilisation: 25/255
* available admission capacity: 23437 [*32us]
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 4-PTKSA-RC 4-GTKSA-RC (0x0028)
HT operation:
* primary channel: 36
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: no
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS b0:39:56:b4:6b:5a(on wlp58s0)
TSF: 866733158484 usec (10d, 00:45:33)
freq: 5220
beacon interval: 100 TUs
capability: ESS Privacy SpectrumMgmt RadioMeasure (0x1111)
signal: -88.00 dBm
last seen: 4880 ms ago
SSID: NETGEAR55-5G_EXT
Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0
TIM: DTIM Count 0 DTIM Period 1 Bitmap Control 0x0 Bitmap[0] 0x0
Country: DE Environment: Indoor/Outdoor
Channels [36 - 36] @ 23 dBm
Channels [40 - 40] @ 23 dBm
Channels [44 - 44] @ 23 dBm
Channels [48 - 48] @ 23 dBm
Channels [52 - 52] @ 23 dBm
Channels [56 - 56] @ 23 dBm
Channels [60 - 60] @ 23 dBm
Channels [64 - 64] @ 23 dBm
Channels [100 - 100] @ 30 dBm
Channels [104 - 104] @ 30 dBm
Channels [108 - 108] @ 30 dBm
Channels [112 - 112] @ 30 dBm
Channels [116 - 116] @ 30 dBm
Channels [132 - 132] @ 30 dBm
Channels [136 - 136] @ 30 dBm
Channels [140 - 140] @ 30 dBm
Power constraint: 0 dB
TPC report: TX power: 20 dBm
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0x963
RX LDPC
HT20/HT40
Static SM Power Save
RX HT20 SGI
RX HT40 SGI
RX STBC 1-stream
Max AMSDU length: 7935 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 4 usec (0x05)
HT Max RX data rate: 384 Mbps
HT RX MCS rate indexes supported: 0-7
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 44
* secondary channel offset: above
* STA channel width: any
* RIFS: 1
* HT protection: no
* non-GF present: 0
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Overlapping BSS scan params:
* passive dwell: 20 TUs
* active dwell: 10 TUs
* channel width trigger scan interval: 300 s
* scan passive total per channel: 200 TUs
* scan active total per channel: 20 TUs
* BSS width channel transition delay factor: 5
* OBSS Scan Activity Threshold: 0.25 %
Extended capabilities:
* Extended Channel Switching
* Operating Mode Notification
* Max Number Of MSDUs In A-MSDU is unlimited
VHT capabilities:
VHT Capabilities (0x0f907932):
Max MPDU length: 11454
Supported Channel Width: neither 160 nor 80+80
RX LDPC
short GI (80 MHz)
SU Beamformer
SU Beamformee
MU Beamformee
VHT RX MCS set:
1 streams: MCS 0-9
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
VHT RX highest supported: 0 Mbps
VHT TX MCS set:
1 streams: MCS 0-9
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
VHT TX highest supported: 0 Mbps
VHT operation:
* channel width: 1 (80 MHz)
* center freq segment 1: 42
* center freq segment 2: 0
* VHT basic MCS set: 0x0000
WPS: * Version: 1.0
* Wi-Fi Protected Setup State: 2 (Configured)
* UUID: e942950b-6f24-aa04-ef84-ca18eb08cd3a
* RF Bands: 0x2
* Unknown TLV (0x1049, 10 bytes): 00 37 2a 00 01 20 05 02 26 88
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS 5c:a4:8a:dd:66:e1(on wlp58s0)
TSF: 6769178685343 usec (78d, 08:19:38)
freq: 2412
beacon interval: 102 TUs
capability: ESS Privacy ShortPreamble ShortSlotTime RadioMeasure (0x1431)
signal: -73.00 dBm
last seen: 6570 ms ago
SSID: \x00
Supported rates: 1.0* 2.0* 5.5* 6.0 9.0 11.0* 12.0 18.0
DS Parameter set: channel 1
TIM: DTIM Count 0 DTIM Period 1 Bitmap Control 0x0 Bitmap[0] 0x0
Country: DE Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
BSS Load:
* station count: 0
* channel utilisation: 180/255
* available admission capacity: 23437 [*32us]
ERP: <no flags>
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 4-PTKSA-RC 4-GTKSA-RC (0x0028)
Extended supported rates: 24.0 36.0 48.0 54.0
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: nonmember
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS 5c:a4:8a:dd:66:e5(on wlp58s0)
TSF: 6769178559469 usec (78d, 08:19:38)
freq: 2412
beacon interval: 102 TUs
capability: ESS Privacy ShortPreamble ShortSlotTime RadioMeasure (0x1431)
signal: -72.00 dBm
last seen: 6430 ms ago
Information elements from Probe Response frame:
SSID: display
Supported rates: 1.0* 2.0* 5.5* 6.0 9.0 11.0* 12.0 18.0
DS Parameter set: channel 1
Country: DE Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
BSS Load:
* station count: 0
* channel utilisation: 180/255
* available admission capacity: 23437 [*32us]
ERP: <no flags>
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 4-PTKSA-RC 4-GTKSA-RC (0x0028)
Extended supported rates: 24.0 36.0 48.0 54.0
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: nonmember
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS 5c:a4:8a:dd:66:e3(on wlp58s0)
TSF: 6769178593098 usec (78d, 08:19:38)
freq: 2412
beacon interval: 102 TUs
capability: ESS Privacy ShortPreamble ShortSlotTime RadioMeasure (0x1431)
signal: -73.00 dBm
last seen: 6640 ms ago
SSID: \x00
Supported rates: 1.0* 2.0* 5.5* 6.0 9.0 11.0* 12.0 18.0
DS Parameter set: channel 1
TIM: DTIM Count 0 DTIM Period 1 Bitmap Control 0x0 Bitmap[0] 0x0
Country: DE Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
BSS Load:
* station count: 0
* channel utilisation: 180/255
* available admission capacity: 23437 [*32us]
ERP: <no flags>
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 4-PTKSA-RC 4-GTKSA-RC (0x0028)
Extended supported rates: 24.0 36.0 48.0 54.0
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: nonmember
* non-GF present: 1
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Proxy ARP Service
* QoS Map
* WNM-Notification
WMM: * Parameter version 1
* u-APSD
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
BSS f0:b0:14:00:79:e8(on wlp58s0)
TSF: 2438861184 usec (0d, 00:40:38)
freq: 2462
beacon interval: 100 TUs
capability: ESS Privacy ShortPreamble ShortSlotTime RadioMeasure (0x1431)
signal: -88.00 dBm
last seen: 5590 ms ago
SSID: MegaMindGreenStreet
Supported rates: 1.0* 2.0* 5.5* 11.0* 6.0* 9.0 12.0* 18.0
DS Parameter set: channel 11
TIM: DTIM Count 0 DTIM Period 1 Bitmap Control 0x0 Bitmap[0] 0x0
Country: DE Environment: Indoor/Outdoor
Channels [1 - 13] @ 20 dBm
ERP: <no flags>
Extended supported rates: 24.0* 36.0 48.0 54.0
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 11
* secondary channel offset: no secondary
* STA channel width: 20 MHz
* RIFS: 0
* HT protection: nonmember
* non-GF present: 0
* OBSS non-GF present: 0
* dual beacon: 0
* dual CTS protection: 0
* STBC beacon: 0
* L-SIG TXOP Prot: 0
* PCO active: 0
* PCO phase: 0
Extended capabilities:
* Extended Channel Switching
* TFS
* WNM-Sleep Mode
* TIM Broadcast
* BSS Transition
* Operating Mode Notification
WMM: * Parameter version 1
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: CW 3-7, AIFSN 2, TXOP 1504 usec
WPS: * Version: 1.0
* Wi-Fi Protected Setup State: 2 (Configured)
* RF Bands: 0x3
* Unknown TLV (0x1049, 6 bytes): 00 37 2a 00 01 20
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
[-- Attachment #3: Type: TEXT/PLAIN, Size: 25915 bytes --]
wlp58s0 Scan completed :
Cell 01 - Address: 4C:12:65:01:1F:7F
Channel:6
Frequency:2.437 GHz (Channel 6)
Quality=70/70 Signal level=-31 dBm
Encryption key:on
ESSID:"Vodafone-A5A0"
Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=00000006015ce15a
Extra: Last beacon: 320ms ago
IE: Unknown: 000D566F6461666F6E652D41354130
IE: Unknown: 01088C129824B048606C
IE: Unknown: 030106
IE: Unknown: 0706455520010D14
IE: Unknown: 2A0100
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : PSK
IE: Unknown: 2D1A6F0017FFFFFF00000000000000C2010100000000001004870100
IE: Unknown: 3D1606000400000000000000000000000000000000000000
IE: Unknown: 7F0901000002000000C001
IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
Cell 02 - Address: B0:98:2B:72:71:65
Channel:1
Frequency:2.412 GHz (Channel 1)
Quality=34/70 Signal level=-76 dBm
Encryption key:on
ESSID:"KabelBox-7160"
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 6 Mb/s
9 Mb/s; 12 Mb/s; 18 Mb/s
Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=00000b148b88e6b3
Extra: Last beacon: 6690ms ago
IE: Unknown: 000D4B6162656C426F782D37313630
IE: Unknown: 010882848B968C129824
IE: Unknown: 030101
IE: Unknown: 0706444520010D14
IE: Unknown: 2A0100
IE: Unknown: 3204B048606C
IE: Unknown: 2D1AAD011BFFFFFF00000000000000000001000000000406E6470D00
IE: Unknown: 3D1601080400000000000000000000000000000000000000
IE: Unknown: 4A0E14000A002C01C800140005001900
IE: Unknown: 7F080100000200000040
IE: Unknown: DD180050F2020101000003A4000027A4000042435E0062322F00
IE: Unknown: DD0900037F01010000FF7F
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : PSK
IE: Unknown: DD9A0050F204104A0001101044000102103B00010310470010D3E1CA209810B19C5A30FBA345BB88F610210008536167656D636F6D10230010536167656D636F6D464153543534363010240007312E312D312E311042000F4C4B313733313130353030303231351054000800060050F204000110110015536167656D636F6D46415354353436302D4C4B31371008000200001049000600372A000120
Cell 03 - Address: 5C:A4:8A:DD:66:E0
Channel:1
Frequency:2.412 GHz (Channel 1)
Quality=37/70 Signal level=-73 dBm
Encryption key:off
ESSID:"STUDENTEN-PORTAL"
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 6 Mb/s; 9 Mb/s
11 Mb/s; 12 Mb/s; 18 Mb/s
Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=0000062810647e87
Extra: Last beacon: 6580ms ago
IE: Unknown: 001053545544454E54454E2D504F5254414C
IE: Unknown: 010882848B0C12961824
IE: Unknown: 030101
IE: Unknown: 0706444520010D14
IE: Unknown: 0B0500009C8D5B
IE: Unknown: 2A0100
IE: Unknown: 2D1AAC191BFFFFFF0000000000000000000000000000000000000000
IE: Unknown: 32043048606C
IE: Unknown: 3D1601000500000000000000000000000000000000000000
IE: Unknown: 7F06001000000140
IE: Unknown: 851E0B008F000F00FF0359005365727665727261756D2D477275650000000040
IE: Unknown: 9606004096001000
IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
IE: Unknown: DD06004096010104
IE: Unknown: DD050040960305
IE: Unknown: DD050040960B09
IE: Unknown: DD050040961400
Cell 04 - Address: 5C:A4:8A:DD:66:E4
Channel:1
Frequency:2.412 GHz (Channel 1)
Quality=35/70 Signal level=-75 dBm
Encryption key:on
ESSID:"eduroam"
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 6 Mb/s; 9 Mb/s
11 Mb/s; 12 Mb/s; 18 Mb/s
Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=0000062810645877
Extra: Last beacon: 6580ms ago
IE: Unknown: 0007656475726F616D
IE: Unknown: 010882848B0C12961824
IE: Unknown: 030101
IE: Unknown: 0706444520010D14
IE: Unknown: 0B0500009C8D5B
IE: Unknown: 2A0100
IE: Unknown: 2D1AAC191BFFFFFF0000000000000000000000000000000000000000
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : 802.1x
IE: Unknown: 32043048606C
IE: Unknown: 3D1601000500000000000000000000000000000000000000
IE: Unknown: 7F06001000000140
IE: Unknown: 851E0B008F000F00FF0359005365727665727261756D2D477275650000000040
IE: Unknown: 9606004096001000
IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
IE: Unknown: DD06004096010104
IE: Unknown: DD050040960305
IE: Unknown: DD050040960B09
IE: Unknown: DD050040961401
Cell 05 - Address: 98:9B:CB:1C:9C:7B
Channel:6
Frequency:2.437 GHz (Channel 6)
Quality=70/70 Signal level=-29 dBm
Encryption key:on
ESSID:"FRITZ!Box 4020 TO"
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 6 Mb/s
9 Mb/s; 12 Mb/s; 18 Mb/s
Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=000003b3b690e665
Extra: Last beacon: 6110ms ago
IE: Unknown: 0011465249545A21426F78203430323020544F
IE: Unknown: 010882848B968C129824
IE: Unknown: 030106
IE: Unknown: 0706444520010D14
IE: Unknown: 2A0100
IE: Unknown: 3204B048606C
IE: Unknown: 2D1AAC011BFFFFFF0000000000000000000100000000000000000000
IE: Unknown: 3D1606000500000000000000000000000000000000000000
IE: Unknown: 7F080000000000000040
IE: Unknown: DD180050F2020101000003A4000027A4000042435E0062322F00
IE: Unknown: DD0900037F01010000FF7F
IE: Unknown: DD0C00040E010102010000000000
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : PSK
IE: Unknown: DD6F0050F204104A0001101044000102103B0001031047001037890CCCCF1C4F19C6D4989BCB1C9C7B1021000341564D1023000446426F78102400043030303010420004303030301054000800060050F20400011011000446426F78100800022388103C0001011049000600372A000120
Cell 06 - Address: 9A:9B:CB:1C:9C:7B
Channel:6
Frequency:2.437 GHz (Channel 6)
Quality=70/70 Signal level=-28 dBm
Encryption key:on
ESSID:"Hilger-Rentals"
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 6 Mb/s
9 Mb/s; 12 Mb/s; 18 Mb/s
Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=000003b3b690f452
Extra: Last beacon: 6100ms ago
IE: Unknown: 000E48696C6765722D52656E74616C73
IE: Unknown: 010882848B968C129824
IE: Unknown: 030106
IE: Unknown: 0706444520010D14
IE: Unknown: 2A0100
IE: Unknown: 3204B048606C
IE: Unknown: 2D1AAC011BFFFFFF0000000000000000000100000000000000000000
IE: Unknown: 3D1606000500000000000000000000000000000000000000
IE: Unknown: 7F080000000000000040
IE: Unknown: DD180050F2020101000003A4000027A4000042435E0062322F00
IE: Unknown: DD0900037F01010000FF7F
IE: Unknown: DD0C00040E010102010000000000
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : PSK
IE: Unknown: DD6F0050F204104A0001101044000102103B000103104700107662F430CBC3BF7CBD9A5D6CEDF1272E1021000341564D1023000446426F78102400043030303010420004303030301054000800060050F20400011011000446426F78100800022388103C0001011049000600372A000120
Cell 07 - Address: 44:4E:6D:39:97:09
Channel:6
Frequency:2.437 GHz (Channel 6)
Quality=28/70 Signal level=-82 dBm
Encryption key:on
ESSID:"FRITZ!Box 1337"
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 6 Mb/s
9 Mb/s; 12 Mb/s; 18 Mb/s
Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=0000003fa95bf4b0
Extra: Last beacon: 6200ms ago
IE: Unknown: 000E465249545A21426F782031333337
IE: Unknown: 010882848B968C129824
IE: Unknown: 030106
IE: Unknown: 0706444520010D14
IE: Unknown: 2A0100
IE: Unknown: 3204B048606C
IE: Unknown: 2D1AAD011BFFFFFF00000000000000000001000000000406E6470D00
IE: Unknown: 3D1606000500000000000000000000000000000000000000
IE: Unknown: 7F080000000000000040
IE: Unknown: DD180050F2020101000003A4000027A4000042435E0062322F00
IE: Unknown: DD0900037F01010000FF7F
IE: Unknown: DD0C00040E010102010000000000
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : PSK
IE: Unknown: DD6F0050F204104A0001101044000102103B00010310470010B3D22B027A1889FF6E2D444E6D3997091021000341564D1023000446426F78102400043030303010420004303030301054000800060050F20400011011000446426F78100800022388103C0001011049000600372A000120
Cell 08 - Address: F6:63:9F:D1:F9:17
Channel:6
Frequency:2.437 GHz (Channel 6)
Quality=42/70 Signal level=-68 dBm
Encryption key:off
ESSID:"hpsetup"
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s
Mode:Ad-Hoc
Extra:tsf=0000000000000000
Extra: Last beacon: 6100ms ago
IE: Unknown: 000768707365747570
IE: Unknown: 010482848B96
IE: Unknown: 030106
IE: Unknown: 06020000
Cell 09 - Address: 34:31:C4:39:63:EF
Channel:11
Frequency:2.462 GHz (Channel 11)
Quality=30/70 Signal level=-80 dBm
Encryption key:on
ESSID:"Skynet"
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 6 Mb/s
9 Mb/s; 12 Mb/s; 18 Mb/s
Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=000000044af65bf9
Extra: Last beacon: 5800ms ago
IE: Unknown: 0006536B796E6574
IE: Unknown: 010882848B968C129824
IE: Unknown: 03010B
IE: Unknown: 0706444520010D14
IE: Unknown: 2A0100
IE: Unknown: 3204B048606C
IE: Unknown: 460573D000000C
IE: Unknown: 2D1AAD011BFFFFFF00000000000000000001000000000406E6470D00
IE: Unknown: 3D160B080400000000000000000000000000000000000000
IE: Unknown: 7F0804000F0000000040
IE: Unknown: DD180050F2020101000003A4000027A4000042435E0062322F00
IE: Unknown: DD0900037F01010000FF7F
IE: Unknown: DD0C00040E010102010000000000
IE: Unknown: DD168CFDF004000049000003020972018C160000CDAB0000
IE: Unknown: DD6A0050F204104A0001101044000102103B000103104700104C74884D53E42C7C7D153431C43963EF1021000341564D1023000446426F78102400043030303010420004303030301054000800060050F20400011011000446426F781008000223881049000600372A000120
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : PSK
IE: Unknown: DD088CFDF00101020100
Cell 10 - Address: 5C:A4:8A:DD:66:EC
Channel:36
Frequency:5.18 GHz (Channel 36)
Quality=33/70 Signal level=-77 dBm
Encryption key:on
ESSID:"\x00"
Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=00000628102cc832
Extra: Last beacon: 5340ms ago
IE: Unknown: 000100
IE: Unknown: 01088C129824B048606C
IE: Unknown: 050400010000
IE: Unknown: 070C44452024081764051784031E
IE: Unknown: 0B050000168D5B
IE: Unknown: 2D1AAC191BFFFFFF0000000000000000000000000000000000000000
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : PSK
IE: Unknown: 3D1624000400000000000000000000000000000000000000
IE: Unknown: 7F06001000000140
IE: Unknown: 851E01008F000F00FF0359005365727665727261756D2D47727565000000003F
IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
IE: Unknown: DD06004096010104
IE: Unknown: DD050040960305
IE: Unknown: DD050040960B09
IE: Unknown: DD050040961401
Cell 11 - Address: 5C:A4:8A:DD:66:EA
Channel:36
Frequency:5.18 GHz (Channel 36)
Quality=33/70 Signal level=-77 dBm
Encryption key:on
ESSID:"display"
Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=00000628102cc84d
Extra: Last beacon: 5320ms ago
IE: Unknown: 0007646973706C6179
IE: Unknown: 01088C129824B048606C
IE: Unknown: 050400010000
IE: Unknown: 070C44452024081764051784031E
IE: Unknown: 0B050000168D5B
IE: Unknown: 2D1AAC191BFFFFFF0000000000000000000000000000000000000000
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : PSK
IE: Unknown: 3D1624000400000000000000000000000000000000000000
IE: Unknown: 7F06001000000140
IE: Unknown: 851E01008F000F00FF0359005365727665727261756D2D47727565000000003F
IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
IE: Unknown: DD06004096010104
IE: Unknown: DD050040960305
IE: Unknown: DD050040960B09
IE: Unknown: DD050040961401
Cell 12 - Address: 5C:A4:8A:DD:66:EF
Channel:36
Frequency:5.18 GHz (Channel 36)
Quality=32/70 Signal level=-78 dBm
Encryption key:off
ESSID:"STUDENTEN-PORTAL"
Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=00000628102cc832
Extra: Last beacon: 5310ms ago
IE: Unknown: 001053545544454E54454E2D504F5254414C
IE: Unknown: 01088C129824B048606C
IE: Unknown: 050400010000
IE: Unknown: 070C44452024081764051784031E
IE: Unknown: 0B050000168D5B
IE: Unknown: 2D1AAC191BFFFFFF0000000000000000000000000000000000000000
IE: Unknown: 3D1624000400000000000000000000000000000000000000
IE: Unknown: 7F06001000000140
IE: Unknown: 851E01008F000F00FF0359005365727665727261756D2D47727565000000003F
IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
IE: Unknown: DD06004096010104
IE: Unknown: DD050040960305
IE: Unknown: DD050040960B09
IE: Unknown: DD050040961400
Cell 13 - Address: 5C:A4:8A:DD:66:EB
Channel:36
Frequency:5.18 GHz (Channel 36)
Quality=32/70 Signal level=-78 dBm
Encryption key:on
ESSID:"eduroam"
Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=00000628102b3032
Extra: Last beacon: 5400ms ago
IE: Unknown: 0007656475726F616D
IE: Unknown: 01088C129824B048606C
IE: Unknown: 050400010000
IE: Unknown: 070C44452024081764051784031E
IE: Unknown: 0B050000168D5B
IE: Unknown: 2D1AAC191BFFFFFF0000000000000000000000000000000000000000
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : 802.1x
IE: Unknown: 3D1624000400000000000000000000000000000000000000
IE: Unknown: 7F06001000000140
IE: Unknown: 851E01008F000F00FF0359005365727665727261756D2D47727565000000003F
IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
IE: Unknown: DD06004096010104
IE: Unknown: DD050040960305
IE: Unknown: DD050040960B09
IE: Unknown: DD050040961401
Cell 14 - Address: 5C:A4:8A:DD:66:ED
Channel:36
Frequency:5.18 GHz (Channel 36)
Quality=33/70 Signal level=-77 dBm
Encryption key:off
ESSID:"\x00"
Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=00000628102b3032
Extra: Last beacon: 5380ms ago
IE: Unknown: 000100
IE: Unknown: 01088C129824B048606C
IE: Unknown: 050400010000
IE: Unknown: 070C44452024081764051784031E
IE: Unknown: 0B050000168D5B
IE: Unknown: 2D1AAC191BFFFFFF0000000000000000000000000000000000000000
IE: Unknown: 3D1624000400000000000000000000000000000000000000
IE: Unknown: 7F06001000000140
IE: Unknown: 851E01008F000F00FF0359005365727665727261756D2D47727565000000003F
IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
IE: Unknown: DD06004096010104
IE: Unknown: DD050040960305
IE: Unknown: DD050040960B09
IE: Unknown: DD050040961400
Cell 15 - Address: 5C:A4:8A:DD:66:EE
Channel:36
Frequency:5.18 GHz (Channel 36)
Quality=32/70 Signal level=-78 dBm
Encryption key:on
ESSID:"\x00"
Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=00000628102cc832
Extra: Last beacon: 5360ms ago
IE: Unknown: 000100
IE: Unknown: 01088C129824B048606C
IE: Unknown: 050400010000
IE: Unknown: 070C44452024081764051784031E
IE: Unknown: 0B050000168D5B
IE: Unknown: 2D1AAC191BFFFFFF0000000000000000000000000000000000000000
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : PSK
IE: Unknown: 3D1624000400000000000000000000000000000000000000
IE: Unknown: 7F06001000000140
IE: Unknown: 851E01008F000F00FF0359005365727665727261756D2D47727565000000003F
IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
IE: Unknown: DD06004096010104
IE: Unknown: DD050040960305
IE: Unknown: DD050040960B09
IE: Unknown: DD050040961401
Cell 16 - Address: B0:39:56:B4:6B:5A
Channel:44
Frequency:5.22 GHz (Channel 44)
Quality=23/70 Signal level=-87 dBm
Encryption key:on
ESSID:"NETGEAR55-5G_EXT"
Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Mode:Master
Extra:tsf=000000c9cb38f052
Extra: Last beacon: 4970ms ago
IE: Unknown: 00104E45544745415235352D35475F455854
IE: Unknown: 01088C129824B048606C
IE: Unknown: 050400010000
IE: Unknown: 07344445202401172801172C01173001173401173801173C011740011764011E68011E6C011E70011E74011E84011E88011E8C011E00
IE: Unknown: 200100
IE: Unknown: 23021400
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : CCMP
Pairwise Ciphers (1) : CCMP
Authentication Suites (1) : PSK
IE: Unknown: 46053208010000
IE: Unknown: 2D1A630917FF00000000000000000080010000000000000000000000
IE: Unknown: 3D162C0D0000000000000000000000000000000000000000
IE: Unknown: 4A0E14000A002C01C800140005001900
IE: Unknown: 7F080400000000000040
IE: Unknown: BF0C3279900FFEFF0000FEFF0000
IE: Unknown: C005012A000000
IE: Unknown: C30402000000
IE: Unknown: DD350050F204104A000110104400010210470010E942950B6F24AA04EF84CA18EB08CD3A103C0001021049000A00372A00012005022688
IE: Unknown: DD090010180200001C0000
IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
^ permalink raw reply
* [PATCH] mac80211_hwsim: Fix a typo in the name of function 'mac80211_hswim_he_capab()'
From: Christophe JAILLET @ 2019-07-25 19:13 UTC (permalink / raw)
To: johannes, kvalo, davem
Cc: linux-wireless, netdev, linux-kernel, kernel-janitors,
Christophe JAILLET
This function name should be 'mac80211_hwsim_he_capab()' (s wand w
switched) to be consistent with the rest of the file.
Fix and use it.
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
---
drivers/net/wireless/mac80211_hwsim.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index b5274d1f30fa..64b0e51f8e8d 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2595,7 +2595,7 @@ static const struct ieee80211_sband_iftype_data he_capa_5ghz = {
},
};
-static void mac80211_hswim_he_capab(struct ieee80211_supported_band *sband)
+static void mac80211_hwsim_he_capab(struct ieee80211_supported_band *sband)
{
if (sband->band == NL80211_BAND_2GHZ)
sband->iftype_data =
@@ -2898,7 +2898,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
sband->ht_cap.mcs.rx_mask[1] = 0xff;
sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
- mac80211_hswim_he_capab(sband);
+ mac80211_hwsim_he_capab(sband);
hw->wiphy->bands[band] = sband;
}
--
2.20.1
^ permalink raw reply related
* [PATCH 0/3] ath10k: Clean up regulator and clock handling
From: Bjorn Andersson @ 2019-07-25 17:47 UTC (permalink / raw)
To: Kalle Valo, Govind Singh
Cc: David S. Miller, ath10k, linux-wireless, netdev, linux-kernel,
linux-arm-msm
The first patch in this series removes the regulator_set_voltage() of a fixed
voltate, as fixed regulator constraints should be specified on a board level
and on certain boards - such as the Lenovo Yoga C630 - the voltage specified
for the 3.3V regulator is outside the given range.
The following two patches cleans up regulator and clock usage by using the bulk
API provided by the two frameworks.
Bjorn Andersson (3):
ath10k: snoc: skip regulator operations
ath10k: Use standard regulator bulk API in snoc
ath10k: Use standard bulk clock API in snoc
drivers/net/wireless/ath/ath10k/snoc.c | 324 ++++---------------------
drivers/net/wireless/ath/ath10k/snoc.h | 26 +-
2 files changed, 48 insertions(+), 302 deletions(-)
--
2.18.0
^ permalink raw reply
* [PATCH 2/3] ath10k: Use standard regulator bulk API in snoc
From: Bjorn Andersson @ 2019-07-25 17:47 UTC (permalink / raw)
To: Kalle Valo, Govind Singh
Cc: David S. Miller, ath10k, linux-wireless, netdev, linux-kernel,
linux-arm-msm
In-Reply-To: <20190725174755.23432-1-bjorn.andersson@linaro.org>
The regulator_get_optional() exists for cases where the driver needs do
behave differently depending on some regulator supply being present or
not, as we don't use this we can use the standard regulator_get() and
rely on its handling of unspecified regulators.
While the driver currently doesn't specify any loads the regulator
framework was updated last year to only account for load of enabled
regulators, so should the need appear it's better to apply load numbers
during initialization that dynamically.
With this the regulator wrappers have been reduced the become identical
to the standard bulk API provided by the regulator framework, so use
these instead of rolling our own.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
drivers/net/wireless/ath/ath10k/snoc.c | 184 ++++---------------------
drivers/net/wireless/ath/ath10k/snoc.h | 13 +-
2 files changed, 27 insertions(+), 170 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 3d93ab09a298..1c9ff7e53e2f 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -36,11 +36,11 @@ static char *const ce_name[] = {
"WLAN_CE_11",
};
-static struct ath10k_vreg_info vreg_cfg[] = {
- {NULL, "vdd-0.8-cx-mx", 0, 0, false},
- {NULL, "vdd-1.8-xo", 0, 0, false},
- {NULL, "vdd-1.3-rfa", 0, 0, false},
- {NULL, "vdd-3.3-ch0", 0, 0, false},
+static const char * const ath10k_regulators[] = {
+ "vdd-0.8-cx-mx",
+ "vdd-1.8-xo",
+ "vdd-1.3-rfa",
+ "vdd-3.3-ch0",
};
static struct ath10k_clk_info clk_cfg[] = {
@@ -1346,43 +1346,6 @@ static void ath10k_snoc_release_resource(struct ath10k *ar)
ath10k_ce_free_pipe(ar, i);
}
-static int ath10k_get_vreg_info(struct ath10k *ar, struct device *dev,
- struct ath10k_vreg_info *vreg_info)
-{
- struct regulator *reg;
- int ret = 0;
-
- reg = devm_regulator_get_optional(dev, vreg_info->name);
-
- if (IS_ERR(reg)) {
- ret = PTR_ERR(reg);
-
- if (ret == -EPROBE_DEFER) {
- ath10k_err(ar, "EPROBE_DEFER for regulator: %s\n",
- vreg_info->name);
- return ret;
- }
- if (vreg_info->required) {
- ath10k_err(ar, "Regulator %s doesn't exist: %d\n",
- vreg_info->name, ret);
- return ret;
- }
- ath10k_dbg(ar, ATH10K_DBG_SNOC,
- "Optional regulator %s doesn't exist: %d\n",
- vreg_info->name, ret);
- goto done;
- }
-
- vreg_info->reg = reg;
-
-done:
- ath10k_dbg(ar, ATH10K_DBG_SNOC,
- "snog vreg %s load_ua %u settle_delay %lu\n",
- vreg_info->name, vreg_info->load_ua, vreg_info->settle_delay);
-
- return 0;
-}
-
static int ath10k_get_clk_info(struct ath10k *ar, struct device *dev,
struct ath10k_clk_info *clk_info)
{
@@ -1411,114 +1374,6 @@ static int ath10k_get_clk_info(struct ath10k *ar, struct device *dev,
return ret;
}
-static int __ath10k_snoc_vreg_on(struct ath10k *ar,
- struct ath10k_vreg_info *vreg_info)
-{
- int ret;
-
- ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc regulator %s being enabled\n",
- vreg_info->name);
-
- if (vreg_info->load_ua) {
- ret = regulator_set_load(vreg_info->reg, vreg_info->load_ua);
- if (ret < 0) {
- ath10k_err(ar, "failed to set regulator %s load: %d\n",
- vreg_info->name, vreg_info->load_ua);
- goto err_set_load;
- }
- }
-
- ret = regulator_enable(vreg_info->reg);
- if (ret) {
- ath10k_err(ar, "failed to enable regulator %s\n",
- vreg_info->name);
- goto err_enable;
- }
-
- if (vreg_info->settle_delay)
- udelay(vreg_info->settle_delay);
-
- return 0;
-
-err_enable:
- regulator_set_load(vreg_info->reg, 0);
-err_set_load:
-
- return ret;
-}
-
-static int __ath10k_snoc_vreg_off(struct ath10k *ar,
- struct ath10k_vreg_info *vreg_info)
-{
- int ret;
-
- ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc regulator %s being disabled\n",
- vreg_info->name);
-
- ret = regulator_disable(vreg_info->reg);
- if (ret)
- ath10k_err(ar, "failed to disable regulator %s\n",
- vreg_info->name);
-
- ret = regulator_set_load(vreg_info->reg, 0);
- if (ret < 0)
- ath10k_err(ar, "failed to set load %s\n", vreg_info->name);
-
- return ret;
-}
-
-static int ath10k_snoc_vreg_on(struct ath10k *ar)
-{
- struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
- struct ath10k_vreg_info *vreg_info;
- int ret = 0;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(vreg_cfg); i++) {
- vreg_info = &ar_snoc->vreg[i];
-
- if (!vreg_info->reg)
- continue;
-
- ret = __ath10k_snoc_vreg_on(ar, vreg_info);
- if (ret)
- goto err_reg_config;
- }
-
- return 0;
-
-err_reg_config:
- for (i = i - 1; i >= 0; i--) {
- vreg_info = &ar_snoc->vreg[i];
-
- if (!vreg_info->reg)
- continue;
-
- __ath10k_snoc_vreg_off(ar, vreg_info);
- }
-
- return ret;
-}
-
-static int ath10k_snoc_vreg_off(struct ath10k *ar)
-{
- struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
- struct ath10k_vreg_info *vreg_info;
- int ret = 0;
- int i;
-
- for (i = ARRAY_SIZE(vreg_cfg) - 1; i >= 0; i--) {
- vreg_info = &ar_snoc->vreg[i];
-
- if (!vreg_info->reg)
- continue;
-
- ret = __ath10k_snoc_vreg_off(ar, vreg_info);
- }
-
- return ret;
-}
-
static int ath10k_snoc_clk_init(struct ath10k *ar)
{
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
@@ -1591,11 +1446,12 @@ static int ath10k_snoc_clk_deinit(struct ath10k *ar)
static int ath10k_hw_power_on(struct ath10k *ar)
{
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
int ret;
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power on\n");
- ret = ath10k_snoc_vreg_on(ar);
+ ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs);
if (ret)
return ret;
@@ -1606,21 +1462,19 @@ static int ath10k_hw_power_on(struct ath10k *ar)
return ret;
vreg_off:
- ath10k_snoc_vreg_off(ar);
+ regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
return ret;
}
static int ath10k_hw_power_off(struct ath10k *ar)
{
- int ret;
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power off\n");
ath10k_snoc_clk_deinit(ar);
- ret = ath10k_snoc_vreg_off(ar);
-
- return ret;
+ return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
}
static const struct of_device_id ath10k_snoc_dt_match[] = {
@@ -1691,12 +1545,20 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
goto err_release_resource;
}
- ar_snoc->vreg = vreg_cfg;
- for (i = 0; i < ARRAY_SIZE(vreg_cfg); i++) {
- ret = ath10k_get_vreg_info(ar, dev, &ar_snoc->vreg[i]);
- if (ret)
- goto err_free_irq;
+ ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators);
+ ar_snoc->vregs = devm_kcalloc(&pdev->dev, ar_snoc->num_vregs,
+ sizeof(*ar_snoc->vregs), GFP_KERNEL);
+ if (!ar_snoc->vregs) {
+ ret = -ENOMEM;
+ goto err_free_irq;
}
+ for (i = 0; i < ar_snoc->num_vregs; i++)
+ ar_snoc->vregs[i].supply = ath10k_regulators[i];
+
+ ret = devm_regulator_bulk_get(&pdev->dev, ar_snoc->num_vregs,
+ ar_snoc->vregs);
+ if (ret < 0)
+ goto err_free_irq;
ar_snoc->clk = clk_cfg;
for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index 1bf7bd4ef2a3..3965ddf66d74 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -42,14 +42,6 @@ struct ath10k_snoc_ce_irq {
u32 irq_line;
};
-struct ath10k_vreg_info {
- struct regulator *reg;
- const char *name;
- u32 load_ua;
- unsigned long settle_delay;
- bool required;
-};
-
struct ath10k_clk_info {
struct clk *handle;
const char *name;
@@ -64,6 +56,8 @@ enum ath10k_snoc_flags {
ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
};
+struct regulator_bulk_data;
+
struct ath10k_snoc {
struct platform_device *dev;
struct ath10k *ar;
@@ -75,7 +69,8 @@ struct ath10k_snoc {
struct ath10k_snoc_ce_irq ce_irqs[CE_COUNT_MAX];
struct ath10k_ce ce;
struct timer_list rx_post_retry;
- struct ath10k_vreg_info *vreg;
+ struct regulator_bulk_data *vregs;
+ size_t num_vregs;
struct ath10k_clk_info *clk;
struct ath10k_qmi *qmi;
unsigned long flags;
--
2.18.0
^ permalink raw reply related
* [PATCH 1/3] ath10k: snoc: skip regulator operations
From: Bjorn Andersson @ 2019-07-25 17:47 UTC (permalink / raw)
To: Kalle Valo, Govind Singh
Cc: David S. Miller, ath10k, linux-wireless, netdev, linux-kernel,
linux-arm-msm
In-Reply-To: <20190725174755.23432-1-bjorn.andersson@linaro.org>
The regulator operations is trying to set a voltage to a fixed value, by
giving some wiggle room. But some board designs specifies regulator
voltages outside this limited range. One such example is the Lenovo Yoga
C630, with vdd-3.3-ch0 in particular specified at 3.1V.
But consumers with fixed voltage requirements should just rely on the
board configuration to provide the power at the required level, so this
code should be removed.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
This patch is required for Lenovo Yoga C630 to succeed in power on ath10k, it
can be merged independently of the two following cleanup patches.
drivers/net/wireless/ath/ath10k/snoc.c | 27 ++++++--------------------
drivers/net/wireless/ath/ath10k/snoc.h | 2 --
2 files changed, 6 insertions(+), 23 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index fc15a0037f0e..3d93ab09a298 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -37,10 +37,10 @@ static char *const ce_name[] = {
};
static struct ath10k_vreg_info vreg_cfg[] = {
- {NULL, "vdd-0.8-cx-mx", 800000, 850000, 0, 0, false},
- {NULL, "vdd-1.8-xo", 1800000, 1850000, 0, 0, false},
- {NULL, "vdd-1.3-rfa", 1300000, 1350000, 0, 0, false},
- {NULL, "vdd-3.3-ch0", 3300000, 3350000, 0, 0, false},
+ {NULL, "vdd-0.8-cx-mx", 0, 0, false},
+ {NULL, "vdd-1.8-xo", 0, 0, false},
+ {NULL, "vdd-1.3-rfa", 0, 0, false},
+ {NULL, "vdd-3.3-ch0", 0, 0, false},
};
static struct ath10k_clk_info clk_cfg[] = {
@@ -1377,9 +1377,8 @@ static int ath10k_get_vreg_info(struct ath10k *ar, struct device *dev,
done:
ath10k_dbg(ar, ATH10K_DBG_SNOC,
- "snog vreg %s min_v %u max_v %u load_ua %u settle_delay %lu\n",
- vreg_info->name, vreg_info->min_v, vreg_info->max_v,
- vreg_info->load_ua, vreg_info->settle_delay);
+ "snog vreg %s load_ua %u settle_delay %lu\n",
+ vreg_info->name, vreg_info->load_ua, vreg_info->settle_delay);
return 0;
}
@@ -1420,15 +1419,6 @@ static int __ath10k_snoc_vreg_on(struct ath10k *ar,
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc regulator %s being enabled\n",
vreg_info->name);
- ret = regulator_set_voltage(vreg_info->reg, vreg_info->min_v,
- vreg_info->max_v);
- if (ret) {
- ath10k_err(ar,
- "failed to set regulator %s voltage-min: %d voltage-max: %d\n",
- vreg_info->name, vreg_info->min_v, vreg_info->max_v);
- return ret;
- }
-
if (vreg_info->load_ua) {
ret = regulator_set_load(vreg_info->reg, vreg_info->load_ua);
if (ret < 0) {
@@ -1453,7 +1443,6 @@ static int __ath10k_snoc_vreg_on(struct ath10k *ar,
err_enable:
regulator_set_load(vreg_info->reg, 0);
err_set_load:
- regulator_set_voltage(vreg_info->reg, 0, vreg_info->max_v);
return ret;
}
@@ -1475,10 +1464,6 @@ static int __ath10k_snoc_vreg_off(struct ath10k *ar,
if (ret < 0)
ath10k_err(ar, "failed to set load %s\n", vreg_info->name);
- ret = regulator_set_voltage(vreg_info->reg, 0, vreg_info->max_v);
- if (ret)
- ath10k_err(ar, "failed to set voltage %s\n", vreg_info->name);
-
return ret;
}
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index 9db823e46314..1bf7bd4ef2a3 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -45,8 +45,6 @@ struct ath10k_snoc_ce_irq {
struct ath10k_vreg_info {
struct regulator *reg;
const char *name;
- u32 min_v;
- u32 max_v;
u32 load_ua;
unsigned long settle_delay;
bool required;
--
2.18.0
^ permalink raw reply related
* [PATCH 3/3] ath10k: Use standard bulk clock API in snoc
From: Bjorn Andersson @ 2019-07-25 17:47 UTC (permalink / raw)
To: Kalle Valo, Govind Singh
Cc: David S. Miller, ath10k, linux-wireless, netdev, linux-kernel,
linux-arm-msm
In-Reply-To: <20190725174755.23432-1-bjorn.andersson@linaro.org>
No frequency is currently specified for the single clock defined in the
snoc driver, so the clock wrappers reimplements the standard bulk API
provided by the clock framework. Change to this.
The single clock defined is marked as optional so this version of the
get API is used, but might need to be reconsidered in the future.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
drivers/net/wireless/ath/ath10k/snoc.c | 125 ++++---------------------
drivers/net/wireless/ath/ath10k/snoc.h | 11 +--
2 files changed, 21 insertions(+), 115 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 1c9ff7e53e2f..80ce68c0f75e 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -43,8 +43,8 @@ static const char * const ath10k_regulators[] = {
"vdd-3.3-ch0",
};
-static struct ath10k_clk_info clk_cfg[] = {
- {NULL, "cxo_ref_clk_pin", 0, false},
+static const char * const ath10k_clocks[] = {
+ "cxo_ref_clk_pin",
};
static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state);
@@ -1346,104 +1346,6 @@ static void ath10k_snoc_release_resource(struct ath10k *ar)
ath10k_ce_free_pipe(ar, i);
}
-static int ath10k_get_clk_info(struct ath10k *ar, struct device *dev,
- struct ath10k_clk_info *clk_info)
-{
- struct clk *handle;
- int ret = 0;
-
- handle = devm_clk_get(dev, clk_info->name);
- if (IS_ERR(handle)) {
- ret = PTR_ERR(handle);
- if (clk_info->required) {
- ath10k_err(ar, "snoc clock %s isn't available: %d\n",
- clk_info->name, ret);
- return ret;
- }
- ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc ignoring clock %s: %d\n",
- clk_info->name,
- ret);
- return 0;
- }
-
- ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s freq %u\n",
- clk_info->name, clk_info->freq);
-
- clk_info->handle = handle;
-
- return ret;
-}
-
-static int ath10k_snoc_clk_init(struct ath10k *ar)
-{
- struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
- struct ath10k_clk_info *clk_info;
- int ret = 0;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
- clk_info = &ar_snoc->clk[i];
-
- if (!clk_info->handle)
- continue;
-
- ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s being enabled\n",
- clk_info->name);
-
- if (clk_info->freq) {
- ret = clk_set_rate(clk_info->handle, clk_info->freq);
-
- if (ret) {
- ath10k_err(ar, "failed to set clock %s freq %u\n",
- clk_info->name, clk_info->freq);
- goto err_clock_config;
- }
- }
-
- ret = clk_prepare_enable(clk_info->handle);
- if (ret) {
- ath10k_err(ar, "failed to enable clock %s\n",
- clk_info->name);
- goto err_clock_config;
- }
- }
-
- return 0;
-
-err_clock_config:
- for (i = i - 1; i >= 0; i--) {
- clk_info = &ar_snoc->clk[i];
-
- if (!clk_info->handle)
- continue;
-
- clk_disable_unprepare(clk_info->handle);
- }
-
- return ret;
-}
-
-static int ath10k_snoc_clk_deinit(struct ath10k *ar)
-{
- struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
- struct ath10k_clk_info *clk_info;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
- clk_info = &ar_snoc->clk[i];
-
- if (!clk_info->handle)
- continue;
-
- ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s being disabled\n",
- clk_info->name);
-
- clk_disable_unprepare(clk_info->handle);
- }
-
- return 0;
-}
-
static int ath10k_hw_power_on(struct ath10k *ar)
{
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
@@ -1455,7 +1357,7 @@ static int ath10k_hw_power_on(struct ath10k *ar)
if (ret)
return ret;
- ret = ath10k_snoc_clk_init(ar);
+ ret = clk_bulk_prepare_enable(ar_snoc->num_clks, ar_snoc->clks);
if (ret)
goto vreg_off;
@@ -1472,7 +1374,7 @@ static int ath10k_hw_power_off(struct ath10k *ar)
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power off\n");
- ath10k_snoc_clk_deinit(ar);
+ clk_bulk_disable_unprepare(ar_snoc->num_clks, ar_snoc->clks);
return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
}
@@ -1560,13 +1462,22 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
if (ret < 0)
goto err_free_irq;
- ar_snoc->clk = clk_cfg;
- for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
- ret = ath10k_get_clk_info(ar, dev, &ar_snoc->clk[i]);
- if (ret)
- goto err_free_irq;
+ ar_snoc->num_clks = ARRAY_SIZE(ath10k_clocks);
+ ar_snoc->clks = devm_kcalloc(&pdev->dev, ar_snoc->num_clks,
+ sizeof(*ar_snoc->clks), GFP_KERNEL);
+ if (!ar_snoc->clks) {
+ ret = -ENOMEM;
+ goto err_free_irq;
}
+ for (i = 0; i < ar_snoc->num_clks; i++)
+ ar_snoc->clks[i].id = ath10k_clocks[i];
+
+ ret = devm_clk_bulk_get_optional(&pdev->dev, ar_snoc->num_clks,
+ ar_snoc->clks);
+ if (ret)
+ goto err_free_irq;
+
ret = ath10k_hw_power_on(ar);
if (ret) {
ath10k_err(ar, "failed to power on device: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index 3965ddf66d74..d2449a3b4a8f 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -42,13 +42,6 @@ struct ath10k_snoc_ce_irq {
u32 irq_line;
};
-struct ath10k_clk_info {
- struct clk *handle;
- const char *name;
- u32 freq;
- bool required;
-};
-
enum ath10k_snoc_flags {
ATH10K_SNOC_FLAG_REGISTERED,
ATH10K_SNOC_FLAG_UNREGISTERING,
@@ -56,6 +49,7 @@ enum ath10k_snoc_flags {
ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
};
+struct clk_bulk_data;
struct regulator_bulk_data;
struct ath10k_snoc {
@@ -71,7 +65,8 @@ struct ath10k_snoc {
struct timer_list rx_post_retry;
struct regulator_bulk_data *vregs;
size_t num_vregs;
- struct ath10k_clk_info *clk;
+ struct clk_bulk_data *clks;
+ size_t num_clks;
struct ath10k_qmi *qmi;
unsigned long flags;
};
--
2.18.0
^ permalink raw reply related
* Re: [PATCH v2 0/2] mmc: core: Fix Marvell WiFi reset by adding SDIO API to replug card
From: Ulf Hansson @ 2019-07-25 13:28 UTC (permalink / raw)
To: Douglas Anderson
Cc: Kalle Valo, Adrian Hunter, Ganapathi Bhat, linux-wireless,
Andreas Fenkart, Brian Norris, Amitkumar Karwar,
open list:ARM/Rockchip SoC..., Wolfram Sang, Nishant Sarmukadam,
netdev, Avri Altman, linux-mmc@vger.kernel.org, David S. Miller,
Xinming Hu, Linux Kernel Mailing List, Thomas Gleixner,
Kate Stewart
In-Reply-To: <20190722193939.125578-1-dianders@chromium.org>
On Mon, 22 Jul 2019 at 21:41, Douglas Anderson <dianders@chromium.org> wrote:
>
> As talked about in the thread at:
>
> http://lkml.kernel.org/r/CAD=FV=X7P2F1k_zwHc0mbtfk55-rucTz_GoDH=PL6zWqKYcpuw@mail.gmail.com
>
> ...when the Marvell WiFi card tries to reset itself it kills
> Bluetooth. It was observed that we could re-init the card properly by
> unbinding / rebinding the host controller. It was also observed that
> in the downstream Chrome OS codebase the solution used was
> mmc_remove_host() / mmc_add_host(), which is similar to the solution
> in this series.
>
> So far I've only done testing of this series using the reset test
> source that can be simulated via sysfs. Specifically I ran this test:
>
> for i in $(seq 1000); do
> echo "LOOP $i --------"
> echo 1 > /sys/kernel/debug/mwifiex/mlan0/reset
>
> while true; do
> if ! ping -w15 -c1 "${GW}" >/dev/null 2>&1; then
> fail=$(( fail + 1 ))
> echo "Fail WiFi ${fail}"
> if [[ ${fail} == 3 ]]; then
> exit 1
> fi
> else
> fail=0
> break
> fi
> done
>
> hciconfig hci0 down
> sleep 1
> if ! hciconfig hci0 up; then
> echo "Fail BT"
> exit 1
> fi
> done
>
> I ran this several times and got several hundred iterations each
> before a failure. When I saw failures:
>
> * Once I saw a "Fail BT"; manually resetting the card again fixed it.
> I didn't give it time to see if it would have detected this
> automatically.
> * Once I saw the ping fail because (for some reason) my device only
> got an IPv6 address from my router and the IPv4 ping failed. I
> changed my script to use 'ping6' to see if that would help.
> * Once I saw the ping fail because the higher level network stack
> ("shill" in my case) seemed to crash. A few minutes later the
> system recovered itself automatically. https://crbug.com/984593 if
> you want more details.
> * Sometimes while I was testing I saw "Fail WiFi 1" indicating a
> transitory failure. Usually this was an association failure, but in
> one case I saw the device do "Firmware wakeup failed" after I
> triggered the reset. This caused the driver to trigger a re-reset
> of itself which eventually recovered things. This was good because
> it was an actual test of the normal reset flow (not the one
> triggered via sysfs).
>
> Changes in v2:
> - s/routnine/routine (Brian Norris, Matthias Kaehlcke).
> - s/contining/containing (Matthias Kaehlcke).
> - Add Matthias Reviewed-by tag.
> - Removed clear_bit() calls and old comment (Brian Norris).
> - Explicit CC of Andreas Fenkart.
> - Explicit CC of Brian Norris.
> - Add "Fixes" pointing at the commit Brian talked about.
> - Add Brian's Reviewed-by tag.
>
> Douglas Anderson (2):
> mmc: core: Add sdio_trigger_replug() API
> mwifiex: Make use of the new sdio_trigger_replug() API to reset
>
> drivers/mmc/core/core.c | 28 +++++++++++++++++++--
> drivers/mmc/core/sdio_io.c | 20 +++++++++++++++
> drivers/net/wireless/marvell/mwifiex/sdio.c | 16 +-----------
> include/linux/mmc/host.h | 15 ++++++++++-
> include/linux/mmc/sdio_func.h | 2 ++
> 5 files changed, 63 insertions(+), 18 deletions(-)
>
Doug, thanks for sending this!
As you know, I have been working on additional changes for SDIO
suspend/resume (still WIP and not ready for sharing) and this series
is related.
The thing is, that even during system suspend/resume, synchronizations
are needed between the different layers (mmc host, mmc core and
sdio-funcs), which is common to the problem you want to solve.
That said, I need to scratch my head a bit more before I can provide
you some feedback on $subject series. Moreover, it's vacation period
at my side so things are moving a bit slower. Please be patient.
Kind regards
Uffe
^ permalink raw reply
* [PATCH] rsi: fix for sdio reset card issue
From: Ganapathi Kondraju @ 2019-07-25 10:51 UTC (permalink / raw)
To: Kalle Valo
Cc: linux-wireless, rishikesh.basu, krishna.pedda, narasimha.a,
srinivas.chappidi, Ganapathi Kondraju
Issue: While removing and inserting the driver module, observed driver
loading is not successful.
Root cause: Card is not resetted completely without issuing cmd5.
Fix: Issued cmd5 properly.
Signed-off-by: Ganapathi Kondraju <ganapathirajukondraju@gmail.com>
---
drivers/net/wireless/rsi/rsi_91x_sdio.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index b42cd50..b3c7724 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -230,19 +230,16 @@ static void rsi_reset_card(struct sdio_func *pfunction)
rsi_dbg(ERR_ZONE, "%s: CMD0 failed : %d\n", __func__, err);
/* Issue CMD5, arg = 0 */
- if (!host->ocr_avail) {
- err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND, 0,
- (MMC_RSP_R4 | MMC_CMD_BCR), &resp);
- if (err)
- rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
- __func__, err);
-
- host->ocr_avail = resp;
- }
+ err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND, 0,
+ (MMC_RSP_R4 | MMC_CMD_BCR), &resp);
+ if (err)
+ rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
+ __func__, err);
+ card->ocr = resp;
/* Issue CMD5, arg = ocr. Wait till card is ready */
for (i = 0; i < 100; i++) {
err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND,
- host->ocr_avail,
+ card->ocr,
(MMC_RSP_R4 | MMC_CMD_BCR), &resp);
if (err) {
rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
--
2.5.5
^ permalink raw reply related
* pull-request: iwlwifi-fixes 2019-07-25
From: Johannes Berg @ 2019-07-25 9:32 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless
Hi Kalle,
So, I hope I finally have this figured out :-) I'm just replacing
Luca and using my usual workflow like with Dave, so ...
Anyway, LOTS of fixes accumulated, so I guess this is bigger than
usual, but a lot of these have been around for a long time and are
quite important, as many people are running into them.
Please pull and let me know if there's any problem.
Thanks,
johannes
The following changes since commit 5f9e832c137075045d15cd6899ab0505cfb2ca4b:
Linus 5.3-rc1 (2019-07-21 14:05:38 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes.git tags/iwlwifi-fixes-for-kvalo-2019-07-25
for you to fetch changes up to 2f0d5845da92517cbbef39bde712b3a7d04da1fe:
iwlwifi: mvm: fix a use-after-free bug in iwl_mvm_tx_tso_segment (2019-07-23 16:50:25 +0200)
----------------------------------------------------------------
We have a lot of fixes, most of them are also applicable to stable.
Notably:
* fix use-after-free issues
* fix DMA mapping API usage errors
* fix frame drop occurring due to reorder buffer handling in
RSS in certain conditions
* fix rate scale locking issues
* disable TX A-MSDU on older NICs as it causes problems and was
never supposed to be supported
* new PCI IDs
* GEO_TX_POWER_LIMIT API issue that many people were hitting
----------------------------------------------------------------
Colin Ian King (1):
iwlwifi: mvm: fix comparison of u32 variable with less than zero
Emmanuel Grumbach (8):
iwlwifi: mvm: prepare the ground for more RSS notifications
iwlwifi: mvm: add a new RSS sync notification for NSSN sync
iwlwiif: mvm: refactor iwl_mvm_notify_rx_queue
iwlwifi: mvm: add a loose synchronization of the NSSN across Rx queues
iwlwifi: mvm: fix frame drop from the reordering buffer
iwlwifi: don't unmap as page memory that was mapped as single
iwlwifi: mvm: fix an out-of-bound access
iwlwifi: mvm: fix a use-after-free bug in iwl_mvm_tx_tso_segment
Gregory Greenman (4):
iwlwifi: mvm: add a wrapper around rs_tx_status to handle locks
iwlwifi: mvm: send LQ command always ASYNC
iwlwifi: mvm: replace RS mutex with a spin_lock
iwlwifi: mvm: fix possible out-of-bounds read when accessing lq_info
Ihab Zhaika (1):
iwlwifi: add 3 new IDs for the 9000 series (iwl9260_2ac_160_cfg)
Johannes Berg (2):
iwlwifi: mvm: disable TX-AMSDU on older NICs
iwlwifi: fix locking in delayed GTK setting
Luca Coelho (2):
iwlwifi: mvm: don't send GEO_TX_POWER_LIMIT on version < 41
iwlwifi: mvm: fix version check for GEO_TX_POWER_LIMIT support
Mordechay Goodstein (1):
iwlwifi: mvm: avoid races in rate init and rate perform
Shahar S Matityahu (2):
iwlwifi: dbg_ini: move iwl_dbg_tlv_load_bin out of debug override ifdef
iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs ifdef
drivers/net/wireless/intel/iwlwifi/fw/api/rx.h | 3 +-
drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 4 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 29 +-
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 58 ++-
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 8 +-
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 4 +-
drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 539 ++++++++++++----------
drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 3 +-
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 185 ++++++--
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 6 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 12 +-
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 3 +-
drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 4 +-
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 3 +
drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 2 +
16 files changed, 523 insertions(+), 342 deletions(-)
^ permalink raw reply
* RE: [PATCH] rtw88: pci: Use general byte arrays as the elements of RX ring
From: David Laight @ 2019-07-25 9:21 UTC (permalink / raw)
To: 'Jian-Hong Pan', Yan-Hsuan Chuang, Kalle Valo,
David S . Miller
Cc: linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, linux@endlessm.com,
stable@vger.kernel.org
In-Reply-To: <20190725080925.6575-1-jian-hong@endlessm.com>
From: Jian-Hong Pan
> Sent: 25 July 2019 09:09
> Each skb as the element in RX ring was expected with sized buffer 8216
> (RTK_PCI_RX_BUF_SIZE) bytes. However, the skb buffer's true size is
> 16640 bytes for alignment after allocated, x86_64 for example. And, the
> difference will be enlarged 512 times (RTK_MAX_RX_DESC_NUM).
> To prevent that much wasted memory, this patch follows David's
> suggestion [1] and uses general buffer arrays, instead of skbs as the
> elements in RX ring.
...
> for (i = 0; i < len; i++) {
> - skb = dev_alloc_skb(buf_sz);
> - if (!skb) {
> + buf = devm_kzalloc(rtwdev->dev, buf_sz, GFP_ATOMIC);
You should do this allocation somewhere than can sleep.
So you don't need GFP_ATOMIC, making the allocate (and dma map)
much less likely to fail.
If they do fail using a smaller ring might be better than failing
completely.
I suspect that buf_sz gets rounded up somewhat.
Also you almost certainly want 'buf' to be cache-line aligned.
I don't think devm_kzalloc() guarantees that at all.
While allocating all 512 buffers in one block (just over 4MB)
is probably not a good idea, you may need to allocated (and dma map)
then in groups.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
^ permalink raw reply
* RE: [RFC PATCH] rtw88: use txpwr_lmt_cfg_pair struct, not arrays
From: Tony Chuang @ 2019-07-25 8:55 UTC (permalink / raw)
To: Kalle Valo; +Cc: Brian Norris, linux-wireless@vger.kernel.org
In-Reply-To: <87ef2ezmb7.fsf@kamboji.qca.qualcomm.com>
> Tony Chuang <yhchuang@realtek.com> writes:
>
> >> Brian Norris <briannorris@chromium.org> wrote:
> >>
> >> > We're just trusting that these tables are of the right dimensions, when
> >> > we could do better by just using the struct directly. Let's expose the
> >> > struct txpwr_lmt_cfg_pair instead.
> >> >
> >> > The table changes were made by using some Vim macros, so that should
> >> > help prevent any translation mistakes along the way.
> >> >
> >> > Remaining work: get the 'void *data' out of the generic struct
> >> > rtw_table; all of these tables really deserve to be their own data
> >> > structure, with proper type fields.
> >> >
> >> > Signed-off-by: Brian Norris <briannorris@chromium.org>
> >>
> >> To me this looks like a clear improvement and I'm inclined to apply it. Tony,
> >> what do you think?
> >
> > I think it indeed is better to use struct instead of arrays to access the table.
> > But what I am trying to do is to figure a way to write a proper struct for
> > radio_[ab] tables. Since the parsing logic is more complicated than others.
> >
> > Once I finished them, I will send a patch to change the tables.
>
> Are you saying that your patch will also clean up these txpwr tables and
> I should drop this patch? Or can I apply this?
>
You can apply this. And I can take care of the rest of them. :)
Thanks.
Tony
^ permalink raw reply
* [PATCH] rtw88: pci: Use general byte arrays as the elements of RX ring
From: Jian-Hong Pan @ 2019-07-25 8:09 UTC (permalink / raw)
To: Yan-Hsuan Chuang, Kalle Valo, David S . Miller, David Laight
Cc: linux-wireless, netdev, linux-kernel, linux, Jian-Hong Pan,
stable
Each skb as the element in RX ring was expected with sized buffer 8216
(RTK_PCI_RX_BUF_SIZE) bytes. However, the skb buffer's true size is
16640 bytes for alignment after allocated, x86_64 for example. And, the
difference will be enlarged 512 times (RTK_MAX_RX_DESC_NUM).
To prevent that much wasted memory, this patch follows David's
suggestion [1] and uses general buffer arrays, instead of skbs as the
elements in RX ring.
[1] https://www.spinics.net/lists/linux-wireless/msg187870.html
Signed-off-by: Jian-Hong Pan <jian-hong@endlessm.com>
Cc: <stable@vger.kernel.org>
---
drivers/net/wireless/realtek/rtw88/pci.c | 132 +++++++++++++----------
drivers/net/wireless/realtek/rtw88/pci.h | 2 +-
2 files changed, 75 insertions(+), 59 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index 23dd06afef3d..e953010f0179 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -111,25 +111,49 @@ static void rtw_pci_free_tx_ring(struct rtw_dev *rtwdev,
tx_ring->r.head = NULL;
}
+static struct rtw_pci_rx_buffer_desc *rtw_pci_get_rx_desc(
+ struct rtw_pci_rx_ring *rx_ring,
+ u32 idx)
+{
+ struct rtw_pci_rx_buffer_desc *buf_desc;
+ u32 desc_sz = rx_ring->r.desc_size;
+
+ buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head +
+ idx * desc_sz);
+ return buf_desc;
+}
+
+static dma_addr_t rtw_pci_get_rx_bufdma(struct rtw_pci_rx_ring *rx_ring,
+ u32 idx)
+{
+ struct rtw_pci_rx_buffer_desc *buf_desc;
+ dma_addr_t dma;
+
+ buf_desc = rtw_pci_get_rx_desc(rx_ring, idx);
+ dma = le32_to_cpu(buf_desc->dma);
+
+ return dma;
+}
+
static void rtw_pci_free_rx_ring(struct rtw_dev *rtwdev,
struct rtw_pci_rx_ring *rx_ring)
{
struct pci_dev *pdev = to_pci_dev(rtwdev->dev);
- struct sk_buff *skb;
+ u8 *buf;
dma_addr_t dma;
u8 *head = rx_ring->r.head;
int buf_sz = RTK_PCI_RX_BUF_SIZE;
int ring_sz = rx_ring->r.desc_size * rx_ring->r.len;
- int i;
+ u32 i;
for (i = 0; i < rx_ring->r.len; i++) {
- skb = rx_ring->buf[i];
- if (!skb)
+ buf = rx_ring->buf[i];
+ if (!buf)
continue;
- dma = *((dma_addr_t *)skb->cb);
- pci_unmap_single(pdev, dma, buf_sz, PCI_DMA_FROMDEVICE);
- dev_kfree_skb(skb);
+ dma = rtw_pci_get_rx_bufdma(rx_ring, i);
+ pci_unmap_single(pdev, dma, buf_sz, DMA_FROM_DEVICE);
+ devm_kfree(rtwdev->dev, buf);
rx_ring->buf[i] = NULL;
}
@@ -180,27 +204,24 @@ static int rtw_pci_init_tx_ring(struct rtw_dev *rtwdev,
return 0;
}
-static int rtw_pci_reset_rx_desc(struct rtw_dev *rtwdev, struct sk_buff *skb,
- struct rtw_pci_rx_ring *rx_ring,
- u32 idx, u32 desc_sz)
+static int rtw_pci_reset_rx_desc(struct rtw_dev *rtwdev, u8 *buf,
+ struct rtw_pci_rx_ring *rx_ring, u32 idx)
{
struct pci_dev *pdev = to_pci_dev(rtwdev->dev);
struct rtw_pci_rx_buffer_desc *buf_desc;
int buf_sz = RTK_PCI_RX_BUF_SIZE;
dma_addr_t dma;
- if (!skb)
+ if (!buf)
return -EINVAL;
- dma = pci_map_single(pdev, skb->data, buf_sz, PCI_DMA_FROMDEVICE);
+ dma = pci_map_single(pdev, buf, buf_sz, DMA_FROM_DEVICE);
if (pci_dma_mapping_error(pdev, dma))
return -EBUSY;
- *((dma_addr_t *)skb->cb) = dma;
- buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head +
- idx * desc_sz);
- memset(buf_desc, 0, sizeof(*buf_desc));
+ buf_desc = rtw_pci_get_rx_desc(rx_ring, idx);
buf_desc->buf_size = cpu_to_le16(RTK_PCI_RX_BUF_SIZE);
+ buf_desc->total_pkt_size = cpu_to_le16(0);
buf_desc->dma = cpu_to_le32(dma);
return 0;
@@ -208,7 +229,7 @@ static int rtw_pci_reset_rx_desc(struct rtw_dev *rtwdev, struct sk_buff *skb,
static void rtw_pci_sync_rx_desc_device(struct rtw_dev *rtwdev, dma_addr_t dma,
struct rtw_pci_rx_ring *rx_ring,
- u32 idx, u32 desc_sz)
+ u32 idx)
{
struct device *dev = rtwdev->dev;
struct rtw_pci_rx_buffer_desc *buf_desc;
@@ -216,10 +237,9 @@ static void rtw_pci_sync_rx_desc_device(struct rtw_dev *rtwdev, dma_addr_t dma,
dma_sync_single_for_device(dev, dma, buf_sz, DMA_FROM_DEVICE);
- buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head +
- idx * desc_sz);
- memset(buf_desc, 0, sizeof(*buf_desc));
+ buf_desc = rtw_pci_get_rx_desc(rx_ring, idx);
buf_desc->buf_size = cpu_to_le16(RTK_PCI_RX_BUF_SIZE);
+ buf_desc->total_pkt_size = cpu_to_le16(0);
buf_desc->dma = cpu_to_le32(dma);
}
@@ -228,12 +248,12 @@ static int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev,
u8 desc_size, u32 len)
{
struct pci_dev *pdev = to_pci_dev(rtwdev->dev);
- struct sk_buff *skb = NULL;
+ u8 *buf = NULL;
dma_addr_t dma;
u8 *head;
int ring_sz = desc_size * len;
int buf_sz = RTK_PCI_RX_BUF_SIZE;
- int i, allocated;
+ u32 i, allocated;
int ret = 0;
head = pci_zalloc_consistent(pdev, ring_sz, &dma);
@@ -242,41 +262,39 @@ static int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev,
return -ENOMEM;
}
rx_ring->r.head = head;
+ rx_ring->r.dma = dma;
+ rx_ring->r.len = len;
+ rx_ring->r.desc_size = desc_size;
+ rx_ring->r.wp = 0;
+ rx_ring->r.rp = 0;
for (i = 0; i < len; i++) {
- skb = dev_alloc_skb(buf_sz);
- if (!skb) {
+ buf = devm_kzalloc(rtwdev->dev, buf_sz, GFP_ATOMIC);
+ if (!buf) {
allocated = i;
ret = -ENOMEM;
goto err_out;
}
- memset(skb->data, 0, buf_sz);
- rx_ring->buf[i] = skb;
- ret = rtw_pci_reset_rx_desc(rtwdev, skb, rx_ring, i, desc_size);
+ rx_ring->buf[i] = buf;
+ ret = rtw_pci_reset_rx_desc(rtwdev, buf, rx_ring, i);
if (ret) {
allocated = i;
- dev_kfree_skb_any(skb);
+ devm_kfree(rtwdev->dev, buf);
goto err_out;
}
}
- rx_ring->r.dma = dma;
- rx_ring->r.len = len;
- rx_ring->r.desc_size = desc_size;
- rx_ring->r.wp = 0;
- rx_ring->r.rp = 0;
-
return 0;
err_out:
for (i = 0; i < allocated; i++) {
- skb = rx_ring->buf[i];
- if (!skb)
+ buf = rx_ring->buf[i];
+ if (!buf)
continue;
- dma = *((dma_addr_t *)skb->cb);
- pci_unmap_single(pdev, dma, buf_sz, PCI_DMA_FROMDEVICE);
- dev_kfree_skb_any(skb);
+ dma = rtw_pci_get_rx_bufdma(rx_ring, i);
+ pci_unmap_single(pdev, dma, buf_sz, DMA_FROM_DEVICE);
+ devm_kfree(rtwdev->dev, buf);
rx_ring->buf[i] = NULL;
}
pci_free_consistent(pdev, ring_sz, head, dma);
@@ -776,13 +794,12 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
struct rtw_pci_rx_ring *ring;
struct rtw_rx_pkt_stat pkt_stat;
struct ieee80211_rx_status rx_status;
- struct sk_buff *skb, *new;
+ struct sk_buff *skb;
u32 cur_wp, cur_rp, tmp;
u32 count;
u32 pkt_offset;
u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
- u32 buf_desc_sz = chip->rx_buf_desc_sz;
- u32 new_len;
+ u32 len;
u8 *rx_desc;
dma_addr_t dma;
@@ -799,11 +816,11 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
cur_rp = ring->r.rp;
while (count--) {
rtw_pci_dma_check(rtwdev, ring, cur_rp);
- skb = ring->buf[cur_rp];
- dma = *((dma_addr_t *)skb->cb);
+ /* buffer is already filled as rx_desc */
+ rx_desc = ring->buf[cur_rp];
+ dma = rtw_pci_get_rx_bufdma(ring, cur_rp);
dma_sync_single_for_cpu(rtwdev->dev, dma, RTK_PCI_RX_BUF_SIZE,
DMA_FROM_DEVICE);
- rx_desc = skb->data;
chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
/* offset from rx_desc to payload */
@@ -813,32 +830,31 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
/* allocate a new skb for this frame,
* discard the frame if none available
*/
- new_len = pkt_stat.pkt_len + pkt_offset;
- new = dev_alloc_skb(new_len);
- if (WARN_ONCE(!new, "rx routine starvation\n"))
+ len = pkt_stat.pkt_len + pkt_offset;
+ skb = dev_alloc_skb(len);
+ if (WARN_ONCE(!skb, "rx routine starvation\n"))
goto next_rp;
/* put the DMA data including rx_desc from phy to new skb */
- skb_put_data(new, skb->data, new_len);
+ skb_put_data(skb, rx_desc, len);
if (pkt_stat.is_c2h) {
/* pass rx_desc & offset for further operation */
- *((u32 *)new->cb) = pkt_offset;
- skb_queue_tail(&rtwdev->c2h_queue, new);
+ *((u32 *)skb->cb) = pkt_offset;
+ skb_queue_tail(&rtwdev->c2h_queue, skb);
ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work);
} else {
/* remove rx_desc */
- skb_pull(new, pkt_offset);
+ skb_pull(skb, pkt_offset);
- rtw_rx_stats(rtwdev, pkt_stat.vif, new);
- memcpy(new->cb, &rx_status, sizeof(rx_status));
- ieee80211_rx_irqsafe(rtwdev->hw, new);
+ rtw_rx_stats(rtwdev, pkt_stat.vif, skb);
+ memcpy(skb->cb, &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(rtwdev->hw, skb);
}
next_rp:
- /* new skb delivered to mac80211, re-enable original skb DMA */
- rtw_pci_sync_rx_desc_device(rtwdev, dma, ring, cur_rp,
- buf_desc_sz);
+ /* new skb delivered to mac80211, re-enable original buf DMA */
+ rtw_pci_sync_rx_desc_device(rtwdev, dma, ring, cur_rp);
/* host read next element in ring */
if (++cur_rp >= ring->r.len)
diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h
index 87824a4caba9..283685421a64 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.h
+++ b/drivers/net/wireless/realtek/rtw88/pci.h
@@ -174,7 +174,7 @@ struct rtw_pci_rx_buffer_desc {
struct rtw_pci_rx_ring {
struct rtw_pci_ring r;
- struct sk_buff *buf[RTK_MAX_RX_DESC_NUM];
+ u8 *buf[RTK_MAX_RX_DESC_NUM];
};
#define RX_TAG_MAX 8192
--
2.22.0
^ permalink raw reply related
* [PATCH] ath10k: Fix HOST capability QMI incompatibility
From: Bjorn Andersson @ 2019-07-25 6:31 UTC (permalink / raw)
To: Kalle Valo, David S. Miller, Rob Herring, Mark Rutland
Cc: linux-wireless, netdev, devicetree, linux-kernel, ath10k, stable
The introduction of 768ec4c012ac ("ath10k: update HOST capability QMI
message") served the purpose of supporting the new and extended HOST
capability QMI message.
But while the new message adds a slew of optional members it changes the
data type of the "daemon_support" member, which means that older
versions of the firmware will fail to decode the incoming request
message.
There is no way to detect this breakage from Linux and there's no way to
recover from sending the wrong message (i.e. we can't just try one
format and then fallback to the other), so a quirk is introduced in
DeviceTree to indicate to the driver that the firmware requires the 8bit
version of this message.
Cc: stable@vger.kernel.org
Fixes: 768ec4c012ac ("ath10k: update HOST capability qmi message")
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
.../bindings/net/wireless/qcom,ath10k.txt | 6 +++++
drivers/net/wireless/ath/ath10k/qmi.c | 13 ++++++++---
.../net/wireless/ath/ath10k/qmi_wlfw_v01.c | 22 +++++++++++++++++++
.../net/wireless/ath/ath10k/qmi_wlfw_v01.h | 1 +
drivers/net/wireless/ath/ath10k/snoc.c | 11 ++++++++++
drivers/net/wireless/ath/ath10k/snoc.h | 1 +
6 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
index ae661e65354e..f9499b20d840 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
@@ -81,6 +81,12 @@ Optional properties:
Definition: Name of external front end module used. Some valid FEM names
for example: "microsemi-lx5586", "sky85703-11"
and "sky85803" etc.
+- qcom,snoc-host-cap-8bit-quirk:
+ Usage: Optional
+ Value type: <empty>
+ Definition: Quirk specifying that the firmware expects the 8bit version
+ of the host capability QMI request
+
Example (to supply PCI based wifi block details):
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index 3b63b6257c43..545ac1f06997 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -581,22 +581,29 @@ static int ath10k_qmi_host_cap_send_sync(struct ath10k_qmi *qmi)
{
struct wlfw_host_cap_resp_msg_v01 resp = {};
struct wlfw_host_cap_req_msg_v01 req = {};
+ struct qmi_elem_info *req_ei;
struct ath10k *ar = qmi->ar;
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
struct qmi_txn txn;
int ret;
req.daemon_support_valid = 1;
req.daemon_support = 0;
- ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
- wlfw_host_cap_resp_msg_v01_ei, &resp);
+ ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_host_cap_resp_msg_v01_ei,
+ &resp);
if (ret < 0)
goto out;
+ if (test_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags))
+ req_ei = wlfw_host_cap_8bit_req_msg_v01_ei;
+ else
+ req_ei = wlfw_host_cap_req_msg_v01_ei;
+
ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
QMI_WLFW_HOST_CAP_REQ_V01,
WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN,
- wlfw_host_cap_req_msg_v01_ei, &req);
+ req_ei, &req);
if (ret < 0) {
qmi_txn_cancel(&txn);
ath10k_err(ar, "failed to send host capability request: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
index 1fe05c6218c3..86fcf4e1de5f 100644
--- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
+++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
@@ -1988,6 +1988,28 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = {
{}
};
+struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ daemon_support_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_host_cap_req_msg_v01,
+ daemon_support),
+ },
+ {}
+};
+
struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = {
{
.data_type = QMI_STRUCT,
diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
index bca1186e1560..4d107e1364a8 100644
--- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
+++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
@@ -575,6 +575,7 @@ struct wlfw_host_cap_req_msg_v01 {
#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 189
extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
+extern struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[];
struct wlfw_host_cap_resp_msg_v01 {
struct qmi_response_type_v01 resp;
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index b491361e6ed4..fc15a0037f0e 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1261,6 +1261,15 @@ static int ath10k_snoc_resource_init(struct ath10k *ar)
return ret;
}
+static void ath10k_snoc_quirks_init(struct ath10k *ar)
+{
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+ struct device *dev = &ar_snoc->dev->dev;
+
+ if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk"))
+ set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags);
+}
+
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)
{
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
@@ -1678,6 +1687,8 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
ar->ce_priv = &ar_snoc->ce;
msa_size = drv_data->msa_size;
+ ath10k_snoc_quirks_init(ar);
+
ret = ath10k_snoc_resource_init(ar);
if (ret) {
ath10k_warn(ar, "failed to initialize resource: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index d62f53501fbb..9db823e46314 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -63,6 +63,7 @@ enum ath10k_snoc_flags {
ATH10K_SNOC_FLAG_REGISTERED,
ATH10K_SNOC_FLAG_UNREGISTERING,
ATH10K_SNOC_FLAG_RECOVERY,
+ ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
};
struct ath10k_snoc {
--
2.18.0
^ permalink raw reply related
* Re: [RFC PATCH] rtw88: use txpwr_lmt_cfg_pair struct, not arrays
From: Kalle Valo @ 2019-07-25 5:59 UTC (permalink / raw)
To: Tony Chuang; +Cc: Brian Norris, linux-wireless@vger.kernel.org
In-Reply-To: <F7CD281DE3E379468C6D07993EA72F84D187DDAE@RTITMBSVM04.realtek.com.tw>
Tony Chuang <yhchuang@realtek.com> writes:
>> Brian Norris <briannorris@chromium.org> wrote:
>>
>> > We're just trusting that these tables are of the right dimensions, when
>> > we could do better by just using the struct directly. Let's expose the
>> > struct txpwr_lmt_cfg_pair instead.
>> >
>> > The table changes were made by using some Vim macros, so that should
>> > help prevent any translation mistakes along the way.
>> >
>> > Remaining work: get the 'void *data' out of the generic struct
>> > rtw_table; all of these tables really deserve to be their own data
>> > structure, with proper type fields.
>> >
>> > Signed-off-by: Brian Norris <briannorris@chromium.org>
>>
>> To me this looks like a clear improvement and I'm inclined to apply it. Tony,
>> what do you think?
>
> I think it indeed is better to use struct instead of arrays to access the table.
> But what I am trying to do is to figure a way to write a proper struct for
> radio_[ab] tables. Since the parsing logic is more complicated than others.
>
> Once I finished them, I will send a patch to change the tables.
Are you saying that your patch will also clean up these txpwr tables and
I should drop this patch? Or can I apply this?
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v2 2/2] mwifiex: Make use of the new sdio_trigger_replug() API to reset
From: Kalle Valo @ 2019-07-25 5:56 UTC (permalink / raw)
To: Doug Anderson
Cc: Ulf Hansson, Adrian Hunter, Ganapathi Bhat, linux-wireless,
Andreas Fenkart, Brian Norris, Amitkumar Karwar,
open list:ARM/Rockchip SoC..., Wolfram Sang, Nishant Sarmukadam,
netdev, Avri Altman, Linux MMC List, David Miller, Xinming Hu,
LKML
In-Reply-To: <CAD=FV=WAsrBV9PzUz1qPzQru+AkOYZ5hsaWdhNYRTNqUfDeOmQ@mail.gmail.com>
Doug Anderson <dianders@chromium.org> writes:
> Hi,
>
> On Wed, Jul 24, 2019 at 4:35 AM Kalle Valo <kvalo@codeaurora.org> wrote:
>>
>> Douglas Anderson <dianders@chromium.org> wrote:
>>
>> > As described in the patch ("mmc: core: Add sdio_trigger_replug()
>> > API"), the current mwifiex_sdio_card_reset() is broken in the cases
>> > where we're running Bluetooth on a second SDIO func on the same card
>> > as WiFi. The problem goes away if we just use the
>> > sdio_trigger_replug() API call.
>> >
>> > NOTE: Even though with this new solution there is less of a reason to
>> > do our work from a workqueue (the unplug / plug mechanism we're using
>> > is possible for a human to perform at any time so the stack is
>> > supposed to handle it without it needing to be called from a special
>> > context), we still need a workqueue because the Marvell reset function
>> > could called from a context where sleeping is invalid and thus we
>> > can't claim the host. One example is Marvell's wakeup_timer_fn().
>> >
>> > Cc: Andreas Fenkart <afenkart@gmail.com>
>> > Cc: Brian Norris <briannorris@chromium.org>
>> > Fixes: b4336a282db8 ("mwifiex: sdio: reset adapter using mmc_hw_reset")
>> > Signed-off-by: Douglas Anderson <dianders@chromium.org>
>> > Reviewed-by: Brian Norris <briannorris@chromium.org>
>>
>> I assume this is going via some other tree so I'm dropping this from my
>> queue. If I should apply this please resend once the dependency is in
>> wireless-drivers-next.
>>
>> Patch set to Not Applicable.
>
> Thanks. For now I'll assume that Ulf will pick it up if/when he is
> happy with patch #1 in this series. Would you be willing to provide
> your Ack on this patch to make it clear to Ulf you're OK with that?
Sure, I was planning to do that already in my previous email but forgot.
Acked-by: Kalle Valo <kvalo@codeaurora.org>
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH for v5.2] iwlwifi: mvm: disable TX-AMSDU on older NICs
From: Kalle Valo @ 2019-07-25 5:55 UTC (permalink / raw)
To: Brian Norris
Cc: Luca Coelho, David S. Miller, linux-wireless, Grumbach, Emmanuel,
johannes.hirte, steven, Johannes Berg
In-Reply-To: <CA+ASDXPjLW+Zrf-uruCLMFGGDaJd=xYWt4tb=T_0HKP=ZnHbTQ@mail.gmail.com>
Brian Norris <briannorris@chromium.org> writes:
> On Wed, Jul 3, 2019 at 4:46 AM Kalle Valo <kvalo@codeaurora.org> wrote:
>> Luca Coelho <luca@coelho.fi> writes:
>> > Hi Dave,
>> >
>> > This is an important fix for a bug that has been reported by several
>> > users in bugzilla (and elsewhere). It fixes FW crashes that disrupt
>> > throughput and connectivity in general in very popular devices (Intel's
>> > WiFi 7000 and 8000 series).
>> >
>> > I know it's a bit late for v5.2, but if possible, it would be great to
>> > take this. Kalle is on vacation, so we agreed that I would send it
>> > directly to you.
>>
>> Acked-by: Kalle Valo <kvalo@codeaurora.org>
>
> 5.2 has come and gone, and I believe Kalle has awoken from vacation.
Yeah, I have sort of crawled out of my cave ;)
> Can we get this for 5.3?
Ah, this slipped through the cracks. Thanks for pointing it out. I now
took this patch from Luca and assigned to myself in patchwork and I'll
queue this for v5.3.
https://patchwork.kernel.org/patch/11029027/
--
Kalle Valo
^ permalink raw reply
* [PATCH v2 5/5] rtw88: add BT co-existence support
From: yhchuang @ 2019-07-25 2:53 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, sgruszka, briannorris
In-Reply-To: <1564023211-3138-1-git-send-email-yhchuang@realtek.com>
From: Yan-Hsuan Chuang <yhchuang@realtek.com>
Both RTL8822BE/RTL8822CE are WiFi + BT combo chips. Since
WiFi and BT use 2.4GHz to transmit, it is important to
make sure they run concurrently without interfering each
other. To achieve this, WiFi driver requires a mechanism
to collaborate with BT, whether they share the antenna(s)
or not.
The final decision made by the co-existence mechanism is
to choose a proper strategy, or called "tdma/table", and
inform either firmware or hardware of the strategy.
To choose a strategy, co-existence mechanism needs to
have enough information from WiFi and BT.
BT information is provided through firmware C2H.
The contents describe the current status of BT, such as
if BT is connected or is idle, or the profile that is
being used.
WiFi information can be provided by WiFi itself. The WiFi
driver will call various of "notify" functions each time
the state of WiFi changed, such as WiFi is going to switch
channel or is connected. Also WiFi driver can know if it
shares antenna with BT by reading efuse content. Antenna
configuration of the module will finally get a different
strategy.
Upon receiving any information from WiFi or BT, the WiFi
driver will run the co-existence mechanism immediately.
It will set the RF antenna configuration according to the
strategy through the TDMA H2C to firmware and a hardware
table. Based on the tdma/table, WiFi + BT should work with
each other, and having a better user experience.
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---
v1 -> v2
no change
drivers/net/wireless/realtek/rtw88/Makefile | 1 +
drivers/net/wireless/realtek/rtw88/coex.c | 2462 +++++++++++++++++++++++++
drivers/net/wireless/realtek/rtw88/coex.h | 363 ++++
drivers/net/wireless/realtek/rtw88/fw.c | 106 ++
drivers/net/wireless/realtek/rtw88/fw.h | 71 +
drivers/net/wireless/realtek/rtw88/mac80211.c | 19 +
drivers/net/wireless/realtek/rtw88/main.c | 45 +-
drivers/net/wireless/realtek/rtw88/main.h | 233 +++
drivers/net/wireless/realtek/rtw88/ps.c | 9 +
drivers/net/wireless/realtek/rtw88/reg.h | 62 +
drivers/net/wireless/realtek/rtw88/rtw8822b.c | 460 ++++-
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 355 +++-
12 files changed, 4158 insertions(+), 28 deletions(-)
create mode 100644 drivers/net/wireless/realtek/rtw88/coex.c
create mode 100644 drivers/net/wireless/realtek/rtw88/coex.h
diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index e0bfefd..77edee2 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -9,6 +9,7 @@ rtw88-y += main.o \
rx.o \
mac.o \
phy.o \
+ coex.o \
efuse.o \
fw.o \
ps.o \
diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c
new file mode 100644
index 0000000..cd85016
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/coex.c
@@ -0,0 +1,2462 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#include "main.h"
+#include "coex.h"
+#include "fw.h"
+#include "ps.h"
+#include "debug.h"
+#include "reg.h"
+
+static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
+ u8 rssi, u8 rssi_thresh)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 tol = chip->rssi_tolerance;
+ u8 next_state;
+
+ if (pre_state == COEX_RSSI_STATE_LOW ||
+ pre_state == COEX_RSSI_STATE_STAY_LOW) {
+ if (rssi >= (rssi_thresh + tol))
+ next_state = COEX_RSSI_STATE_HIGH;
+ else
+ next_state = COEX_RSSI_STATE_STAY_LOW;
+ } else {
+ if (rssi < rssi_thresh)
+ next_state = COEX_RSSI_STATE_LOW;
+ else
+ next_state = COEX_RSSI_STATE_STAY_HIGH;
+ }
+
+ return next_state;
+}
+
+static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
+ bool tx_limit_en, bool ampdu_limit_en)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ bool wifi_under_b_mode = false;
+
+ if (!chip->scbd_support)
+ return;
+
+ /* force max tx retry limit = 8 */
+ if (coex_stat->wl_tx_limit_en == tx_limit_en &&
+ coex_stat->wl_ampdu_limit_en == ampdu_limit_en)
+ return;
+
+ if (!coex_stat->wl_tx_limit_en) {
+ coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC);
+ coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH);
+ coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT);
+ }
+
+ if (!coex_stat->wl_ampdu_limit_en)
+ coex_stat->ampdu_max_time =
+ rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1);
+
+ coex_stat->wl_tx_limit_en = tx_limit_en;
+ coex_stat->wl_ampdu_limit_en = ampdu_limit_en;
+
+ if (tx_limit_en) {
+ /* set BT polluted packet on for tx rate adaptive,
+ * not including tx retry broken by PTA
+ */
+ rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
+
+ /* set queue life time to avoid can't reach tx retry limit
+ * if tx is always broken by GNT_BT
+ */
+ rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
+ rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);
+
+ /* auto rate fallback step within 8 retries */
+ if (wifi_under_b_mode) {
+ rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
+ rtw_write32(rtwdev, REG_DARFRCH, 0x1010101);
+ } else {
+ rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
+ rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
+ }
+ } else {
+ rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
+ rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);
+
+ rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit);
+ rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc);
+ rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch);
+ }
+
+ if (ampdu_limit_en)
+ rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20);
+ else
+ rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1,
+ coex_stat->ampdu_max_time);
+}
+
+static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ bool tx_limit = false;
+ bool tx_agg_ctrl = false;
+
+ if (coex->under_5g ||
+ coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
+ /* no need to limit tx */
+ } else {
+ tx_limit = true;
+ if (coex_stat->bt_hid_exist || coex_stat->bt_hfp_exist ||
+ coex_stat->bt_hid_pair_num > 0)
+ tx_agg_ctrl = true;
+ }
+
+ rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);
+}
+
+static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ u8 para[6] = {0};
+
+ if (coex->stop_dm)
+ return;
+
+ para[0] = COEX_H2C69_WL_LEAKAP;
+
+ if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) {
+ para[1] = PARA1_H2C69_DIS_5MS; /* disable 5ms extend */
+ rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
+ coex_stat->wl_slot_extend = false;
+ coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
+ return;
+ }
+
+ if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl &&
+ !coex_stat->wl_cck_lock_ever) {
+ if (coex_stat->wl_fw_dbg_info[7] <= 5)
+ coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++;
+ else
+ coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
+
+ if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) {
+ para[1] = 0x1; /* disable 5ms extend */
+ rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
+ coex_stat->wl_slot_extend = false;
+ coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
+ }
+ } else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) {
+ para[1] = 0x0; /* enable 5ms extend */
+ rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
+ coex_stat->wl_slot_extend = true;
+ }
+}
+
+static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+
+ /* TODO: wait for rx_rate_change_notify implement */
+ coex_stat->wl_cck_lock = false;
+ coex_stat->wl_cck_lock_pre = false;
+ coex_stat->wl_cck_lock_ever = false;
+}
+
+static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u32 cnt_cck;
+
+ /* wifi noisy environment identification */
+ cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;
+
+ if (!coex_stat->wl_gl_busy) {
+ if (cnt_cck > 250) {
+ if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)
+ coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;
+
+ if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) {
+ coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
+ coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
+ }
+ } else if (cnt_cck < 100) {
+ if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5)
+ coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++;
+
+ if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) {
+ coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
+ coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
+ }
+ } else {
+ if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5)
+ coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++;
+
+ if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) {
+ coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
+ coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
+ }
+ }
+
+ if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5)
+ coex_stat->wl_noisy_level = 2;
+ else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5)
+ coex_stat->wl_noisy_level = 1;
+ else
+ coex_stat->wl_noisy_level = 0;
+ }
+}
+
+static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
+ u8 data)
+{
+ u32 addr;
+
+ addr = REG_BT_COEX_TABLE_H + (bitmap / 8);
+ bitmap = bitmap % 8;
+
+ rtw_write8_mask(rtwdev, addr, BIT(bitmap), data);
+}
+
+void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ u16 val = 0x2;
+
+ if (!chip->scbd_support)
+ return;
+
+ val |= coex_stat->score_board;
+
+ /* for 8822b, scbd[10] is CQDDR on
+ * for 8822c, scbd[10] is no fix 2M
+ */
+ if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) {
+ if (set)
+ val &= ~COEX_SCBD_FIX2M;
+ else
+ val |= COEX_SCBD_FIX2M;
+ } else {
+ if (set)
+ val |= bitpos;
+ else
+ val &= ~bitpos;
+ }
+
+ if (val != coex_stat->score_board) {
+ coex_stat->score_board = val;
+ val |= BIT_BT_INT_EN;
+ rtw_write16(rtwdev, REG_WIFI_BT_INFO, val);
+ }
+}
+
+static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ if (!chip->scbd_support)
+ return 0;
+
+ return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN);
+}
+
+static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_rfe *coex_rfe = &coex->rfe;
+ u8 cnt = 0;
+ u32 wait_cnt;
+ bool btk, wlk;
+
+ if (coex_rfe->wlg_at_btg && chip->scbd_support &&
+ coex_stat->bt_iqk_state != 0xff) {
+ wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;
+ do {
+ /* BT RFK */
+ btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK);
+
+ /* WL RFK */
+ wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK);
+
+ if (!btk && !wlk)
+ break;
+
+ mdelay(COEX_MIN_DELAY);
+ } while (++cnt < wait_cnt);
+
+ if (cnt >= wait_cnt)
+ coex_stat->bt_iqk_state = 0xff;
+ }
+}
+
+static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+
+ if (coex_stat->bt_disabled)
+ return;
+
+ rtw_fw_query_bt_info(rtwdev);
+}
+
+static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ bool bt_disabled = false;
+ u16 score_board;
+
+ if (chip->scbd_support) {
+ score_board = rtw_coex_read_scbd(rtwdev);
+ bt_disabled = !(score_board & COEX_SCBD_ONOFF);
+ }
+
+ if (coex_stat->bt_disabled != bt_disabled) {
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: BT state changed (%d) -> (%d)\n",
+ coex_stat->bt_disabled, bt_disabled);
+
+ coex_stat->bt_disabled = bt_disabled;
+ coex_stat->bt_ble_scan_type = 0;
+ coex_dm->cur_bt_lna_lvl = 0;
+ }
+
+ if (!coex_stat->bt_disabled) {
+ coex_stat->bt_reenable = true;
+ ieee80211_queue_delayed_work(rtwdev->hw,
+ &coex->bt_reenable_work, 15 * HZ);
+ } else {
+ coex_stat->bt_mailbox_reply = false;
+ coex_stat->bt_reenable = false;
+ }
+}
+
+static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_traffic_stats *stats = &rtwdev->stats;
+ bool is_5G = false;
+ bool scan = false, link = false;
+ int i;
+ u8 rssi_state;
+ u8 rssi_step;
+ u8 rssi;
+
+ scan = rtw_flag_check(rtwdev, RTW_FLAG_SCANNING);
+ coex_stat->wl_connected = !!rtwdev->sta_cnt;
+ coex_stat->wl_gl_busy = rtw_flag_check(rtwdev, RTW_FLAG_BUSY_TRAFFIC);
+
+ if (stats->tx_throughput > stats->rx_throughput)
+ coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;
+ else
+ coex_stat->wl_tput_dir = COEX_WL_TPUT_RX;
+
+ if (scan || link || reason == COEX_RSN_2GCONSTART ||
+ reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND)
+ coex_stat->wl_linkscan_proc = true;
+ else
+ coex_stat->wl_linkscan_proc = false;
+
+ rtw_coex_wl_noisy_detect(rtwdev);
+
+ for (i = 0; i < 4; i++) {
+ rssi_state = coex_dm->wl_rssi_state[i];
+ rssi_step = chip->wl_rssi_step[i];
+ rssi = rtwdev->dm_info.min_rssi;
+ rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
+ rssi, rssi_step);
+ coex_dm->wl_rssi_state[i] = rssi_state;
+ }
+
+ switch (reason) {
+ case COEX_RSN_5GSCANSTART:
+ case COEX_RSN_5GSWITCHBAND:
+ case COEX_RSN_5GCONSTART:
+
+ is_5G = true;
+ break;
+ case COEX_RSN_2GSCANSTART:
+ case COEX_RSN_2GSWITCHBAND:
+ case COEX_RSN_2GCONSTART:
+
+ is_5G = false;
+ break;
+ default:
+ if (rtwdev->hal.current_band_type == RTW_BAND_5G)
+ is_5G = true;
+ else
+ is_5G = false;
+ break;
+ }
+
+ coex->under_5g = is_5G;
+}
+
+static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp)
+{
+ struct rtw_c2h_cmd *c2h;
+ u32 pkt_offset;
+
+ pkt_offset = *((u32 *)resp->cb);
+ c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset);
+
+ return c2h->payload;
+}
+
+void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ u8 *payload = get_payload_from_coex_resp(skb);
+
+ if (payload[0] != COEX_RESP_ACK_BY_WL_FW)
+ return;
+
+ skb_queue_tail(&coex->queue, skb);
+ wake_up(&coex->wait);
+}
+
+static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
+ struct rtw_coex_info_req *req)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct sk_buff *skb_resp = NULL;
+
+ mutex_lock(&coex->mutex);
+
+ rtw_fw_query_bt_mp_info(rtwdev, req);
+
+ if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),
+ COEX_REQUEST_TIMEOUT)) {
+ rtw_err(rtwdev, "coex request time out\n");
+ goto out;
+ }
+
+ skb_resp = skb_dequeue(&coex->queue);
+ if (!skb_resp) {
+ rtw_err(rtwdev, "failed to get coex info response\n");
+ goto out;
+ }
+
+out:
+ mutex_unlock(&coex->mutex);
+ return skb_resp;
+}
+
+static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)
+{
+ struct rtw_coex_info_req req = {0};
+ struct sk_buff *skb;
+ u8 *payload;
+ bool ret = false;
+
+ req.op_code = BT_MP_INFO_OP_SCAN_TYPE;
+ skb = rtw_coex_info_request(rtwdev, &req);
+ if (!skb)
+ goto out;
+
+ payload = get_payload_from_coex_resp(skb);
+ *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);
+ ret = true;
+
+out:
+ return ret;
+}
+
+static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,
+ u8 lna_constrain_level)
+{
+ struct rtw_coex_info_req req = {0};
+ struct sk_buff *skb;
+ bool ret = false;
+
+ req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;
+ req.para1 = lna_constrain_level;
+ skb = rtw_coex_info_request(rtwdev, &req);
+ if (!skb)
+ goto out;
+
+ ret = true;
+
+out:
+ return ret;
+}
+
+static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 i;
+ u8 rssi_state;
+ u8 rssi_step;
+ u8 rssi;
+
+ /* update wl/bt rssi by btinfo */
+ for (i = 0; i < COEX_RSSI_STEP; i++) {
+ rssi_state = coex_dm->bt_rssi_state[i];
+ rssi_step = chip->bt_rssi_step[i];
+ rssi = coex_stat->bt_rssi;
+ rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
+ rssi, rssi_step);
+ coex_dm->bt_rssi_state[i] = rssi_state;
+ }
+
+ for (i = 0; i < COEX_RSSI_STEP; i++) {
+ rssi_state = coex_dm->wl_rssi_state[i];
+ rssi_step = chip->wl_rssi_step[i];
+ rssi = rtwdev->dm_info.min_rssi;
+ rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
+ rssi, rssi_step);
+ coex_dm->wl_rssi_state[i] = rssi_state;
+ }
+
+ if (coex_stat->bt_ble_scan_en &&
+ coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {
+ u8 scan_type;
+
+ if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) {
+ coex_stat->bt_ble_scan_type = scan_type;
+ if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1)
+ coex_stat->bt_init_scan = true;
+ else
+ coex_stat->bt_init_scan = false;
+ }
+ }
+
+ coex_stat->bt_profile_num = 0;
+
+ /* set link exist status */
+ if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
+ coex_stat->bt_link_exist = false;
+ coex_stat->bt_pan_exist = false;
+ coex_stat->bt_a2dp_exist = false;
+ coex_stat->bt_hid_exist = false;
+ coex_stat->bt_hfp_exist = false;
+ } else {
+ /* connection exists */
+ coex_stat->bt_link_exist = true;
+ if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) {
+ coex_stat->bt_pan_exist = true;
+ coex_stat->bt_profile_num++;
+ } else {
+ coex_stat->bt_pan_exist = false;
+ }
+
+ if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) {
+ coex_stat->bt_a2dp_exist = true;
+ coex_stat->bt_profile_num++;
+ } else {
+ coex_stat->bt_a2dp_exist = false;
+ }
+
+ if (coex_stat->bt_info_lb2 & COEX_INFO_HID) {
+ coex_stat->bt_hid_exist = true;
+ coex_stat->bt_profile_num++;
+ } else {
+ coex_stat->bt_hid_exist = false;
+ }
+
+ if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) {
+ coex_stat->bt_hfp_exist = true;
+ coex_stat->bt_profile_num++;
+ } else {
+ coex_stat->bt_hfp_exist = false;
+ }
+ }
+
+ if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) {
+ coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;
+ } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
+ coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;
+ } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {
+ coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;
+ } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||
+ (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) {
+ if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY)
+ coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY;
+ else
+ coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY;
+ } else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) {
+ coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY;
+ } else {
+ coex_dm->bt_status = COEX_BTSTATUS_MAX;
+ }
+
+ coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: bt status(%d)\n", coex_dm->bt_status);
+}
+
+static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ u8 link = 0;
+ u8 center_chan = 0;
+ u8 bw;
+ int i;
+
+ bw = rtwdev->hal.current_band_width;
+
+ if (type != COEX_MEDIA_DISCONNECT)
+ center_chan = rtwdev->hal.current_channel;
+
+ if (center_chan == 0 || (efuse->share_ant && center_chan <= 14)) {
+ link = 0;
+ } else if (center_chan <= 14) {
+ link = 0x1;
+
+ if (bw == RTW_CHANNEL_WIDTH_40)
+ bw = chip->bt_afh_span_bw40;
+ else
+ bw = chip->bt_afh_span_bw20;
+ } else if (chip->afh_5g_num > 1) {
+ for (i = 0; i < chip->afh_5g_num; i++) {
+ if (center_chan == chip->afh_5g[i].wl_5g_ch) {
+ link = 0x3;
+ center_chan = chip->afh_5g[i].bt_skip_ch;
+ bw = chip->afh_5g[i].bt_skip_span;
+ break;
+ }
+ }
+ }
+
+ coex_dm->wl_ch_info[0] = link;
+ coex_dm->wl_ch_info[1] = center_chan;
+ coex_dm->wl_ch_info[2] = bw;
+
+ rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);
+}
+
+static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+
+ if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl)
+ return;
+
+ coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl;
+
+ rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl);
+}
+
+static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+
+ if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl)
+ return;
+
+ coex_dm->cur_bt_lna_lvl = bt_lna_lvl;
+
+ /* notify BT rx gain table changed */
+ if (bt_lna_lvl < 7) {
+ rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl);
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true);
+ } else {
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);
+ }
+}
+
+static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
+ struct coex_rf_para para)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ u8 offset = 0;
+
+ if (coex->freerun && coex_stat->wl_noisy_level <= 1)
+ offset = 3;
+
+ rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);
+ rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset);
+ rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en);
+ rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);
+}
+
+static u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
+{
+ u32 val;
+
+ if (!ltecoex_read_reg(rtwdev, addr, &val)) {
+ rtw_err(rtwdev, "failed to read indirect register\n");
+ return 0;
+ }
+
+ return val;
+}
+
+void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
+ u32 mask, u32 val)
+{
+ u32 shift = __ffs(mask);
+ u32 tmp;
+
+ tmp = rtw_coex_read_indirect_reg(rtwdev, addr);
+ tmp = (tmp & (~mask)) | ((val << shift) & mask);
+
+ if (!ltecoex_reg_write(rtwdev, addr, tmp))
+ rtw_err(rtwdev, "failed to write indirect register\n");
+}
+
+static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
+{
+ if (wifi_control)
+ rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
+ else
+ rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
+}
+
+static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
+{
+ rtw_coex_write_indirect_reg(rtwdev, 0x38, 0xc000, state);
+ rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0c00, state);
+}
+
+static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
+{
+ rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x3000, state);
+ rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0300, state);
+}
+
+static void rtw_coex_set_table(struct rtw_dev *rtwdev, u32 table0, u32 table1)
+{
+#define DEF_BRK_TABLE_VAL 0xf0ffffff
+ rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);
+ rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);
+ rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);
+}
+
+static void rtw_coex_table(struct rtw_dev *rtwdev, u8 type)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+
+ coex_dm->cur_table = type;
+
+ if (efuse->share_ant) {
+ if (type < chip->table_sant_num)
+ rtw_coex_set_table(rtwdev,
+ chip->table_sant[type].bt,
+ chip->table_sant[type].wl);
+ } else {
+ type = type - 100;
+ if (type < chip->table_nsant_num)
+ rtw_coex_set_table(rtwdev,
+ chip->table_nsant[type].bt,
+ chip->table_nsant[type].wl);
+ }
+}
+
+static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+
+ if (coex->stop_dm)
+ return;
+
+ rtw_fw_bt_ignore_wlan_action(rtwdev, enable);
+}
+
+static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
+ u8 lps_val, u8 rpwm_val)
+{
+ struct rtw_lps_conf *lps_conf = &rtwdev->lps_conf;
+ struct rtw_vif *rtwvif;
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ u8 lps_mode = 0x0;
+
+ lps_mode = rtwdev->lps_conf.mode;
+
+ switch (ps_type) {
+ case COEX_PS_WIFI_NATIVE:
+ /* recover to original 32k low power setting */
+ coex_stat->wl_force_lps_ctrl = false;
+
+ rtwvif = lps_conf->rtwvif;
+ if (rtwvif && rtw_in_lps(rtwdev))
+ rtw_leave_lps(rtwdev, rtwvif);
+ break;
+ case COEX_PS_LPS_OFF:
+ coex_stat->wl_force_lps_ctrl = true;
+ if (lps_mode)
+ rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0);
+
+ rtwvif = lps_conf->rtwvif;
+ if (rtwvif && rtw_in_lps(rtwdev))
+ rtw_leave_lps(rtwdev, rtwvif);
+ break;
+ default:
+ break;
+ }
+}
+
+static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
+ u8 byte3, u8 byte4, u8 byte5)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 ps_type = COEX_PS_WIFI_NATIVE;
+ bool ap_enable = false;
+
+ if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {
+ byte1 &= ~BIT(4);
+ byte1 |= BIT(5);
+
+ byte5 |= BIT(5);
+ byte5 &= ~BIT(6);
+
+ ps_type = COEX_PS_WIFI_NATIVE;
+ rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
+ } else if (byte1 & BIT(4) && !(byte1 & BIT(5))) {
+ if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)
+ ps_type = COEX_PS_LPS_OFF;
+ else
+ ps_type = COEX_PS_LPS_ON;
+ rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);
+ } else {
+ ps_type = COEX_PS_WIFI_NATIVE;
+ rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
+ }
+
+ coex_dm->ps_tdma_para[0] = byte1;
+ coex_dm->ps_tdma_para[1] = byte2;
+ coex_dm->ps_tdma_para[2] = byte3;
+ coex_dm->ps_tdma_para[3] = byte4;
+ coex_dm->ps_tdma_para[4] = byte5;
+
+ rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);
+}
+
+static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u8 type)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ u8 n;
+ bool turn_on;
+
+ turn_on = (type == 0 || type == 100) ? false : true;
+
+ if (!force) {
+ if (turn_on == coex_dm->cur_ps_tdma_on &&
+ type == coex_dm->cur_ps_tdma) {
+ return;
+ }
+ }
+
+ if (turn_on) {
+ /* enable TBTT interrupt */
+ rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);
+ } else {
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false);
+ }
+
+ if (efuse->share_ant) {
+ if (type < chip->tdma_sant_num)
+ rtw_coex_set_tdma(rtwdev,
+ chip->tdma_sant[type].para[0],
+ chip->tdma_sant[type].para[1],
+ chip->tdma_sant[type].para[2],
+ chip->tdma_sant[type].para[3],
+ chip->tdma_sant[type].para[4]);
+ } else {
+ n = type - 100;
+ if (n < chip->tdma_nsant_num)
+ rtw_coex_set_tdma(rtwdev,
+ chip->tdma_nsant[n].para[0],
+ chip->tdma_nsant[n].para[1],
+ chip->tdma_nsant[n].para[2],
+ chip->tdma_nsant[n].para[3],
+ chip->tdma_nsant[n].para[4]);
+ }
+
+ /* update pre state */
+ coex_dm->cur_ps_tdma_on = turn_on;
+ coex_dm->cur_ps_tdma = type;
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type);
+}
+
+static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ u8 ctrl_type = COEX_SWITCH_CTRL_MAX;
+ u8 pos_type = COEX_SWITCH_TO_MAX;
+
+ if (!force && coex_dm->cur_ant_pos_type == phase)
+ return;
+
+ coex_dm->cur_ant_pos_type = phase;
+
+ /* avoid switch coex_ctrl_owner during BT IQK */
+ rtw_coex_check_rfk(rtwdev);
+
+ switch (phase) {
+ case COEX_SET_ANT_POWERON:
+ /* set path control owner to BT at power-on */
+ if (coex_stat->bt_disabled)
+ rtw_coex_coex_ctrl_owner(rtwdev, true);
+ else
+ rtw_coex_coex_ctrl_owner(rtwdev, false);
+
+ ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
+ pos_type = COEX_SWITCH_TO_BT;
+ break;
+ case COEX_SET_ANT_INIT:
+ if (coex_stat->bt_disabled) {
+ /* set GNT_BT to SW low */
+ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
+
+ /* set GNT_WL to SW high */
+ rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
+ } else {
+ /* set GNT_BT to SW high */
+ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
+
+ /* set GNT_WL to SW low */
+ rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW);
+ }
+
+ /* set path control owner to wl at initial step */
+ rtw_coex_coex_ctrl_owner(rtwdev, true);
+
+ ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
+ pos_type = COEX_SWITCH_TO_BT;
+ break;
+ case COEX_SET_ANT_WONLY:
+ /* set GNT_BT to SW Low */
+ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
+
+ /* Set GNT_WL to SW high */
+ rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
+
+ /* set path control owner to wl at initial step */
+ rtw_coex_coex_ctrl_owner(rtwdev, true);
+
+ ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
+ pos_type = COEX_SWITCH_TO_WLG;
+ break;
+ case COEX_SET_ANT_WOFF:
+ /* set path control owner to BT */
+ rtw_coex_coex_ctrl_owner(rtwdev, false);
+
+ ctrl_type = COEX_SWITCH_CTRL_BY_BT;
+ pos_type = COEX_SWITCH_TO_NOCARE;
+ break;
+ case COEX_SET_ANT_2G:
+ /* set GNT_BT to PTA */
+ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
+
+ /* set GNT_WL to PTA */
+ rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
+
+ /* set path control owner to wl at runtime step */
+ rtw_coex_coex_ctrl_owner(rtwdev, true);
+
+ ctrl_type = COEX_SWITCH_CTRL_BY_PTA;
+ pos_type = COEX_SWITCH_TO_NOCARE;
+ break;
+ case COEX_SET_ANT_5G:
+ /* set GNT_BT to PTA */
+ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
+
+ /* set GNT_WL to SW high */
+ rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
+
+ /* set path control owner to wl at runtime step */
+ rtw_coex_coex_ctrl_owner(rtwdev, true);
+
+ ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
+ pos_type = COEX_SWITCH_TO_WLA;
+ break;
+ case COEX_SET_ANT_2G_FREERUN:
+ /* set GNT_BT to SW high */
+ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
+
+ /* Set GNT_WL to SW high */
+ rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
+
+ /* set path control owner to wl at runtime step */
+ rtw_coex_coex_ctrl_owner(rtwdev, true);
+
+ ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
+ pos_type = COEX_SWITCH_TO_WLG_BT;
+ break;
+ case COEX_SET_ANT_2G_WLBT:
+ /* set GNT_BT to SW high */
+ rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
+
+ /* Set GNT_WL to SW high */
+ rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
+
+ /* set path control owner to wl at runtime step */
+ rtw_coex_coex_ctrl_owner(rtwdev, true);
+
+ ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
+ pos_type = COEX_SWITCH_TO_WLG_BT;
+ break;
+ default:
+ WARN_ON("unknown phase when setting antenna path\n");
+ return;
+ }
+
+ if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX)
+ rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
+}
+
+static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ u8 algorithm = COEX_ALGO_NOPROFILE;
+ u8 profile_map = 0;
+
+ if (coex_stat->bt_hfp_exist)
+ profile_map |= BPM_HFP;
+ if (coex_stat->bt_hid_exist)
+ profile_map |= BPM_HID;
+ if (coex_stat->bt_a2dp_exist)
+ profile_map |= BPM_A2DP;
+ if (coex_stat->bt_pan_exist)
+ profile_map |= BPM_PAN;
+
+ switch (profile_map) {
+ case BPM_HFP:
+ algorithm = COEX_ALGO_HFP;
+ break;
+ case BPM_HID:
+ case BPM_HFP + BPM_HID:
+ algorithm = COEX_ALGO_HID;
+ break;
+ case BPM_HFP + BPM_A2DP:
+ case BPM_HID + BPM_A2DP:
+ case BPM_HFP + BPM_HID + BPM_A2DP:
+ algorithm = COEX_ALGO_A2DP_HID;
+ break;
+ case BPM_HFP + BPM_PAN:
+ case BPM_HID + BPM_PAN:
+ case BPM_HFP + BPM_HID + BPM_PAN:
+ algorithm = COEX_ALGO_PAN_HID;
+ break;
+ case BPM_HFP + BPM_A2DP + BPM_PAN:
+ case BPM_HID + BPM_A2DP + BPM_PAN:
+ case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN:
+ algorithm = COEX_ALGO_A2DP_PAN_HID;
+ break;
+ case BPM_PAN:
+ algorithm = COEX_ALGO_PAN;
+ break;
+ case BPM_A2DP + BPM_PAN:
+ algorithm = COEX_ALGO_A2DP_PAN;
+ break;
+ case BPM_A2DP:
+ if (coex_stat->bt_multi_link) {
+ if (coex_stat->bt_hid_pair_num > 0)
+ algorithm = COEX_ALGO_A2DP_HID;
+ else
+ algorithm = COEX_ALGO_A2DP_PAN;
+ } else {
+ algorithm = COEX_ALGO_A2DP;
+ }
+ break;
+ default:
+ algorithm = COEX_ALGO_NOPROFILE;
+ break;
+ }
+
+ return algorithm;
+}
+
+static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ table_case = 2;
+ tdma_case = 0;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 100;
+ tdma_case = 100;
+ }
+
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 level = 0;
+
+ if (efuse->share_ant)
+ return;
+
+ coex->freerun = true;
+
+ if (coex_stat->wl_connected)
+ rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
+
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
+
+ if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0]))
+ level = 2;
+ else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
+ level = 3;
+ else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2]))
+ level = 4;
+ else
+ level = 5;
+
+ if (level > chip->wl_rf_para_num - 1)
+ level = chip->wl_rf_para_num - 1;
+
+ if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]);
+ else
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);
+
+ rtw_coex_table(rtwdev, 100);
+ rtw_coex_tdma(rtwdev, false, 100);
+}
+
+static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ table_case = 2;
+ tdma_case = 0;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 100;
+ tdma_case = 100;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ table_case = 1;
+ tdma_case = 0;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 100;
+ tdma_case = 100;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_coex_rfe *coex_rfe = &coex->rfe;
+ u8 table_case = 0xff, tdma_case = 0xff;
+
+ if (coex_rfe->ant_switch_with_bt &&
+ coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
+ if (efuse->share_ant &&
+ COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) {
+ table_case = 0;
+ tdma_case = 0;
+ } else if (!efuse->share_ant) {
+ table_case = 100;
+ tdma_case = 100;
+ }
+ }
+
+ if (table_case != 0xff && tdma_case != 0xff) {
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+ return;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ if (!coex_stat->wl_gl_busy) {
+ table_case = 10;
+ tdma_case = 3;
+ } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
+ table_case = 6;
+ tdma_case = 7;
+ } else {
+ table_case = 12;
+ tdma_case = 7;
+ }
+ } else {
+ /* Non-Shared-Ant */
+ if (!coex_stat->wl_gl_busy) {
+ table_case = 112;
+ tdma_case = 104;
+ } else if ((coex_stat->bt_ble_scan_type & 0x2) &&
+ coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
+ table_case = 114;
+ tdma_case = 103;
+ } else {
+ table_case = 112;
+ tdma_case = 103;
+ }
+ }
+
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ bool wl_hi_pri = false;
+ u8 table_case, tdma_case;
+
+ if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
+ coex_stat->wl_hi_pri_task2)
+ wl_hi_pri = true;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ if (wl_hi_pri) {
+ table_case = 15;
+ if (coex_stat->bt_a2dp_exist &&
+ !coex_stat->bt_pan_exist)
+ tdma_case = 11;
+ else if (coex_stat->wl_hi_pri_task1)
+ tdma_case = 6;
+ else if (!coex_stat->bt_page)
+ tdma_case = 8;
+ else
+ tdma_case = 9;
+ } else if (coex_stat->wl_connected) {
+ table_case = 10;
+ tdma_case = 10;
+ } else {
+ table_case = 1;
+ tdma_case = 0;
+ }
+ } else {
+ /* Non_Shared-Ant */
+ if (wl_hi_pri) {
+ table_case = 113;
+ if (coex_stat->bt_a2dp_exist &&
+ !coex_stat->bt_pan_exist)
+ tdma_case = 111;
+ else if (coex_stat->wl_hi_pri_task1)
+ tdma_case = 106;
+ else if (!coex_stat->bt_page)
+ tdma_case = 108;
+ else
+ tdma_case = 109;
+ } else if (coex_stat->wl_connected) {
+ table_case = 101;
+ tdma_case = 110;
+ } else {
+ table_case = 100;
+ tdma_case = 100;
+ }
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n",
+ wl_hi_pri, coex_stat->bt_page);
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ if (coex_stat->bt_multi_link) {
+ table_case = 10;
+ tdma_case = 17;
+ } else {
+ table_case = 10;
+ tdma_case = 5;
+ }
+ } else {
+ /* Non-Shared-Ant */
+ if (coex_stat->bt_multi_link) {
+ table_case = 112;
+ tdma_case = 117;
+ } else {
+ table_case = 105;
+ tdma_case = 100;
+ }
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+ u32 wl_bw;
+
+ wl_bw = rtwdev->hal.current_band_width;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ if (coex_stat->bt_ble_exist) {
+ /* RCU */
+ if (!coex_stat->wl_gl_busy)
+ table_case = 14;
+ else
+ table_case = 15;
+
+ if (coex_stat->bt_a2dp_active || wl_bw == 0)
+ tdma_case = 18;
+ else if (coex_stat->wl_gl_busy)
+ tdma_case = 8;
+ else
+ tdma_case = 4;
+ } else {
+ if (coex_stat->bt_a2dp_active || wl_bw == 0) {
+ table_case = 8;
+ tdma_case = 4;
+ } else {
+ /* for 4/18 HID */
+ if (coex_stat->bt_418_hid_exist &&
+ coex_stat->wl_gl_busy)
+ table_case = 12;
+ else
+ table_case = 10;
+ tdma_case = 4;
+ }
+ }
+ } else {
+ /* Non-Shared-Ant */
+ if (coex_stat->bt_a2dp_active) {
+ table_case = 113;
+ tdma_case = 118;
+ } else if (coex_stat->bt_ble_exist) {
+ /* BLE */
+ table_case = 113;
+
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 106;
+ else
+ tdma_case = 104;
+ } else {
+ table_case = 113;
+ tdma_case = 104;
+ }
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
+ table_case = 10;
+ else
+ table_case = 9;
+
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 13;
+ else
+ tdma_case = 14;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 112;
+
+ if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
+ tdma_case = 112;
+ else
+ tdma_case = 113;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+ bool ap_enable = false;
+
+ if (efuse->share_ant) { /* Shared-Ant */
+ if (ap_enable) {
+ table_case = 2;
+ tdma_case = 0;
+ } else if (coex_stat->wl_gl_busy) {
+ table_case = 28;
+ tdma_case = 20;
+ } else {
+ table_case = 28;
+ tdma_case = 26;
+ }
+ } else { /* Non-Shared-Ant */
+ if (ap_enable) {
+ table_case = 100;
+ tdma_case = 100;
+ } else {
+ table_case = 119;
+ tdma_case = 120;
+ }
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
+ table_case = 14;
+ else
+ table_case = 10;
+
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 17;
+ else
+ tdma_case = 19;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 112;
+
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 117;
+ else
+ tdma_case = 119;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ if (coex_stat->bt_ble_exist)
+ table_case = 26;
+ else
+ table_case = 9;
+
+ if (!coex_stat->wl_gl_busy)
+ tdma_case = 14;
+ else
+ tdma_case = 13;
+ } else {
+ /* Non-Shared-Ant */
+ if (coex_stat->bt_ble_exist)
+ table_case = 121;
+ else
+ table_case = 113;
+
+ if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
+ tdma_case = 112;
+ else
+ tdma_case = 113;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ if (coex_stat->wl_gl_busy &&
+ coex_stat->wl_noisy_level == 0)
+ table_case = 14;
+ else
+ table_case = 10;
+
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 15;
+ else
+ tdma_case = 20;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 112;
+
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 115;
+ else
+ tdma_case = 120;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ table_case = 9;
+
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 18;
+ else
+ tdma_case = 19;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 113;
+
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 117;
+ else
+ tdma_case = 119;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ table_case = 10;
+
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 15;
+ else
+ tdma_case = 20;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 113;
+
+ if (coex_stat->wl_gl_busy)
+ tdma_case = 115;
+ else
+ tdma_case = 120;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ table_case = 0;
+ tdma_case = 0;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 100;
+ tdma_case = 100;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ table_case = 2;
+ tdma_case = 0;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 100;
+ tdma_case = 100;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (coex->under_5g)
+ return;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ table_case = 28;
+ tdma_case = 0;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 100;
+ tdma_case = 100;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ if (coex_stat->bt_a2dp_exist) {
+ table_case = 9;
+ tdma_case = 11;
+ } else {
+ table_case = 9;
+ tdma_case = 7;
+ }
+ } else {
+ /* Non-Shared-Ant */
+ if (coex_stat->bt_a2dp_exist) {
+ table_case = 112;
+ tdma_case = 111;
+ } else {
+ table_case = 112;
+ tdma_case = 107;
+ }
+ }
+
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ u8 table_case, tdma_case;
+
+ if (efuse->share_ant) {
+ /* Shared-Ant */
+ table_case = 1;
+ tdma_case = 0;
+ } else {
+ /* Non-Shared-Ant */
+ table_case = 100;
+ tdma_case = 100;
+ }
+
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
+ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
+ rtw_coex_table(rtwdev, table_case);
+ rtw_coex_tdma(rtwdev, false, tdma_case);
+}
+
+static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ u8 algorithm;
+
+ /* Non-Shared-Ant */
+ if (!efuse->share_ant && coex_stat->wl_gl_busy &&
+ COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
+ COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) {
+ rtw_coex_action_freerun(rtwdev);
+ return;
+ }
+
+ algorithm = rtw_coex_algorithm(rtwdev);
+
+ switch (algorithm) {
+ case COEX_ALGO_HFP:
+ rtw_coex_action_bt_hfp(rtwdev);
+ break;
+ case COEX_ALGO_HID:
+ rtw_coex_action_bt_hid(rtwdev);
+ break;
+ case COEX_ALGO_A2DP:
+ if (coex_stat->bt_a2dp_sink)
+ rtw_coex_action_bt_a2dpsink(rtwdev);
+ else
+ rtw_coex_action_bt_a2dp(rtwdev);
+ break;
+ case COEX_ALGO_PAN:
+ rtw_coex_action_bt_pan(rtwdev);
+ break;
+ case COEX_ALGO_A2DP_HID:
+ rtw_coex_action_bt_a2dp_hid(rtwdev);
+ break;
+ case COEX_ALGO_A2DP_PAN:
+ rtw_coex_action_bt_a2dp_pan(rtwdev);
+ break;
+ case COEX_ALGO_PAN_HID:
+ rtw_coex_action_bt_pan_hid(rtwdev);
+ break;
+ case COEX_ALGO_A2DP_PAN_HID:
+ rtw_coex_action_bt_a2dp_pan_hid(rtwdev);
+ break;
+ default:
+ case COEX_ALGO_NOPROFILE:
+ rtw_coex_action_bt_idle(rtwdev);
+ break;
+ }
+}
+
+static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ coex_dm->reason = reason;
+
+ /* update wifi_link_info_ext variable */
+ rtw_coex_update_wl_link_info(rtwdev, reason);
+
+ rtw_coex_monitor_bt_enable(rtwdev);
+
+ if (coex->stop_dm)
+ return;
+
+ if (coex_stat->wl_under_ips)
+ return;
+
+ if (coex->freeze && !coex_stat->bt_setup_link)
+ return;
+
+ coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
+ coex->freerun = false;
+
+ /* Pure-5G Coex Process */
+ if (coex->under_5g) {
+ coex_stat->wl_coex_mode = COEX_WLINK_5G;
+ rtw_coex_action_wl_under5g(rtwdev);
+ goto exit;
+ }
+
+ coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
+ if (coex_stat->bt_disabled) {
+ rtw_coex_action_wl_only(rtwdev);
+ goto exit;
+ }
+
+ if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {
+ rtw_coex_action_wl_native_lps(rtwdev);
+ goto exit;
+ }
+
+ if (coex_stat->bt_whck_test) {
+ rtw_coex_action_bt_whql_test(rtwdev);
+ goto exit;
+ }
+
+ if (coex_stat->bt_setup_link) {
+ rtw_coex_action_bt_relink(rtwdev);
+ goto exit;
+ }
+
+ if (coex_stat->bt_inq_page) {
+ rtw_coex_action_bt_inquiry(rtwdev);
+ goto exit;
+ }
+
+ if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||
+ coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&
+ coex_stat->wl_connected) {
+ rtw_coex_action_bt_idle(rtwdev);
+ goto exit;
+ }
+
+ if (coex_stat->wl_linkscan_proc) {
+ rtw_coex_action_wl_linkscan(rtwdev);
+ goto exit;
+ }
+
+ if (coex_stat->wl_connected)
+ rtw_coex_action_wl_connected(rtwdev);
+ else
+ rtw_coex_action_wl_not_connected(rtwdev);
+
+exit:
+ rtw_coex_set_gnt_fix(rtwdev);
+ rtw_coex_limited_wl(rtwdev);
+}
+
+static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ u8 i;
+
+ memset(coex_dm, 0, sizeof(*coex_dm));
+ memset(coex_stat, 0, sizeof(*coex_stat));
+
+ for (i = 0; i < COEX_CNT_WL_MAX; i++)
+ coex_stat->cnt_wl[i] = 0;
+
+ for (i = 0; i < COEX_CNT_BT_MAX; i++)
+ coex_stat->cnt_bt[i] = 0;
+
+ for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)
+ coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;
+
+ for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)
+ coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
+
+ coex_stat->wl_coex_mode = COEX_WLINK_MAX;
+}
+
+static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+
+ rtw_coex_init_coex_var(rtwdev);
+ rtw_coex_monitor_bt_enable(rtwdev);
+ rtw_coex_set_rfe_type(rtwdev);
+ rtw_coex_set_init(rtwdev);
+
+ /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */
+ rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);
+
+ /* set Tx beacon = Hi-Pri */
+ rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);
+
+ /* set Tx beacon queue = Hi-Pri */
+ rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);
+
+ /* antenna config */
+ if (coex->wl_rf_off) {
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
+ coex->stop_dm = true;
+ } else if (wifi_only) {
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
+ true);
+ coex->stop_dm = true;
+ } else {
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
+ true);
+ coex->stop_dm = false;
+ coex->freeze = true;
+ }
+
+ /* PTA parameter */
+ rtw_coex_table(rtwdev, 0);
+ rtw_coex_tdma(rtwdev, true, 0);
+ rtw_coex_query_bt_info(rtwdev);
+}
+
+void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+
+ coex->stop_dm = true;
+ coex->wl_rf_off = false;
+
+ /* enable BB, we can write 0x948 */
+ rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1));
+
+ rtw_coex_monitor_bt_enable(rtwdev);
+ rtw_coex_set_rfe_type(rtwdev);
+
+ /* set antenna path to BT */
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
+
+ /* red x issue */
+ rtw_write8(rtwdev, 0xff1a, 0x0);
+}
+
+void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
+{
+ __rtw_coex_init_hw_config(rtwdev, wifi_only);
+}
+
+void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+
+ if (coex->stop_dm)
+ return;
+
+ if (type == COEX_IPS_ENTER) {
+ coex_stat->wl_under_ips = true;
+
+ /* for lps off */
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
+
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
+ rtw_coex_action_coex_all_off(rtwdev);
+ } else if (type == COEX_IPS_LEAVE) {
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
+
+ /* run init hw config (exclude wifi only) */
+ __rtw_coex_init_hw_config(rtwdev, false);
+ /* sw all off */
+
+ coex_stat->wl_under_ips = false;
+ }
+}
+
+void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+
+ if (coex->stop_dm)
+ return;
+
+ if (type == COEX_LPS_ENABLE) {
+ coex_stat->wl_under_lps = true;
+
+ if (coex_stat->wl_force_lps_ctrl) {
+ /* for ps-tdma */
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
+ } else {
+ /* for native ps */
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
+
+ rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
+ }
+ } else if (type == COEX_LPS_DISABLE) {
+ coex_stat->wl_under_lps = false;
+
+ /* for lps off */
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
+
+ if (!coex_stat->wl_force_lps_ctrl)
+ rtw_coex_query_bt_info(rtwdev);
+ }
+}
+
+void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+
+ if (coex->stop_dm)
+ return;
+
+ coex->freeze = false;
+
+ if (type != COEX_SCAN_FINISH)
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
+ COEX_SCBD_ONOFF, true);
+
+ if (type == COEX_SCAN_START_5G) {
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
+ rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
+ } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
+ coex_stat->wl_hi_pri_task2 = true;
+
+ /* Force antenna setup for no scan result issue */
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
+ rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
+ } else {
+ coex_stat->wl_hi_pri_task2 = false;
+ rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
+ }
+}
+
+void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+
+ if (coex->stop_dm)
+ return;
+
+ if (type == COEX_SWITCH_TO_5G)
+ rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
+ else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
+ rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);
+ else
+ rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);
+}
+
+void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+
+ if (coex->stop_dm)
+ return;
+
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
+ COEX_SCBD_ONOFF, true);
+
+ if (type == COEX_ASSOCIATE_5G_START) {
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
+ rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
+ } else if (type == COEX_ASSOCIATE_5G_FINISH) {
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
+ rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
+ } else if (type == COEX_ASSOCIATE_START) {
+ coex_stat->wl_hi_pri_task1 = true;
+ coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
+
+ /* Force antenna setup for no scan result issue */
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
+
+ rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);
+
+ /* To keep TDMA case during connect process,
+ * to avoid changed by Btinfo and runcoexmechanism
+ */
+ coex->freeze = true;
+ ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,
+ 5 * HZ);
+ } else {
+ coex_stat->wl_hi_pri_task1 = false;
+ coex->freeze = false;
+
+ rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
+ }
+}
+
+void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ u8 para[6] = {0};
+
+ if (coex->stop_dm)
+ return;
+
+ if (type == COEX_MEDIA_CONNECT_5G) {
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
+
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
+ rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
+ } else if (type == COEX_MEDIA_CONNECT) {
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
+
+ /* Force antenna setup for no scan result issue */
+ rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
+
+ /* Set CCK Rx high Pri */
+ rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
+
+ /* always enable 5ms extend if connect */
+ para[0] = COEX_H2C69_WL_LEAKAP;
+ para[1] = PARA1_H2C69_EN_5MS; /* enable 5ms extend */
+ rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
+ coex_stat->wl_slot_extend = true;
+ rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
+ } else {
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
+
+ rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
+
+ rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
+ }
+
+ rtw_coex_update_wl_ch_info(rtwdev, type);
+}
+
+void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ unsigned long bt_relink_time;
+ u8 i, rsp_source = 0, type;
+
+ rsp_source = buf[0] & 0xf;
+ if (rsp_source >= COEX_BTINFO_SRC_MAX)
+ rsp_source = COEX_BTINFO_SRC_WL_FW;
+
+ if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
+ coex_stat->bt_iqk_state = buf[1];
+ if (coex_stat->bt_iqk_state == 1)
+ coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
+ else if (coex_stat->bt_iqk_state == 2)
+ coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
+
+ return;
+ }
+
+ if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
+ rtw_coex_monitor_bt_enable(rtwdev);
+ if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
+ coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
+ rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
+ }
+ return;
+ }
+
+ if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
+ rsp_source == COEX_BTINFO_SRC_BT_ACT) {
+ if (coex_stat->bt_disabled) {
+ coex_stat->bt_disabled = false;
+ coex_stat->bt_reenable = true;
+ ieee80211_queue_delayed_work(rtwdev->hw,
+ &coex->bt_reenable_work,
+ 15 * HZ);
+ }
+ }
+
+ for (i = 0; i < length; i++) {
+ if (i < COEX_BTINFO_LENGTH_MAX)
+ coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
+ else
+ break;
+ }
+
+ if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
+ rtw_coex_update_bt_link_info(rtwdev);
+ rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
+ return;
+ }
+
+ /* get the same info from bt, skip it */
+ if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
+ coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
+ coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
+ coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
+ coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
+ coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3)
+ return;
+
+ coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
+ coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
+ coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];
+ coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];
+ coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];
+ coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];
+
+ /* 0xff means BT is under WHCK test */
+ coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);
+ coex_stat->bt_inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));
+ coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
+ coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
+ if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
+ coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
+
+ coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));
+ coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));
+ if (coex_stat->bt_inq)
+ coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
+
+ coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
+ if (coex_stat->bt_page) {
+ coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
+ if (coex_stat->wl_linkscan_proc ||
+ coex_stat->wl_hi_pri_task1 ||
+ coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
+ else
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
+ } else {
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
+ }
+
+ /* unit: % (value-100 to translate to unit: dBm in coex info) */
+ if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
+ coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
+ } else { /* original unit: dbm -> unit: % -> value-100 in coex info */
+ if (coex_stat->bt_info_hb0 <= 127)
+ coex_stat->bt_rssi = 100;
+ else if (256 - coex_stat->bt_info_hb0 <= 100)
+ coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);
+ else
+ coex_stat->bt_rssi = 0;
+ }
+
+ coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0));
+ if (coex_stat->bt_info_hb1 & BIT(1))
+ coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
+
+ if (coex_stat->bt_info_hb1 & BIT(2)) {
+ coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;
+ coex_stat->bt_setup_link = true;
+ if (coex_stat->bt_reenable)
+ bt_relink_time = 6 * HZ;
+ else
+ bt_relink_time = 2 * HZ;
+
+ ieee80211_queue_delayed_work(rtwdev->hw,
+ &coex->bt_relink_work,
+ bt_relink_time);
+ }
+
+ if (coex_stat->bt_info_hb1 & BIT(3))
+ coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;
+
+ coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));
+ coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));
+ if (coex_stat->bt_info_hb1 & BIT(6))
+ coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
+
+ coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
+ /* resend wifi info to bt, it is reset and lost the info */
+ if ((coex_stat->bt_info_hb1 & BIT(1))) {
+ if (coex_stat->wl_connected)
+ type = COEX_MEDIA_CONNECT;
+ else
+ type = COEX_MEDIA_DISCONNECT;
+ rtw_coex_update_wl_ch_info(rtwdev, type);
+ }
+
+ /* if ignore_wlan_act && not set_up_link */
+ if ((coex_stat->bt_info_hb1 & BIT(3)) &&
+ (!(coex_stat->bt_info_hb1 & BIT(2))))
+ rtw_coex_ignore_wlan_act(rtwdev, false);
+
+ coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
+ if (coex_stat->bt_info_hb2 & BIT(1))
+ coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;
+
+ coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);
+ coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));
+ coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;
+ coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
+ if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
+ coex_stat->bt_418_hid_exist = true;
+ else if (coex_stat->bt_hid_pair_num == 0)
+ coex_stat->bt_418_hid_exist = false;
+
+ if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
+ coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);
+ else
+ coex_stat->bt_a2dp_bitpool = 0;
+
+ coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));
+
+ rtw_coex_update_bt_link_info(rtwdev);
+ rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
+}
+
+void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ u8 val;
+ int i;
+
+ if (WARN(length < 8, "invalid wl info c2h length\n"))
+ return;
+
+ if (buf[0] != 0x08)
+ return;
+
+ for (i = 1; i < 8; i++) {
+ val = coex_stat->wl_fw_dbg_info_pre[i];
+ if (buf[i] >= val)
+ coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
+ else
+ coex_stat->wl_fw_dbg_info[i] = val - buf[i];
+
+ coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
+ }
+
+ coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;
+ rtw_coex_wl_ccklock_action(rtwdev);
+ rtw_coex_wl_ccklock_detect(rtwdev);
+}
+
+void rtw_coex_coex_dm_reset(struct rtw_dev *rtwdev)
+{
+ __rtw_coex_init_hw_config(rtwdev, false);
+}
+
+void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev)
+{
+ rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
+}
+
+void rtw_coex_bt_relink_work(struct work_struct *work)
+{
+ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
+ coex.bt_relink_work.work);
+ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
+
+ mutex_lock(&rtwdev->mutex);
+ coex_stat->bt_setup_link = false;
+ rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
+ mutex_unlock(&rtwdev->mutex);
+}
+
+void rtw_coex_bt_reenable_work(struct work_struct *work)
+{
+ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
+ coex.bt_reenable_work.work);
+ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
+
+ mutex_lock(&rtwdev->mutex);
+ coex_stat->bt_reenable = false;
+ mutex_unlock(&rtwdev->mutex);
+}
+
+void rtw_coex_defreeze_work(struct work_struct *work)
+{
+ struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
+ coex.defreeze_work.work);
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
+
+ mutex_lock(&rtwdev->mutex);
+ coex->freeze = false;
+ coex_stat->wl_hi_pri_task1 = false;
+ rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
+ mutex_unlock(&rtwdev->mutex);
+}
diff --git a/drivers/net/wireless/realtek/rtw88/coex.h b/drivers/net/wireless/realtek/rtw88/coex.h
new file mode 100644
index 0000000..248e3c8
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/coex.h
@@ -0,0 +1,363 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#ifndef __RTW_COEX_H__
+#define __RTW_COEX_H__
+
+/* BT profile map bit definition */
+#define BPM_HFP BIT(0)
+#define BPM_HID BIT(1)
+#define BPM_A2DP BIT(2)
+#define BPM_PAN BIT(3)
+
+#define COEX_RESP_ACK_BY_WL_FW 0x1
+#define COEX_REQUEST_TIMEOUT msecs_to_jiffies(10)
+
+#define COEX_MIN_DELAY 10 /* delay unit in ms */
+#define COEX_RFK_TIMEOUT 600 /* RFK timeout in ms */
+
+#define COEX_RF_OFF 0x0
+#define COEX_RF_ON 0x1
+
+#define COEX_H2C69_WL_LEAKAP 0xc
+#define PARA1_H2C69_DIS_5MS 0x1
+#define PARA1_H2C69_EN_5MS 0x0
+
+#define COEX_RSSI_STEP 4
+#define COEX_RSSI_HIGH(rssi) \
+ ({ typeof(rssi) __rssi__ = rssi; \
+ (__rssi__ == COEX_RSSI_STATE_HIGH || \
+ __rssi__ == COEX_RSSI_STATE_STAY_HIGH ? true : false); })
+
+#define COEX_RSSI_MEDIUM(rssi) \
+ ({ typeof(rssi) __rssi__ = rssi; \
+ (__rssi__ == COEX_RSSI_STATE_MEDIUM || \
+ __rssi__ == COEX_RSSI_STATE_STAY_MEDIUM ? true : false); })
+
+#define COEX_RSSI_LOW(rssi) \
+ ({ typeof(rssi) __rssi__ = rssi; \
+ (__rssi__ == COEX_RSSI_STATE_LOW || \
+ __rssi__ == COEX_RSSI_STATE_STAY_LOW ? true : false); })
+
+#define GET_COEX_RESP_BT_SCAN_TYPE(payload) \
+ le64_get_bits(*((__le64 *)(payload)), GENMASK(31, 24))
+
+enum coex_mp_info_op {
+ BT_MP_INFO_OP_PATCH_VER = 0x00,
+ BT_MP_INFO_OP_READ_REG = 0x11,
+ BT_MP_INFO_OP_SUPP_FEAT = 0x2a,
+ BT_MP_INFO_OP_SUPP_VER = 0x2b,
+ BT_MP_INFO_OP_SCAN_TYPE = 0x2d,
+ BT_MP_INFO_OP_LNA_CONSTRAINT = 0x32,
+};
+
+enum coex_set_ant_phase {
+ COEX_SET_ANT_INIT,
+ COEX_SET_ANT_WONLY,
+ COEX_SET_ANT_WOFF,
+ COEX_SET_ANT_2G,
+ COEX_SET_ANT_5G,
+ COEX_SET_ANT_POWERON,
+ COEX_SET_ANT_2G_WLBT,
+ COEX_SET_ANT_2G_FREERUN,
+
+ COEX_SET_ANT_MAX
+};
+
+enum coex_runreason {
+ COEX_RSN_2GSCANSTART = 0,
+ COEX_RSN_5GSCANSTART = 1,
+ COEX_RSN_SCANFINISH = 2,
+ COEX_RSN_2GSWITCHBAND = 3,
+ COEX_RSN_5GSWITCHBAND = 4,
+ COEX_RSN_2GCONSTART = 5,
+ COEX_RSN_5GCONSTART = 6,
+ COEX_RSN_2GCONFINISH = 7,
+ COEX_RSN_5GCONFINISH = 8,
+ COEX_RSN_2GMEDIA = 9,
+ COEX_RSN_5GMEDIA = 10,
+ COEX_RSN_MEDIADISCON = 11,
+ COEX_RSN_BTINFO = 12,
+ COEX_RSN_LPS = 13,
+ COEX_RSN_WLSTATUS = 14,
+
+ COEX_RSN_MAX
+};
+
+enum coex_lte_coex_table_type {
+ COEX_CTT_WL_VS_LTE,
+ COEX_CTT_BT_VS_LTE,
+};
+
+enum coex_gnt_setup_state {
+ COEX_GNT_SET_HW_PTA = 0x0,
+ COEX_GNT_SET_SW_LOW = 0x1,
+ COEX_GNT_SET_SW_HIGH = 0x3,
+};
+
+enum coex_ext_ant_switch_pos_type {
+ COEX_SWITCH_TO_BT,
+ COEX_SWITCH_TO_WLG,
+ COEX_SWITCH_TO_WLA,
+ COEX_SWITCH_TO_NOCARE,
+ COEX_SWITCH_TO_WLG_BT,
+
+ COEX_SWITCH_TO_MAX
+};
+
+enum coex_ext_ant_switch_ctrl_type {
+ COEX_SWITCH_CTRL_BY_BBSW,
+ COEX_SWITCH_CTRL_BY_PTA,
+ COEX_SWITCH_CTRL_BY_ANTDIV,
+ COEX_SWITCH_CTRL_BY_MAC,
+ COEX_SWITCH_CTRL_BY_BT,
+ COEX_SWITCH_CTRL_BY_FW,
+
+ COEX_SWITCH_CTRL_MAX
+};
+
+enum coex_algorithm {
+ COEX_ALGO_NOPROFILE = 0,
+ COEX_ALGO_HFP = 1,
+ COEX_ALGO_HID = 2,
+ COEX_ALGO_A2DP = 3,
+ COEX_ALGO_PAN = 4,
+ COEX_ALGO_A2DP_HID = 5,
+ COEX_ALGO_A2DP_PAN = 6,
+ COEX_ALGO_PAN_HID = 7,
+ COEX_ALGO_A2DP_PAN_HID = 8,
+
+ COEX_ALGO_MAX
+};
+
+enum coex_wl_link_mode {
+ COEX_WLINK_2G1PORT = 0x0,
+ COEX_WLINK_5G = 0x3,
+ COEX_WLINK_MAX
+};
+
+enum coex_wl2bt_scoreboard {
+ COEX_SCBD_ACTIVE = BIT(0),
+ COEX_SCBD_ONOFF = BIT(1),
+ COEX_SCBD_SCAN = BIT(2),
+ COEX_SCBD_UNDERTEST = BIT(3),
+ COEX_SCBD_RXGAIN = BIT(4),
+ COEX_SCBD_BT_RFK = BIT(5),
+ COEX_SCBD_WLBUSY = BIT(6),
+ COEX_SCBD_EXTFEM = BIT(8),
+ COEX_SCBD_TDMA = BIT(9),
+ COEX_SCBD_FIX2M = BIT(10),
+ COEX_SCBD_ALL = GENMASK(15, 0),
+};
+
+enum coex_power_save_type {
+ COEX_PS_WIFI_NATIVE = 0,
+ COEX_PS_LPS_ON = 1,
+ COEX_PS_LPS_OFF = 2,
+};
+
+enum coex_rssi_state {
+ COEX_RSSI_STATE_HIGH,
+ COEX_RSSI_STATE_MEDIUM,
+ COEX_RSSI_STATE_LOW,
+ COEX_RSSI_STATE_STAY_HIGH,
+ COEX_RSSI_STATE_STAY_MEDIUM,
+ COEX_RSSI_STATE_STAY_LOW,
+};
+
+enum coex_notify_type_ips {
+ COEX_IPS_LEAVE = 0x0,
+ COEX_IPS_ENTER = 0x1,
+};
+
+enum coex_notify_type_lps {
+ COEX_LPS_DISABLE = 0x0,
+ COEX_LPS_ENABLE = 0x1,
+};
+
+enum coex_notify_type_scan {
+ COEX_SCAN_FINISH,
+ COEX_SCAN_START,
+ COEX_SCAN_START_2G,
+ COEX_SCAN_START_5G,
+};
+
+enum coex_notify_type_switchband {
+ COEX_NOT_SWITCH,
+ COEX_SWITCH_TO_24G,
+ COEX_SWITCH_TO_5G,
+ COEX_SWITCH_TO_24G_NOFORSCAN,
+};
+
+enum coex_notify_type_associate {
+ COEX_ASSOCIATE_FINISH,
+ COEX_ASSOCIATE_START,
+ COEX_ASSOCIATE_5G_FINISH,
+ COEX_ASSOCIATE_5G_START,
+};
+
+enum coex_notify_type_media_status {
+ COEX_MEDIA_DISCONNECT,
+ COEX_MEDIA_CONNECT,
+ COEX_MEDIA_CONNECT_5G,
+};
+
+enum coex_bt_status {
+ COEX_BTSTATUS_NCON_IDLE = 0,
+ COEX_BTSTATUS_CON_IDLE = 1,
+ COEX_BTSTATUS_INQ_PAGE = 2,
+ COEX_BTSTATUS_ACL_BUSY = 3,
+ COEX_BTSTATUS_SCO_BUSY = 4,
+ COEX_BTSTATUS_ACL_SCO_BUSY = 5,
+
+ COEX_BTSTATUS_MAX
+};
+
+enum coex_wl_tput_dir {
+ COEX_WL_TPUT_TX = 0x0,
+ COEX_WL_TPUT_RX = 0x1,
+ COEX_WL_TPUT_MAX
+};
+
+enum coex_wl_priority_mask {
+ COEX_WLPRI_RX_RSP = 2,
+ COEX_WLPRI_TX_RSP = 3,
+ COEX_WLPRI_TX_BEACON = 4,
+ COEX_WLPRI_TX_OFDM = 11,
+ COEX_WLPRI_TX_CCK = 12,
+ COEX_WLPRI_TX_BEACONQ = 27,
+ COEX_WLPRI_RX_CCK = 28,
+ COEX_WLPRI_RX_OFDM = 29,
+ COEX_WLPRI_MAX
+};
+
+enum coex_commom_chip_setup {
+ COEX_CSETUP_INIT_HW = 0x0,
+ COEX_CSETUP_ANT_SWITCH = 0x1,
+ COEX_CSETUP_GNT_FIX = 0x2,
+ COEX_CSETUP_GNT_DEBUG = 0x3,
+ COEX_CSETUP_RFE_TYPE = 0x4,
+ COEX_CSETUP_COEXINFO_HW = 0x5,
+ COEX_CSETUP_WL_TX_POWER = 0x6,
+ COEX_CSETUP_WL_RX_GAIN = 0x7,
+ COEX_CSETUP_WLAN_ACT_IPS = 0x8,
+ COEX_CSETUP_MAX
+};
+
+enum coex_indirect_reg_type {
+ COEX_INDIRECT_1700 = 0x0,
+ COEX_INDIRECT_7C0 = 0x1,
+ COEX_INDIRECT_MAX
+};
+
+enum coex_pstdma_type {
+ COEX_PSTDMA_FORCE_LPSOFF = 0x0,
+ COEX_PSTDMA_FORCE_LPSON = 0x1,
+ COEX_PSTDMA_MAX
+};
+
+enum coex_btrssi_type {
+ COEX_BTRSSI_RATIO = 0x0,
+ COEX_BTRSSI_DBM = 0x1,
+ COEX_BTRSSI_MAX
+};
+
+struct coex_table_para {
+ u32 bt;
+ u32 wl;
+};
+
+struct coex_tdma_para {
+ u8 para[5];
+};
+
+struct coex_5g_afh_map {
+ u32 wl_5g_ch;
+ u8 bt_skip_ch;
+ u8 bt_skip_span;
+};
+
+struct coex_rf_para {
+ u8 wl_pwr_dec_lvl;
+ u8 bt_pwr_dec_lvl;
+ bool wl_low_gain_en;
+ u8 bt_lna_lvl;
+};
+
+static inline void rtw_coex_set_init(struct rtw_dev *rtwdev)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ chip->ops->coex_set_init(rtwdev);
+}
+
+static inline
+void rtw_coex_set_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, u8 pos_type)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ if (!chip->ops->coex_set_ant_switch)
+ return;
+
+ chip->ops->coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
+}
+
+static inline void rtw_coex_set_gnt_fix(struct rtw_dev *rtwdev)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ chip->ops->coex_set_gnt_fix(rtwdev);
+}
+
+static inline void rtw_coex_set_gnt_debug(struct rtw_dev *rtwdev)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ chip->ops->coex_set_gnt_debug(rtwdev);
+}
+
+static inline void rtw_coex_set_rfe_type(struct rtw_dev *rtwdev)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ chip->ops->coex_set_rfe_type(rtwdev);
+}
+
+static inline void rtw_coex_set_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ chip->ops->coex_set_wl_tx_power(rtwdev, wl_pwr);
+}
+
+static inline
+void rtw_coex_set_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ chip->ops->coex_set_wl_rx_gain(rtwdev, low_gain);
+}
+
+void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb);
+void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
+ u32 mask, u32 val);
+void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set);
+
+void rtw_coex_bt_relink_work(struct work_struct *work);
+void rtw_coex_bt_reenable_work(struct work_struct *work);
+void rtw_coex_defreeze_work(struct work_struct *work);
+
+void rtw_coex_power_on_setting(struct rtw_dev *rtwdev);
+void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only);
+void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type);
+void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type);
+void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type);
+void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 action);
+void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 status);
+void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 len);
+void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
+void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type);
+void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev);
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 3b06f71..b082e2c 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -3,6 +3,7 @@
*/
#include "main.h"
+#include "coex.h"
#include "fw.h"
#include "tx.h"
#include "reg.h"
@@ -39,6 +40,12 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
mutex_lock(&rtwdev->mutex);
switch (c2h->id) {
+ case C2H_BT_INFO:
+ rtw_coex_bt_info_notify(rtwdev, c2h->payload, len);
+ break;
+ case C2H_WLAN_INFO:
+ rtw_coex_wl_fwdbginfo_notify(rtwdev, c2h->payload, len);
+ break;
case C2H_HALMAC:
rtw_fw_c2h_cmd_handle_ext(rtwdev, skb);
break;
@@ -63,6 +70,9 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
c2h->id, c2h->seq, len);
switch (c2h->id) {
+ case C2H_BT_MP_INFO:
+ rtw_coex_info_response(rtwdev, skb);
+ break;
default:
/* pass offset for further operation */
*((u32 *)skb->cb) = pkt_offset;
@@ -206,6 +216,102 @@ void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para)
rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
}
+void rtw_fw_query_bt_info(struct rtw_dev *rtwdev)
+{
+ u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_INFO);
+
+ SET_QUERY_BT_INFO(h2c_pkt, true);
+
+ rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw)
+{
+ u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WL_CH_INFO);
+
+ SET_WL_CH_INFO_LINK(h2c_pkt, link);
+ SET_WL_CH_INFO_CHNL(h2c_pkt, ch);
+ SET_WL_CH_INFO_BW(h2c_pkt, bw);
+
+ rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_query_bt_mp_info(struct rtw_dev *rtwdev,
+ struct rtw_coex_info_req *req)
+{
+ u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_MP_INFO);
+
+ SET_BT_MP_INFO_SEQ(h2c_pkt, req->seq);
+ SET_BT_MP_INFO_OP_CODE(h2c_pkt, req->op_code);
+ SET_BT_MP_INFO_PARA1(h2c_pkt, req->para1);
+ SET_BT_MP_INFO_PARA2(h2c_pkt, req->para2);
+ SET_BT_MP_INFO_PARA3(h2c_pkt, req->para3);
+
+ rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
+{
+ u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+ u8 index = 0 - bt_pwr_dec_lvl;
+
+ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_FORCE_BT_TX_POWER);
+
+ SET_BT_TX_POWER_INDEX(h2c_pkt, index);
+
+ rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable)
+{
+ u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_IGNORE_WLAN_ACTION);
+
+ SET_IGNORE_WLAN_ACTION_EN(h2c_pkt, enable);
+
+ rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev,
+ u8 para1, u8 para2, u8 para3, u8 para4, u8 para5)
+{
+ u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_COEX_TDMA_TYPE);
+
+ SET_COEX_TDMA_TYPE_PARA1(h2c_pkt, para1);
+ SET_COEX_TDMA_TYPE_PARA2(h2c_pkt, para2);
+ SET_COEX_TDMA_TYPE_PARA3(h2c_pkt, para3);
+ SET_COEX_TDMA_TYPE_PARA4(h2c_pkt, para4);
+ SET_COEX_TDMA_TYPE_PARA5(h2c_pkt, para5);
+
+ rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data)
+{
+ u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BT_WIFI_CONTROL);
+
+ SET_BT_WIFI_CONTROL_OP_CODE(h2c_pkt, op_code);
+
+ SET_BT_WIFI_CONTROL_DATA1(h2c_pkt, *data);
+ SET_BT_WIFI_CONTROL_DATA2(h2c_pkt, *(data + 1));
+ SET_BT_WIFI_CONTROL_DATA3(h2c_pkt, *(data + 2));
+ SET_BT_WIFI_CONTROL_DATA4(h2c_pkt, *(data + 3));
+ SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, *(data + 4));
+
+ rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
{
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index 67f6cf7..e95d85b 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -35,7 +35,9 @@
enum rtw_c2h_cmd_id {
C2H_BT_INFO = 0x09,
+ C2H_BT_MP_INFO = 0x0b,
C2H_HW_FEATURE_REPORT = 0x19,
+ C2H_WLAN_INFO = 0x27,
C2H_HW_FEATURE_DUMP = 0xfd,
C2H_HALMAC = 0xff,
};
@@ -71,6 +73,14 @@ enum rtw_fw_rf_type {
FW_RF_MAX_TYPE = 0xF,
};
+struct rtw_coex_info_req {
+ u8 seq;
+ u8 op_code;
+ u8 para1;
+ u8 para2;
+ u8 para3;
+};
+
struct rtw_iqk_para {
u8 clear;
u8 segment_iqk;
@@ -139,6 +149,14 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
#define H2C_CMD_RA_INFO 0x40
#define H2C_CMD_RSSI_MONITOR 0x42
+#define H2C_CMD_COEX_TDMA_TYPE 0x60
+#define H2C_CMD_QUERY_BT_INFO 0x61
+#define H2C_CMD_FORCE_BT_TX_POWER 0x62
+#define H2C_CMD_IGNORE_WLAN_ACTION 0x63
+#define H2C_CMD_WL_CH_INFO 0x66
+#define H2C_CMD_QUERY_BT_MP_INFO 0x67
+#define H2C_CMD_BT_WIFI_CONTROL 0x69
+
#define SET_H2C_CMD_ID_CLASS(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0))
@@ -191,6 +209,50 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16))
#define SET_RA_INFO_RA_MASK3(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(31, 24))
+#define SET_QUERY_BT_INFO(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
+#define SET_WL_CH_INFO_LINK(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
+#define SET_WL_CH_INFO_CHNL(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
+#define SET_WL_CH_INFO_BW(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
+#define SET_BT_MP_INFO_SEQ(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 12))
+#define SET_BT_MP_INFO_OP_CODE(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
+#define SET_BT_MP_INFO_PARA1(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
+#define SET_BT_MP_INFO_PARA2(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
+#define SET_BT_MP_INFO_PARA3(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
+#define SET_BT_TX_POWER_INDEX(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
+#define SET_IGNORE_WLAN_ACTION_EN(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
+#define SET_COEX_TDMA_TYPE_PARA1(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
+#define SET_COEX_TDMA_TYPE_PARA2(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
+#define SET_COEX_TDMA_TYPE_PARA3(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
+#define SET_COEX_TDMA_TYPE_PARA4(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
+#define SET_COEX_TDMA_TYPE_PARA5(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
+#define SET_BT_WIFI_CONTROL_OP_CODE(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
+#define SET_BT_WIFI_CONTROL_DATA1(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
+#define SET_BT_WIFI_CONTROL_DATA2(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
+#define SET_BT_WIFI_CONTROL_DATA3(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
+#define SET_BT_WIFI_CONTROL_DATA4(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
+#define SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16))
static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb)
{
@@ -208,6 +270,15 @@ void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev);
void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para);
void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev);
+void rtw_fw_query_bt_info(struct rtw_dev *rtwdev);
+void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw);
+void rtw_fw_query_bt_mp_info(struct rtw_dev *rtwdev,
+ struct rtw_coex_info_req *req);
+void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl);
+void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable);
+void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev,
+ u8 para1, u8 para2, u8 para3, u8 para4, u8 para5);
+void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data);
void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn);
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index abe6a14..fedea28 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -7,6 +7,7 @@
#include "tx.h"
#include "fw.h"
#include "mac.h"
+#include "coex.h"
#include "ps.h"
#include "reg.h"
#include "debug.h"
@@ -253,6 +254,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
enum rtw_net_type net_type;
if (conf->assoc) {
+ rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH);
net_type = RTW_NET_MGD_LINKED;
chip->ops->do_iqk(rtwdev);
@@ -262,6 +264,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
rtw_add_rsvd_page(rtwdev, RSVD_NULL, true);
rtw_fw_download_rsvd_page(rtwdev, vif);
rtw_send_rsvd_page_h2c(rtwdev);
+ rtw_coex_media_status_notify(rtwdev, conf->assoc);
} else {
net_type = RTW_NET_NO_LINK;
rtwvif->aid = 0;
@@ -469,6 +472,8 @@ static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw,
config |= PORT_SET_MAC_ADDR;
rtw_vif_port_config(rtwdev, rtwvif, config);
+ rtw_coex_scan_notify(rtwdev, COEX_SCAN_START);
+
rtw_flag_set(rtwdev, RTW_FLAG_DIG_DISABLE);
rtw_flag_set(rtwdev, RTW_FLAG_SCANNING);
@@ -491,6 +496,19 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw,
config |= PORT_SET_MAC_ADDR;
rtw_vif_port_config(rtwdev, rtwvif, config);
+ rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH);
+
+ mutex_unlock(&rtwdev->mutex);
+}
+
+static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 duration)
+{
+ struct rtw_dev *rtwdev = hw->priv;
+
+ mutex_lock(&rtwdev->mutex);
+ rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_START);
mutex_unlock(&rtwdev->mutex);
}
@@ -509,5 +527,6 @@ const struct ieee80211_ops rtw_ops = {
.ampdu_action = rtw_ops_ampdu_action,
.sw_scan_start = rtw_ops_sw_scan_start,
.sw_scan_complete = rtw_ops_sw_scan_complete,
+ .mgd_prepare_tx = rtw_ops_mgd_prepare_tx,
};
EXPORT_SYMBOL(rtw_ops);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 5a2c062..e5a6bc0 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -8,6 +8,7 @@
#include "ps.h"
#include "sec.h"
#include "mac.h"
+#include "coex.h"
#include "phy.h"
#include "reg.h"
#include "efuse.h"
@@ -149,6 +150,7 @@ static void rtw_watch_dog_work(struct work_struct *work)
struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
watch_dog_work.work);
struct rtw_watch_dog_iter_data data = {};
+ bool busy_traffic = rtw_flag_check(rtwdev, RTW_FLAG_BUSY_TRAFFIC);
if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING))
return;
@@ -156,6 +158,14 @@ static void rtw_watch_dog_work(struct work_struct *work)
ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work,
RTW_WATCH_DOG_DELAY_TIME);
+ if (rtwdev->stats.tx_cnt > 100 || rtwdev->stats.rx_cnt > 100)
+ rtw_flag_set(rtwdev, RTW_FLAG_BUSY_TRAFFIC);
+ else
+ rtw_flag_clear(rtwdev, RTW_FLAG_BUSY_TRAFFIC);
+
+ if (busy_traffic != rtw_flag_check(rtwdev, RTW_FLAG_BUSY_TRAFFIC))
+ rtw_coex_wl_status_change_notify(rtwdev);
+
/* reset tx/rx statictics */
rtwdev->stats.tx_unicast = 0;
rtwdev->stats.rx_unicast = 0;
@@ -298,6 +308,15 @@ void rtw_set_channel(struct rtw_dev *rtwdev)
chip->ops->set_channel(rtwdev, center_chan, bandwidth, primary_chan_idx);
+ if (hal->current_band_type == RTW_BAND_5G) {
+ rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_5G);
+ } else {
+ if (rtw_flag_check(rtwdev, RTW_FLAG_SCANNING))
+ rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_24G);
+ else
+ rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_24G_NOFORSCAN);
+ }
+
rtw_phy_set_tx_power_level(rtwdev, center_chan);
}
@@ -641,6 +660,7 @@ static int rtw_power_on(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_fw_state *fw = &rtwdev->fw;
+ bool wifi_only;
int ret;
ret = rtw_hci_setup(rtwdev);
@@ -684,6 +704,10 @@ static int rtw_power_on(struct rtw_dev *rtwdev)
goto err_off;
}
+ wifi_only = !rtwdev->efuse.btcoex;
+ rtw_coex_power_on_setting(rtwdev);
+ rtw_coex_init_hw_config(rtwdev, wifi_only);
+
return 0;
err_off:
@@ -722,10 +746,15 @@ static void rtw_power_off(struct rtw_dev *rtwdev)
void rtw_core_stop(struct rtw_dev *rtwdev)
{
+ struct rtw_coex *coex = &rtwdev->coex;
+
rtw_flag_clear(rtwdev, RTW_FLAG_RUNNING);
rtw_flag_clear(rtwdev, RTW_FLAG_FW_RUNNING);
cancel_delayed_work_sync(&rtwdev->watch_dog_work);
+ cancel_delayed_work_sync(&coex->bt_relink_work);
+ cancel_delayed_work_sync(&coex->bt_reenable_work);
+ cancel_delayed_work_sync(&coex->defreeze_work);
rtw_power_off(rtwdev);
}
@@ -876,7 +905,6 @@ static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev)
struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_hal *hal = &rtwdev->hal;
struct rtw_efuse *efuse = &rtwdev->efuse;
- u32 wl_bt_pwr_ctrl;
int ret = 0;
switch (rtw_hci_type(rtwdev)) {
@@ -888,9 +916,6 @@ static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev)
return -EINVAL;
}
- wl_bt_pwr_ctrl = rtw_read32(rtwdev, REG_WL_BT_PWR_CTRL);
- if (wl_bt_pwr_ctrl & BIT_BT_FUNC_EN)
- rtwdev->efuse.btcoex = true;
hal->chip_version = rtw_read32(rtwdev, REG_SYS_CFG1);
hal->fab_version = BIT_GET_VENDOR_ID(hal->chip_version) >> 2;
hal->cut_version = BIT_GET_CHIP_VER(hal->chip_version);
@@ -1044,11 +1069,14 @@ static int rtw_chip_efuse_info_setup(struct rtw_dev *rtwdev)
efuse->lna_type_5g = 0;
if (efuse->channel_plan == 0xff)
efuse->channel_plan = 0x7f;
+ if (efuse->rf_board_option == 0xff)
+ efuse->rf_board_option = 0;
if (efuse->bt_setting & BIT(0))
efuse->share_ant = true;
if (efuse->regd == 0xff)
efuse->regd = 0;
+ efuse->btcoex = (efuse->rf_board_option & 0xe0) == 0x20;
efuse->ext_pa_2g = efuse->pa_type_2g & BIT(4) ? 1 : 0;
efuse->ext_lna_2g = efuse->lna_type_2g & BIT(3) ? 1 : 0;
efuse->ext_pa_5g = efuse->pa_type_5g & BIT(0) ? 1 : 0;
@@ -1111,6 +1139,7 @@ EXPORT_SYMBOL(rtw_chip_info_setup);
int rtw_core_init(struct rtw_dev *rtwdev)
{
+ struct rtw_coex *coex = &rtwdev->coex;
int ret;
INIT_LIST_HEAD(&rtwdev->rsvd_page_list);
@@ -1120,8 +1149,12 @@ int rtw_core_init(struct rtw_dev *rtwdev)
INIT_DELAYED_WORK(&rtwdev->watch_dog_work, rtw_watch_dog_work);
INIT_DELAYED_WORK(&rtwdev->lps_work, rtw_lps_work);
+ INIT_DELAYED_WORK(&coex->bt_relink_work, rtw_coex_bt_relink_work);
+ INIT_DELAYED_WORK(&coex->bt_reenable_work, rtw_coex_bt_reenable_work);
+ INIT_DELAYED_WORK(&coex->defreeze_work, rtw_coex_defreeze_work);
INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work);
skb_queue_head_init(&rtwdev->c2h_queue);
+ skb_queue_head_init(&rtwdev->coex.queue);
skb_queue_head_init(&rtwdev->tx_report.queue);
spin_lock_init(&rtwdev->dm_lock);
@@ -1130,8 +1163,11 @@ int rtw_core_init(struct rtw_dev *rtwdev)
spin_lock_init(&rtwdev->tx_report.q_lock);
mutex_init(&rtwdev->mutex);
+ mutex_init(&rtwdev->coex.mutex);
mutex_init(&rtwdev->hal.tx_power_mutex);
+ init_waitqueue_head(&rtwdev->coex.wait);
+
rtwdev->sec.total_cam_num = 32;
rtwdev->hal.current_channel = 1;
set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map);
@@ -1174,6 +1210,7 @@ void rtw_core_deinit(struct rtw_dev *rtwdev)
}
mutex_destroy(&rtwdev->mutex);
+ mutex_destroy(&rtwdev->coex.mutex);
mutex_destroy(&rtwdev->hal.tx_power_mutex);
}
EXPORT_SYMBOL(rtw_core_deinit);
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 8fa0575..9208b9c 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -310,6 +310,7 @@ enum rtw_flags {
RTW_FLAG_INACTIVE_PS,
RTW_FLAG_LEISURE_PS,
RTW_FLAG_DIG_DISABLE,
+ RTW_FLAG_BUSY_TRAFFIC,
NUM_OF_RTW_FLAGS,
};
@@ -640,6 +641,16 @@ struct rtw_chip_ops {
void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable);
void (*false_alarm_statistics)(struct rtw_dev *rtwdev);
void (*do_iqk)(struct rtw_dev *rtwdev);
+
+ /* for coex */
+ void (*coex_set_init)(struct rtw_dev *rtwdev);
+ void (*coex_set_ant_switch)(struct rtw_dev *rtwdev,
+ u8 ctrl_type, u8 pos_type);
+ void (*coex_set_gnt_fix)(struct rtw_dev *rtwdev);
+ void (*coex_set_gnt_debug)(struct rtw_dev *rtwdev);
+ void (*coex_set_rfe_type)(struct rtw_dev *rtwdev);
+ void (*coex_set_wl_tx_power)(struct rtw_dev *rtwdev, u8 wl_pwr);
+ void (*coex_set_wl_rx_gain)(struct rtw_dev *rtwdev, bool low_gain);
};
#define RTW_PWR_POLLING_CNT 20000
@@ -852,6 +863,216 @@ struct rtw_chip_info {
const struct rtw_rfe_def *rfe_defs;
u32 rfe_defs_size;
+
+ /* coex paras */
+ u32 coex_para_ver;
+ u8 bt_desired_ver;
+ bool scbd_support;
+ bool new_scbd10_def; /* true: fix 2M(8822c) */
+ u8 pstdma_type; /* 0: LPSoff, 1:LPSon */
+ u8 bt_rssi_type;
+ u8 ant_isolation;
+ u8 rssi_tolerance;
+ u8 table_sant_num;
+ u8 table_nsant_num;
+ u8 tdma_sant_num;
+ u8 tdma_nsant_num;
+ u8 bt_afh_span_bw20;
+ u8 bt_afh_span_bw40;
+ u8 afh_5g_num;
+ u8 wl_rf_para_num;
+ const u8 *bt_rssi_step;
+ const u8 *wl_rssi_step;
+ const struct coex_table_para *table_nsant;
+ const struct coex_table_para *table_sant;
+ const struct coex_tdma_para *tdma_sant;
+ const struct coex_tdma_para *tdma_nsant;
+ const struct coex_rf_para *wl_rf_para_tx;
+ const struct coex_rf_para *wl_rf_para_rx;
+ const struct coex_5g_afh_map *afh_5g;
+};
+
+enum rtw_coex_bt_state_cnt {
+ COEX_CNT_BT_RETRY,
+ COEX_CNT_BT_REINIT,
+ COEX_CNT_BT_REENABLE,
+ COEX_CNT_BT_POPEVENT,
+ COEX_CNT_BT_SETUPLINK,
+ COEX_CNT_BT_IGNWLANACT,
+ COEX_CNT_BT_INQ,
+ COEX_CNT_BT_PAGE,
+ COEX_CNT_BT_ROLESWITCH,
+ COEX_CNT_BT_AFHUPDATE,
+ COEX_CNT_BT_INFOUPDATE,
+ COEX_CNT_BT_IQK,
+ COEX_CNT_BT_IQKFAIL,
+
+ COEX_CNT_BT_MAX
+};
+
+enum rtw_coex_wl_state_cnt {
+ COEX_CNT_WL_CONNPKT,
+ COEX_CNT_WL_COEXRUN,
+ COEX_CNT_WL_NOISY0,
+ COEX_CNT_WL_NOISY1,
+ COEX_CNT_WL_NOISY2,
+ COEX_CNT_WL_5MS_NOEXTEND,
+ COEX_CNT_WL_FW_NOTIFY,
+
+ COEX_CNT_WL_MAX
+};
+
+struct rtw_coex_rfe {
+ bool ant_switch_exist;
+ bool ant_switch_diversity;
+ bool ant_switch_with_bt;
+ u8 rfe_module_type;
+ u8 ant_switch_polarity;
+
+ /* true if WLG at BTG, else at WLAG */
+ bool wlg_at_btg;
+};
+
+struct rtw_coex_dm {
+ bool cur_ps_tdma_on;
+ bool cur_wl_rx_low_gain_en;
+
+ u8 reason;
+ u8 bt_rssi_state[4];
+ u8 wl_rssi_state[4];
+ u8 wl_ch_info[3];
+ u8 cur_ps_tdma;
+ u8 cur_table;
+ u8 ps_tdma_para[5];
+ u8 cur_bt_pwr_lvl;
+ u8 cur_bt_lna_lvl;
+ u8 cur_wl_pwr_lvl;
+ u8 bt_status;
+ u32 cur_ant_pos_type;
+ u32 cur_switch_status;
+ u32 setting_tdma;
+};
+
+#define COEX_BTINFO_SRC_WL_FW 0x0
+#define COEX_BTINFO_SRC_BT_RSP 0x1
+#define COEX_BTINFO_SRC_BT_ACT 0x2
+#define COEX_BTINFO_SRC_BT_IQK 0x3
+#define COEX_BTINFO_SRC_BT_SCBD 0x4
+#define COEX_BTINFO_SRC_MAX 0x5
+
+#define COEX_INFO_FTP BIT(7)
+#define COEX_INFO_A2DP BIT(6)
+#define COEX_INFO_HID BIT(5)
+#define COEX_INFO_SCO_BUSY BIT(4)
+#define COEX_INFO_ACL_BUSY BIT(3)
+#define COEX_INFO_INQ_PAGE BIT(2)
+#define COEX_INFO_SCO_ESCO BIT(1)
+#define COEX_INFO_CONNECTION BIT(0)
+#define COEX_BTINFO_LENGTH_MAX 10
+
+struct rtw_coex_stat {
+ bool bt_disabled;
+ bool bt_disabled_pre;
+ bool bt_link_exist;
+ bool bt_whck_test;
+ bool bt_inq_page;
+ bool bt_inq;
+ bool bt_page;
+ bool bt_ble_voice;
+ bool bt_ble_exist;
+ bool bt_hfp_exist;
+ bool bt_a2dp_exist;
+ bool bt_hid_exist;
+ bool bt_pan_exist; /* PAN or OPP */
+ bool bt_opp_exist; /* OPP only */
+ bool bt_acl_busy;
+ bool bt_fix_2M;
+ bool bt_setup_link;
+ bool bt_multi_link;
+ bool bt_a2dp_sink;
+ bool bt_a2dp_active;
+ bool bt_reenable;
+ bool bt_ble_scan_en;
+ bool bt_init_scan;
+ bool bt_slave;
+ bool bt_418_hid_exist;
+ bool bt_mailbox_reply;
+
+ bool wl_under_lps;
+ bool wl_under_ips;
+ bool wl_hi_pri_task1;
+ bool wl_hi_pri_task2;
+ bool wl_force_lps_ctrl;
+ bool wl_gl_busy;
+ bool wl_linkscan_proc;
+ bool wl_ps_state_fail;
+ bool wl_tx_limit_en;
+ bool wl_ampdu_limit_en;
+ bool wl_connected;
+ bool wl_slot_extend;
+ bool wl_cck_lock;
+ bool wl_cck_lock_pre;
+ bool wl_cck_lock_ever;
+
+ u32 bt_supported_version;
+ u32 bt_supported_feature;
+ s8 bt_rssi;
+ u8 kt_ver;
+ u8 gnt_workaround_state;
+ u8 tdma_timer_base;
+ u8 bt_profile_num;
+ u8 bt_info_c2h[COEX_BTINFO_SRC_MAX][COEX_BTINFO_LENGTH_MAX];
+ u8 bt_info_lb2;
+ u8 bt_info_lb3;
+ u8 bt_info_hb0;
+ u8 bt_info_hb1;
+ u8 bt_info_hb2;
+ u8 bt_info_hb3;
+ u8 bt_ble_scan_type;
+ u8 bt_hid_pair_num;
+ u8 bt_hid_slot;
+ u8 bt_a2dp_bitpool;
+ u8 bt_iqk_state;
+
+ u8 wl_noisy_level;
+ u8 wl_fw_dbg_info[10];
+ u8 wl_fw_dbg_info_pre[10];
+ u8 wl_coex_mode;
+ u8 ampdu_max_time;
+ u8 wl_tput_dir;
+
+ u16 score_board;
+ u16 retry_limit;
+
+ /* counters to record bt states */
+ u32 cnt_bt[COEX_CNT_BT_MAX];
+
+ /* counters to record wifi states */
+ u32 cnt_wl[COEX_CNT_WL_MAX];
+
+ u32 darfrc;
+ u32 darfrch;
+};
+
+struct rtw_coex {
+ /* protects coex info request section */
+ struct mutex mutex;
+ struct sk_buff_head queue;
+ wait_queue_head_t wait;
+
+ bool under_5g;
+ bool stop_dm;
+ bool freeze;
+ bool freerun;
+ bool wl_rf_off;
+
+ struct rtw_coex_stat stat;
+ struct rtw_coex_dm dm;
+ struct rtw_coex_rfe rfe;
+
+ struct delayed_work bt_relink_work;
+ struct delayed_work bt_reenable_work;
+ struct delayed_work defreeze_work;
};
#define DACK_MSBK_BACKUP_NUM 0xf
@@ -861,6 +1082,16 @@ struct rtw_dm_info {
u32 cck_fa_cnt;
u32 ofdm_fa_cnt;
u32 total_fa_cnt;
+
+ u32 cck_ok_cnt;
+ u32 cck_err_cnt;
+ u32 ofdm_ok_cnt;
+ u32 ofdm_err_cnt;
+ u32 ht_ok_cnt;
+ u32 ht_err_cnt;
+ u32 vht_ok_cnt;
+ u32 vht_err_cnt;
+
u8 min_rssi;
u8 pre_min_rssi;
u16 fa_history[4];
@@ -888,6 +1119,7 @@ struct rtw_efuse {
u8 addr[ETH_ALEN];
u8 channel_plan;
u8 country_code[2];
+ u8 rf_board_option;
u8 rfe_option;
u8 thermal_meter;
u8 crystal_cap;
@@ -1047,6 +1279,7 @@ struct rtw_dev {
struct rtw_regulatory regd;
struct rtw_dm_info dm_info;
+ struct rtw_coex coex;
/* ensures exclusive access from mac80211 callbacks */
struct mutex mutex;
diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c
index 607bfa4..9ecd14fe 100644
--- a/drivers/net/wireless/realtek/rtw88/ps.c
+++ b/drivers/net/wireless/realtek/rtw88/ps.c
@@ -6,6 +6,7 @@
#include "fw.h"
#include "ps.h"
#include "mac.h"
+#include "coex.h"
#include "debug.h"
static int rtw_ips_pwr_up(struct rtw_dev *rtwdev)
@@ -26,6 +27,8 @@ int rtw_enter_ips(struct rtw_dev *rtwdev)
{
rtw_flag_set(rtwdev, RTW_FLAG_INACTIVE_PS);
+ rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER);
+
rtw_core_stop(rtwdev);
return 0;
@@ -53,6 +56,8 @@ int rtw_leave_ips(struct rtw_dev *rtwdev)
rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev);
+ rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
+
return 0;
}
@@ -67,6 +72,8 @@ static void rtw_leave_lps_core(struct rtw_dev *rtwdev)
rtw_fw_set_pwr_mode(rtwdev);
rtw_flag_clear(rtwdev, RTW_FLAG_LEISURE_PS);
+
+ rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE);
}
static void rtw_enter_lps_core(struct rtw_dev *rtwdev)
@@ -78,6 +85,8 @@ static void rtw_enter_lps_core(struct rtw_dev *rtwdev)
conf->rlbm = 1;
conf->smart_ps = 2;
+ rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE);
+
rtw_fw_set_pwr_mode(rtwdev);
rtw_flag_set(rtwdev, RTW_FLAG_LEISURE_PS);
}
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index e2628f0..0bd0717 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -37,17 +37,28 @@
#define REG_GPIO_MUXCFG 0x0040
#define BIT_FSPI_EN BIT(19)
+#define BIT_BT_AOD_GPIO3 BIT(9)
+#define BIT_BT_PTA_EN BIT(5)
#define BIT_WLRFE_4_5_EN BIT(2)
#define REG_LED_CFG 0x004C
#define BIT_LNAON_SEL_EN BIT(26)
#define BIT_PAPE_SEL_EN BIT(25)
+#define BIT_DPDT_WL_SEL BIT(24)
+#define BIT_DPDT_SEL_EN BIT(23)
#define REG_PAD_CTRL1 0x0064
#define BIT_PAPE_WLBT_SEL BIT(29)
#define BIT_LNAON_WLBT_SEL BIT(28)
+#define BIT_BTGP_JTAG_EN BIT(24)
+#define BIT_BTGP_SPI_EN BIT(20)
+#define BIT_LED1DIS BIT(15)
+#define BIT_SW_DPDT_SEL_DATA BIT(0)
#define REG_WL_BT_PWR_CTRL 0x0068
#define BIT_BT_FUNC_EN BIT(18)
#define BIT_BT_DIG_CLK_EN BIT(8)
+#define REG_SYS_SDIO_CTRL 0x0070
+#define BIT_DBG_GNT_WL_BT BIT(27)
+#define BIT_LTE_MUX_CTRL_PATH BIT(26)
#define REG_HCI_OPT_CTRL 0x0074
#define REG_MCUFW_CTRL 0x0080
@@ -70,6 +81,8 @@
#define FW_READY_MASK 0xffff
#define REG_WLRF1 0x00EC
+#define REG_WIFI_BT_INFO 0x00AA
+#define BIT_BT_INT_EN BIT(15)
#define REG_SYS_CFG1 0x00F0
#define BIT_RTL_ID BIT(23)
#define BIT_RF_TYPE_ID BIT(27)
@@ -187,6 +200,7 @@
#define REG_LIFETIME_EN 0x0426
#define BIT_BA_PARSER_EN BIT(5)
#define REG_SPEC_SIFS 0x0428
+#define REG_RETRY_LIMIT 0x042a
#define REG_DARFRC 0x0430
#define REG_DARFRCH 0x0434
#define REG_RARFRCH 0x043C
@@ -199,18 +213,25 @@
#define REG_AMPDU_MAX_TIME_V1 0x0455
#define REG_BCNQ1_BDNY_V1 0x0456
#define REG_TX_HANG_CTRL 0x045E
+#define BIT_EN_GNT_BT_AWAKE BIT(3)
#define BIT_EN_EOF_V1 BIT(2)
#define REG_DATA_SC 0x0483
#define REG_ARFR4 0x049C
+#define BIT_WL_RFK BIT(0)
#define REG_ARFRH4 0x04A0
#define REG_ARFR5 0x04A4
#define REG_ARFRH5 0x04A8
#define REG_SW_AMPDU_BURST_MODE_CTRL 0x04BC
#define BIT_PRE_TX_CMD BIT(6)
+#define REG_QUEUE_CTRL 0x04C6
+#define BIT_PTA_WL_TX_EN BIT(4)
+#define BIT_PTA_EDCCA_EN BIT(5)
#define REG_PROT_MODE_CTRL 0x04C8
#define REG_BAR_MODE_CTRL 0x04CC
#define REG_PRECNT_CTRL 0x04E5
+#define BIT_BTCCA_CTRL (BIT(0) | BIT(1))
#define BIT_EN_PRECNT BIT(11)
+#define REG_DUMMY_PAGE4_V1 0x04FC
#define REG_EDCA_VO_PARAM 0x0500
#define REG_EDCA_VI_PARAM 0x0504
@@ -297,11 +318,34 @@
#define REG_RXFLTMAP0 0x06A0
#define REG_RXFLTMAP1 0x06A2
#define REG_RXFLTMAP2 0x06A4
+#define REG_BT_COEX_TABLE0 0x06C0
+#define REG_BT_COEX_TABLE1 0x06C4
+#define REG_BT_COEX_BRK_TABLE 0x06C8
+#define REG_BT_COEX_TABLE_H 0x06CC
+#define REG_BT_COEX_TABLE_H1 0x06CD
+#define REG_BT_COEX_TABLE_H2 0x06CE
+#define REG_BT_COEX_TABLE_H3 0x06CF
#define REG_BBPSF_CTRL 0x06DC
+#define REG_BT_COEX_V2 0x0763
+#define BIT_GNT_BT_POLARITY BIT(4)
+#define BIT_LTE_COEX_EN BIT(7)
+#define REG_BT_STAT_CTRL 0x0778
+#define REG_BT_TDMA_TIME 0x0790
#define REG_WMAC_OPTION_FUNCTION 0x07D0
#define REG_WMAC_OPTION_FUNCTION_1 0x07D4
+#define REG_RX_GAIN_EN 0x081c
+
+#define REG_RFE_CTRL_E 0x0974
+
+#define REG_RFE_CTRL8 0x0cb4
+#define BIT_MASK_RFE_SEL89 GENMASK(7, 0)
+#define REG_RFE_INV8 0x0cbd
+#define BIT_MASK_RFE_INV89 GENMASK(1, 0)
+#define REG_RFE_INV16 0x0cbe
+#define BIT_RFE_BUF_EN BIT(3)
+
#define REG_ANAPAR_XTAL_0 0x1040
#define REG_CPU_DMEM_CON 0x1080
#define BIT_WL_PLATFORM_RST BIT(16)
@@ -407,15 +451,33 @@
#define LTECOEX_WRITE_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1
#define LTECOEX_READ_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1
+#define REG_IGN_GNT_BT1 0x1860
+
+#define REG_RFESEL_CTRL 0x1990
+
+#define REG_NOMASK_TXBT 0x1ca7
+#define REG_ANAPAR 0x1c30
+#define BIT_ANAPAR_BTPS BIT(22)
+#define REG_RSTB_SEL 0x1c38
+
+#define REG_IGN_GNTBT4 0x4160
+
+#define RF_MODOPT 0x01
#define RF_DTXLOK 0x08
#define RF_CFGCH 0x18
+#define RF_RCK 0x1d
#define RF_LUTWA 0x33
#define RF_LUTWD1 0x3e
#define RF_LUTWD0 0x3f
#define RF_XTALX2 0xb8
#define RF_MALSEL 0xbe
+#define RF_RCKD 0xde
#define RF_LUTDBG 0xdf
#define RF_LUTWE2 0xee
#define RF_LUTWE 0xef
+#define LTE_COEX_CTRL 0x38
+#define LTE_WL_TRX_CTRL 0xa0
+#define LTE_BT_TRX_CTRL 0xa4
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
index d61d534..568033a 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
@@ -3,6 +3,7 @@
*/
#include "main.h"
+#include "coex.h"
#include "fw.h"
#include "tx.h"
#include "rx.h"
@@ -31,6 +32,7 @@ static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
map = (struct rtw8822b_efuse *)log_map;
efuse->rfe_option = map->rfe_option;
+ efuse->rf_board_option = map->rf_board_option;
efuse->crystal_cap = map->xtal_k;
efuse->pa_type_2g = map->pa_type;
efuse->pa_type_5g = map->pa_type;
@@ -104,24 +106,6 @@ static void rtw8822b_phy_set_param(struct rtw_dev *rtwdev)
rtw_phy_init(rtwdev);
rtw8822b_phy_rfe_init(rtwdev);
-
- /* wifi path controller */
- rtw_write32_mask(rtwdev, 0x70, 0x4000000, 1);
- /* BB control */
- rtw_write32_mask(rtwdev, 0x4c, 0x01800000, 0x2);
- /* antenna mux switch */
- rtw_write8(rtwdev, 0x974, 0xff);
- rtw_write32_mask(rtwdev, 0x1990, 0x300, 0);
- rtw_write32_mask(rtwdev, 0xcbc, 0x80000, 0x0);
- /* SW control */
- rtw_write8(rtwdev, 0xcb4, 0x77);
- /* switch to WL side controller and gnt_wl gnt_bt debug signal */
- rtw_write32_mask(rtwdev, 0x70, 0xff000000, 0x0e);
- /* gnt_wl = 1, gnt_bt = 0 */
- rtw_write32(rtwdev, 0x1704, 0x7700);
- rtw_write32(rtwdev, 0x1700, 0xc00f0038);
- /* switch for WL 2G */
- rtw_write8(rtwdev, 0xcbd, 0x2);
}
#define WLAN_SLOT_TIME 0x09
@@ -960,6 +944,7 @@ static void rtw8822b_false_alarm_statistics(struct rtw_dev *rtwdev)
u32 cck_enable;
u32 cck_fa_cnt;
u32 ofdm_fa_cnt;
+ u32 crc32_cnt;
cck_enable = rtw_read32(rtwdev, 0x808) & BIT(28);
cck_fa_cnt = rtw_read16(rtwdev, 0xa5c);
@@ -970,6 +955,19 @@ static void rtw8822b_false_alarm_statistics(struct rtw_dev *rtwdev)
dm_info->total_fa_cnt = ofdm_fa_cnt;
dm_info->total_fa_cnt += cck_enable ? cck_fa_cnt : 0;
+ crc32_cnt = rtw_read32(rtwdev, 0xf04);
+ dm_info->cck_ok_cnt = crc32_cnt & 0xffff;
+ dm_info->cck_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
+ crc32_cnt = rtw_read32(rtwdev, 0xf14);
+ dm_info->ofdm_ok_cnt = crc32_cnt & 0xffff;
+ dm_info->ofdm_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
+ crc32_cnt = rtw_read32(rtwdev, 0xf10);
+ dm_info->ht_ok_cnt = crc32_cnt & 0xffff;
+ dm_info->ht_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
+ crc32_cnt = rtw_read32(rtwdev, 0xf0c);
+ dm_info->vht_ok_cnt = crc32_cnt & 0xffff;
+ dm_info->vht_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
+
rtw_write32_set(rtwdev, 0x9a4, BIT(17));
rtw_write32_clr(rtwdev, 0x9a4, BIT(17));
rtw_write32_clr(rtwdev, 0xa2c, BIT(15));
@@ -1003,6 +1001,254 @@ static void rtw8822b_do_iqk(struct rtw_dev *rtwdev)
counter, reload, ++do_iqk_cnt, iqk_fail_mask);
}
+static void rtw8822b_coex_cfg_init(struct rtw_dev *rtwdev)
+{
+ /* enable TBTT nterrupt */
+ rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+
+ /* BT report packet sample rate */
+ /* 0x790[5:0]=0x5 */
+ rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05);
+
+ /* enable BT counter statistics */
+ rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);
+
+ /* enable PTA (3-wire function form BT side) */
+ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
+ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3);
+
+ /* enable PTA (tx/rx signal form WiFi side) */
+ rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
+ /* wl tx signal to PTA not case EDCCA */
+ rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT_PTA_EDCCA_EN);
+ /* GNT_BT=1 while select both */
+ rtw_write8_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY);
+}
+
+static void rtw8822b_coex_cfg_ant_switch(struct rtw_dev *rtwdev,
+ u8 ctrl_type, u8 pos_type)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_coex_rfe *coex_rfe = &coex->rfe;
+ bool polarity_inverse;
+ u8 regval = 0;
+
+ if (((ctrl_type << 8) + pos_type) == coex_dm->cur_switch_status)
+ return;
+
+ coex_dm->cur_switch_status = (ctrl_type << 8) + pos_type;
+
+ if (coex_rfe->ant_switch_diversity &&
+ ctrl_type == COEX_SWITCH_CTRL_BY_BBSW)
+ ctrl_type = COEX_SWITCH_CTRL_BY_ANTDIV;
+
+ polarity_inverse = (coex_rfe->ant_switch_polarity == 1);
+
+ switch (ctrl_type) {
+ default:
+ case COEX_SWITCH_CTRL_BY_BBSW:
+ /* 0x4c[23] = 0 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x0);
+ /* 0x4c[24] = 1 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 3, BIT_DPDT_WL_SEL >> 24, 0x1);
+ /* BB SW, DPDT use RFE_ctrl8 and RFE_ctrl9 as ctrl pin */
+ rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_RFE_SEL89, 0x77);
+
+ if (pos_type == COEX_SWITCH_TO_WLG_BT) {
+ if (coex_rfe->rfe_module_type != 0x4 &&
+ coex_rfe->rfe_module_type != 0x2)
+ regval = 0x3;
+ else
+ regval = (!polarity_inverse ? 0x2 : 0x1);
+ } else if (pos_type == COEX_SWITCH_TO_WLG) {
+ regval = (!polarity_inverse ? 0x2 : 0x1);
+ } else {
+ regval = (!polarity_inverse ? 0x1 : 0x2);
+ }
+
+ rtw_write8_mask(rtwdev, REG_RFE_INV8, BIT_MASK_RFE_INV89, regval);
+ break;
+ case COEX_SWITCH_CTRL_BY_PTA:
+ /* 0x4c[23] = 0 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x0);
+ /* 0x4c[24] = 1 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 3, BIT_DPDT_WL_SEL >> 24, 0x1);
+ /* PTA, DPDT use RFE_ctrl8 and RFE_ctrl9 as ctrl pin */
+ rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_RFE_SEL89, 0x66);
+
+ regval = (!polarity_inverse ? 0x2 : 0x1);
+ rtw_write8_mask(rtwdev, REG_RFE_INV8, BIT_MASK_RFE_INV89, regval);
+ break;
+ case COEX_SWITCH_CTRL_BY_ANTDIV:
+ /* 0x4c[23] = 0 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x0);
+ /* 0x4c[24] = 1 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 3, BIT_DPDT_WL_SEL >> 24, 0x1);
+ rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_RFE_SEL89, 0x88);
+ break;
+ case COEX_SWITCH_CTRL_BY_MAC:
+ /* 0x4c[23] = 1 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x1);
+
+ regval = (!polarity_inverse ? 0x0 : 0x1);
+ rtw_write8_mask(rtwdev, REG_PAD_CTRL1, BIT_SW_DPDT_SEL_DATA, regval);
+ break;
+ case COEX_SWITCH_CTRL_BY_FW:
+ /* 0x4c[23] = 0 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x0);
+ /* 0x4c[24] = 1 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 3, BIT_DPDT_WL_SEL >> 24, 0x1);
+ break;
+ case COEX_SWITCH_CTRL_BY_BT:
+ /* 0x4c[23] = 0 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x0);
+ /* 0x4c[24] = 0 */
+ rtw_write8_mask(rtwdev, REG_LED_CFG + 3, BIT_DPDT_WL_SEL >> 24, 0x0);
+ break;
+ }
+}
+
+static void rtw8822b_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
+{
+}
+
+static void rtw8822b_coex_cfg_gnt_debug(struct rtw_dev *rtwdev)
+{
+ rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 2, BIT_BTGP_SPI_EN >> 16, 0);
+ rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 3, BIT_BTGP_JTAG_EN >> 24, 0);
+ rtw_write8_mask(rtwdev, REG_GPIO_MUXCFG + 2, BIT_FSPI_EN >> 16, 0);
+ rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 1, BIT_LED1DIS >> 8, 0);
+ rtw_write8_mask(rtwdev, REG_SYS_SDIO_CTRL + 3, BIT_DBG_GNT_WL_BT >> 24, 0);
+}
+
+static void rtw8822b_coex_cfg_rfe_type(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_rfe *coex_rfe = &coex->rfe;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ bool is_ext_fem = false;
+
+ coex_rfe->rfe_module_type = rtwdev->efuse.rfe_option;
+ coex_rfe->ant_switch_polarity = 0;
+ coex_rfe->ant_switch_diversity = false;
+ if (coex_rfe->rfe_module_type == 0x12 ||
+ coex_rfe->rfe_module_type == 0x15 ||
+ coex_rfe->rfe_module_type == 0x16)
+ coex_rfe->ant_switch_exist = false;
+ else
+ coex_rfe->ant_switch_exist = true;
+
+ if (coex_rfe->rfe_module_type == 2 ||
+ coex_rfe->rfe_module_type == 4) {
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_EXTFEM, true);
+ is_ext_fem = true;
+ } else {
+ rtw_coex_write_scbd(rtwdev, COEX_SCBD_EXTFEM, false);
+ }
+
+ coex_rfe->wlg_at_btg = false;
+
+ if (efuse->share_ant &&
+ coex_rfe->ant_switch_exist && !is_ext_fem)
+ coex_rfe->ant_switch_with_bt = true;
+ else
+ coex_rfe->ant_switch_with_bt = false;
+
+ /* Ext switch buffer mux */
+ rtw_write8(rtwdev, REG_RFE_CTRL_E, 0xff);
+ rtw_write8_mask(rtwdev, REG_RFESEL_CTRL + 1, 0x3, 0x0);
+ rtw_write8_mask(rtwdev, REG_RFE_INV16, BIT_RFE_BUF_EN, 0x0);
+
+ /* Disable LTE Coex Function in WiFi side */
+ rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, BIT_LTE_COEX_EN, 0);
+
+ /* BTC_CTT_WL_VS_LTE */
+ rtw_coex_write_indirect_reg(rtwdev, LTE_WL_TRX_CTRL, MASKLWORD, 0xffff);
+
+ /* BTC_CTT_BT_VS_LTE */
+ rtw_coex_write_indirect_reg(rtwdev, LTE_BT_TRX_CTRL, MASKLWORD, 0xffff);
+}
+
+static void rtw8822b_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ static const u16 reg_addr[] = {0xc58, 0xe58};
+ static const u8 wl_tx_power[] = {0xd8, 0xd4, 0xd0, 0xcc, 0xc8};
+ u8 i, pwr;
+
+ if (wl_pwr == coex_dm->cur_wl_pwr_lvl)
+ return;
+
+ coex_dm->cur_wl_pwr_lvl = wl_pwr;
+
+ if (coex_dm->cur_wl_pwr_lvl >= ARRAY_SIZE(wl_tx_power))
+ coex_dm->cur_wl_pwr_lvl = ARRAY_SIZE(wl_tx_power) - 1;
+
+ pwr = wl_tx_power[coex_dm->cur_wl_pwr_lvl];
+
+ for (i = 0; i < ARRAY_SIZE(reg_addr); i++)
+ rtw_write8_mask(rtwdev, reg_addr[i], 0xff, pwr);
+}
+
+static void rtw8822b_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ /* WL Rx Low gain on */
+ static const u32 wl_rx_low_gain_on[] = {
+ 0xff000003, 0xbd120003, 0xbe100003, 0xbf080003, 0xbf060003,
+ 0xbf050003, 0xbc140003, 0xbb160003, 0xba180003, 0xb91a0003,
+ 0xb81c0003, 0xb71e0003, 0xb4200003, 0xb5220003, 0xb4240003,
+ 0xb3260003, 0xb2280003, 0xb12a0003, 0xb02c0003, 0xaf2e0003,
+ 0xae300003, 0xad320003, 0xac340003, 0xab360003, 0x8d380003,
+ 0x8c3a0003, 0x8b3c0003, 0x8a3e0003, 0x6e400003, 0x6d420003,
+ 0x6c440003, 0x6b460003, 0x6a480003, 0x694a0003, 0x684c0003,
+ 0x674e0003, 0x66500003, 0x65520003, 0x64540003, 0x64560003,
+ 0x007e0403
+ };
+
+ /* WL Rx Low gain off */
+ static const u32 wl_rx_low_gain_off[] = {
+ 0xff000003, 0xf4120003, 0xf5100003, 0xf60e0003, 0xf70c0003,
+ 0xf80a0003, 0xf3140003, 0xf2160003, 0xf1180003, 0xf01a0003,
+ 0xef1c0003, 0xee1e0003, 0xed200003, 0xec220003, 0xeb240003,
+ 0xea260003, 0xe9280003, 0xe82a0003, 0xe72c0003, 0xe62e0003,
+ 0xe5300003, 0xc8320003, 0xc7340003, 0xc6360003, 0xc5380003,
+ 0xc43a0003, 0xc33c0003, 0xc23e0003, 0xc1400003, 0xc0420003,
+ 0xa5440003, 0xa4460003, 0xa3480003, 0xa24a0003, 0xa14c0003,
+ 0x834e0003, 0x82500003, 0x81520003, 0x80540003, 0x65560003,
+ 0x007e0403
+ };
+ u8 i;
+
+ if (low_gain == coex_dm->cur_wl_rx_low_gain_en)
+ return;
+
+ coex_dm->cur_wl_rx_low_gain_en = low_gain;
+
+ if (coex_dm->cur_wl_rx_low_gain_en) {
+ for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_on); i++)
+ rtw_write32(rtwdev, REG_RX_GAIN_EN, wl_rx_low_gain_on[i]);
+
+ /* set Rx filter corner RCK offset */
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCKD, 0x2, 0x1);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCK, 0x3f, 0x3f);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCKD, 0x2, 0x1);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCK, 0x3f, 0x3f);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_off); i++)
+ rtw_write32(rtwdev, 0x81c, wl_rx_low_gain_off[i]);
+
+ /* set Rx filter corner RCK offset */
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCK, 0x3f, 0x4);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RCKD, 0x2, 0x0);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCK, 0x3f, 0x4);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_RCKD, 0x2, 0x0);
+ }
+}
+
static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = {
{0x0086,
RTW_PWR_CUT_ALL_MSK,
@@ -1549,8 +1795,160 @@ static struct rtw_chip_ops rtw8822b_ops = {
.cfg_ldo25 = rtw8822b_cfg_ldo25,
.false_alarm_statistics = rtw8822b_false_alarm_statistics,
.do_iqk = rtw8822b_do_iqk,
+
+ .coex_set_init = rtw8822b_coex_cfg_init,
+ .coex_set_ant_switch = rtw8822b_coex_cfg_ant_switch,
+ .coex_set_gnt_fix = rtw8822b_coex_cfg_gnt_fix,
+ .coex_set_gnt_debug = rtw8822b_coex_cfg_gnt_debug,
+ .coex_set_rfe_type = rtw8822b_coex_cfg_rfe_type,
+ .coex_set_wl_tx_power = rtw8822b_coex_cfg_wl_tx_power,
+ .coex_set_wl_rx_gain = rtw8822b_coex_cfg_wl_rx_gain,
+};
+
+/* Shared-Antenna Coex Table */
+static const struct coex_table_para table_sant_8822b[] = {
+ {0xffffffff, 0xffffffff}, /* case-0 */
+ {0x55555555, 0x55555555},
+ {0x66555555, 0x66555555},
+ {0xaaaaaaaa, 0xaaaaaaaa},
+ {0x5a5a5a5a, 0x5a5a5a5a},
+ {0xfafafafa, 0xfafafafa}, /* case-5 */
+ {0x6a5a6a5a, 0xaaaaaaaa},
+ {0x6a5a56aa, 0x6a5a56aa},
+ {0x6a5a5a5a, 0x6a5a5a5a},
+ {0x66555555, 0x5a5a5a5a},
+ {0x66555555, 0x6a5a5a5a}, /* case-10 */
+ {0x66555555, 0xfafafafa},
+ {0x66555555, 0x6a5a5aaa},
+ {0x66555555, 0x5aaa5aaa},
+ {0x66555555, 0xaaaa5aaa},
+ {0x66555555, 0xaaaaaaaa}, /* case-15 */
+ {0xffff55ff, 0xfafafafa},
+ {0xffff55ff, 0x6afa5afa},
+ {0xaaffffaa, 0xfafafafa},
+ {0xaa5555aa, 0x5a5a5a5a},
+ {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */
+ {0xaa5555aa, 0xaaaaaaaa},
+ {0xffffffff, 0x5a5a5a5a},
+ {0xffffffff, 0x6a5a5a5a},
+ {0xffffffff, 0x55555555},
+ {0xffffffff, 0x6a5a5aaa}, /* case-25 */
+ {0x55555555, 0x5a5a5a5a},
+ {0x55555555, 0xaaaaaaaa},
+ {0x55555555, 0x6a5a6a5a},
+ {0x66556655, 0x66556655}
+};
+
+/* Non-Shared-Antenna Coex Table */
+static const struct coex_table_para table_nsant_8822b[] = {
+ {0xffffffff, 0xffffffff}, /* case-100 */
+ {0x55555555, 0x55555555},
+ {0x66555555, 0x66555555},
+ {0xaaaaaaaa, 0xaaaaaaaa},
+ {0x5a5a5a5a, 0x5a5a5a5a},
+ {0xfafafafa, 0xfafafafa}, /* case-105 */
+ {0x5afa5afa, 0x5afa5afa},
+ {0x55555555, 0xfafafafa},
+ {0x66555555, 0xfafafafa},
+ {0x66555555, 0x5a5a5a5a},
+ {0x66555555, 0x6a5a5a5a}, /* case-110 */
+ {0x66555555, 0xaaaaaaaa},
+ {0xffff55ff, 0xfafafafa},
+ {0xffff55ff, 0x5afa5afa},
+ {0xffff55ff, 0xaaaaaaaa},
+ {0xaaffffaa, 0xfafafafa}, /* case-115 */
+ {0xaaffffaa, 0x5afa5afa},
+ {0xaaffffaa, 0xaaaaaaaa},
+ {0xffffffff, 0xfafafafa},
+ {0xffffffff, 0x5afa5afa},
+ {0xffffffff, 0xaaaaaaaa}, /* case-120 */
+ {0x55ff55ff, 0x5afa5afa},
+ {0x55ff55ff, 0xaaaaaaaa},
+ {0x55ff55ff, 0x55ff55ff}
};
+/* Shared-Antenna TDMA */
+static const struct coex_tdma_para tdma_sant_8822b[] = {
+ { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */
+ { {0x61, 0x45, 0x03, 0x11, 0x11} },
+ { {0x61, 0x3a, 0x03, 0x11, 0x11} },
+ { {0x61, 0x30, 0x03, 0x11, 0x11} },
+ { {0x61, 0x20, 0x03, 0x11, 0x11} },
+ { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-5 */
+ { {0x61, 0x45, 0x03, 0x11, 0x10} },
+ { {0x61, 0x3a, 0x03, 0x11, 0x10} },
+ { {0x61, 0x30, 0x03, 0x11, 0x10} },
+ { {0x61, 0x20, 0x03, 0x11, 0x10} },
+ { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */
+ { {0x61, 0x08, 0x03, 0x11, 0x14} },
+ { {0x61, 0x08, 0x03, 0x10, 0x14} },
+ { {0x51, 0x08, 0x03, 0x10, 0x54} },
+ { {0x51, 0x08, 0x03, 0x10, 0x55} },
+ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */
+ { {0x51, 0x45, 0x03, 0x10, 0x10} },
+ { {0x51, 0x3a, 0x03, 0x10, 0x50} },
+ { {0x51, 0x30, 0x03, 0x10, 0x50} },
+ { {0x51, 0x20, 0x03, 0x10, 0x50} },
+ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-20 */
+ { {0x51, 0x4a, 0x03, 0x10, 0x50} },
+ { {0x51, 0x0c, 0x03, 0x10, 0x54} },
+ { {0x55, 0x08, 0x03, 0x10, 0x54} },
+ { {0x65, 0x10, 0x03, 0x11, 0x11} },
+ { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */
+ { {0x51, 0x08, 0x03, 0x10, 0x50} }
+};
+
+/* Non-Shared-Antenna TDMA */
+static const struct coex_tdma_para tdma_nsant_8822b[] = {
+ { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-100 */
+ { {0x61, 0x45, 0x03, 0x11, 0x11} },
+ { {0x61, 0x3a, 0x03, 0x11, 0x11} },
+ { {0x61, 0x30, 0x03, 0x11, 0x11} },
+ { {0x61, 0x20, 0x03, 0x11, 0x11} },
+ { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-105 */
+ { {0x61, 0x45, 0x03, 0x11, 0x10} },
+ { {0x61, 0x3a, 0x03, 0x11, 0x10} },
+ { {0x61, 0x30, 0x03, 0x11, 0x10} },
+ { {0x61, 0x20, 0x03, 0x11, 0x10} },
+ { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-110 */
+ { {0x61, 0x08, 0x03, 0x11, 0x14} },
+ { {0x61, 0x08, 0x03, 0x10, 0x14} },
+ { {0x51, 0x08, 0x03, 0x10, 0x54} },
+ { {0x51, 0x08, 0x03, 0x10, 0x55} },
+ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-115 */
+ { {0x51, 0x45, 0x03, 0x10, 0x50} },
+ { {0x51, 0x3a, 0x03, 0x10, 0x50} },
+ { {0x51, 0x30, 0x03, 0x10, 0x50} },
+ { {0x51, 0x20, 0x03, 0x10, 0x50} },
+ { {0x51, 0x10, 0x03, 0x10, 0x50} } /* case-120 */
+};
+
+/* rssi in percentage % (dbm = % - 100) */
+static const u8 wl_rssi_step_8822b[] = {60, 50, 44, 30};
+static const u8 bt_rssi_step_8822b[] = {30, 30, 30, 30};
+static const struct coex_5g_afh_map afh_5g_8822b[] = { {0, 0, 0} };
+
+/* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */
+static const struct coex_rf_para rf_para_tx_8822b[] = {
+ {0, 0, false, 7}, /* for normal */
+ {0, 16, false, 7}, /* for WL-CPT */
+ {4, 0, true, 1},
+ {3, 6, true, 1},
+ {2, 9, true, 1},
+ {1, 13, true, 1}
+};
+
+static const struct coex_rf_para rf_para_rx_8822b[] = {
+ {0, 0, false, 7}, /* for normal */
+ {0, 16, false, 7}, /* for WL-CPT */
+ {4, 0, true, 1},
+ {3, 6, true, 1},
+ {2, 9, true, 1},
+ {1, 13, true, 1}
+};
+
+static_assert(ARRAY_SIZE(rf_para_tx_8822b) == ARRAY_SIZE(rf_para_rx_8822b));
+
struct rtw_chip_info rtw8822b_hw_spec = {
.ops = &rtw8822b_ops,
.id = RTW_CHIP_TYPE_8822B,
@@ -1588,6 +1986,32 @@ struct rtw_chip_info rtw8822b_hw_spec = {
.rf_tbl = {&rtw8822b_rf_a_tbl, &rtw8822b_rf_b_tbl},
.rfe_defs = rtw8822b_rfe_defs,
.rfe_defs_size = ARRAY_SIZE(rtw8822b_rfe_defs),
+
+ .coex_para_ver = 0x19062706,
+ .bt_desired_ver = 0x6,
+ .scbd_support = true,
+ .new_scbd10_def = false,
+ .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
+ .bt_rssi_type = COEX_BTRSSI_RATIO,
+ .ant_isolation = 15,
+ .rssi_tolerance = 2,
+ .wl_rssi_step = wl_rssi_step_8822b,
+ .bt_rssi_step = bt_rssi_step_8822b,
+ .table_sant_num = ARRAY_SIZE(table_sant_8822b),
+ .table_sant = table_sant_8822b,
+ .table_nsant_num = ARRAY_SIZE(table_nsant_8822b),
+ .table_nsant = table_nsant_8822b,
+ .tdma_sant_num = ARRAY_SIZE(tdma_sant_8822b),
+ .tdma_sant = tdma_sant_8822b,
+ .tdma_nsant_num = ARRAY_SIZE(tdma_nsant_8822b),
+ .tdma_nsant = tdma_nsant_8822b,
+ .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8822b),
+ .wl_rf_para_tx = rf_para_tx_8822b,
+ .wl_rf_para_rx = rf_para_rx_8822b,
+ .bt_afh_span_bw20 = 0x24,
+ .bt_afh_span_bw40 = 0x36,
+ .afh_5g_num = ARRAY_SIZE(afh_5g_8822b),
+ .afh_5g = afh_5g_8822b,
};
EXPORT_SYMBOL(rtw8822b_hw_spec);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index f6214ff..207f64c 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -3,6 +3,7 @@
*/
#include "main.h"
+#include "coex.h"
#include "fw.h"
#include "tx.h"
#include "rx.h"
@@ -31,6 +32,7 @@ static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
map = (struct rtw8822c_efuse *)log_map;
efuse->rfe_option = map->rfe_option;
+ efuse->rf_board_option = map->rf_board_option;
efuse->crystal_cap = map->xtal_k;
efuse->channel_plan = map->channel_plan;
efuse->country_code[0] = map->country_code[0];
@@ -1041,12 +1043,6 @@ static void rtw8822c_phy_set_param(struct rtw_dev *rtwdev)
dm_info->cck_gi_l_bnd = ((cck_gi_l_bnd_msb << 4) | (cck_gi_l_bnd_lsb));
rtw8822c_rf_init(rtwdev);
- /* wifi path controller */
- rtw_write32_mask(rtwdev, 0x70, 0xff000000, 0x0e);
- rtw_write32_mask(rtwdev, 0x1704, 0xffffffff, 0x7700);
- rtw_write32_mask(rtwdev, 0x1700, 0xffffffff, 0xc00f0038);
- rtw_write32_mask(rtwdev, 0x6c0, 0xffffffff, 0xaaaaaaaa);
- rtw_write32_mask(rtwdev, 0x6c4, 0xffffffff, 0xaaaaaaaa);
}
#define WLAN_TXQ_RPT_EN 0x1F
@@ -1817,6 +1813,7 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev)
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u32 cck_enable;
u32 cck_fa_cnt;
+ u32 crc32_cnt;
u32 ofdm_fa_cnt;
u32 ofdm_fa_cnt1, ofdm_fa_cnt2, ofdm_fa_cnt3, ofdm_fa_cnt4, ofdm_fa_cnt5;
u16 parity_fail, rate_illegal, crc8_fail, mcs_fail, sb_search_fail,
@@ -1848,6 +1845,19 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev)
dm_info->total_fa_cnt = ofdm_fa_cnt;
dm_info->total_fa_cnt += cck_enable ? cck_fa_cnt : 0;
+ crc32_cnt = rtw_read32(rtwdev, 0x2c04);
+ dm_info->cck_ok_cnt = crc32_cnt & 0xffff;
+ dm_info->cck_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
+ crc32_cnt = rtw_read32(rtwdev, 0x2c14);
+ dm_info->ofdm_ok_cnt = crc32_cnt & 0xffff;
+ dm_info->ofdm_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
+ crc32_cnt = rtw_read32(rtwdev, 0x2c10);
+ dm_info->ht_ok_cnt = crc32_cnt & 0xffff;
+ dm_info->ht_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
+ crc32_cnt = rtw_read32(rtwdev, 0x2c0c);
+ dm_info->vht_ok_cnt = crc32_cnt & 0xffff;
+ dm_info->vht_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
+
rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 0);
rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 2);
rtw_write32_mask(rtwdev, REG_CCANRX, BIT_OFDM_FA_RST, 0);
@@ -1864,6 +1874,161 @@ static void rtw8822c_do_iqk(struct rtw_dev *rtwdev)
{
}
+/* for coex */
+static void rtw8822c_coex_cfg_init(struct rtw_dev *rtwdev)
+{
+ /* enable TBTT nterrupt */
+ rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+
+ /* BT report packet sample rate */
+ /* 0x790[5:0]=0x5 */
+ rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05);
+
+ /* enable BT counter statistics */
+ rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);
+
+ /* enable PTA (3-wire function form BT side) */
+ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
+ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3);
+
+ /* enable PTA (tx/rx signal form WiFi side) */
+ rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
+ /* wl tx signal to PTA not case EDCCA */
+ rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT_PTA_EDCCA_EN);
+ /* GNT_BT=1 while select both */
+ rtw_write8_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY);
+ /* BT_CCA = ~GNT_WL_BB, (not or GNT_BT_BB, LTE_Rx */
+ rtw_write8_clr(rtwdev, REG_DUMMY_PAGE4_V1, BIT_BTCCA_CTRL);
+
+ /* to avoid RF parameter error */
+ rtw_write_rf(rtwdev, RF_PATH_B, 0x1, 0xfffff, 0x40000);
+}
+
+static void rtw8822c_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_stat *coex_stat = &coex->stat;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ u32 rf_0x1;
+
+ if (coex_stat->gnt_workaround_state == coex_stat->wl_coex_mode)
+ return;
+
+ coex_stat->gnt_workaround_state = coex_stat->wl_coex_mode;
+
+ if ((coex_stat->kt_ver == 0 && coex->under_5g) || coex->freerun)
+ rf_0x1 = 0x40021;
+ else
+ rf_0x1 = 0x40000;
+
+ /* BT at S1 for Shared-Ant */
+ if (efuse->share_ant)
+ rf_0x1 |= BIT(13);
+
+ rtw_write_rf(rtwdev, RF_PATH_B, 0x1, 0xfffff, rf_0x1);
+
+ /* WL-S0 2G RF TRX cannot be masked by GNT_BT
+ * enable "WLS0 BB chage RF mode if GNT_BT = 1" for shared-antenna type
+ * disable:0x1860[3] = 1, enable:0x1860[3] = 0
+ *
+ * enable "DAC off if GNT_WL = 0" for non-shared-antenna
+ * disable 0x1c30[22] = 0,
+ * enable: 0x1c30[22] = 1, 0x1c38[12] = 0, 0x1c38[28] = 1
+ *
+ * disable WL-S1 BB chage RF mode if GNT_BT
+ * since RF TRx mask can do it
+ */
+ rtw_write8_mask(rtwdev, 0x1c32, BIT(6), 1);
+ rtw_write8_mask(rtwdev, 0x1c39, BIT(4), 0);
+ rtw_write8_mask(rtwdev, 0x1c3b, BIT(4), 1);
+ rtw_write8_mask(rtwdev, 0x4160, BIT(3), 1);
+
+ /* disable WL-S0 BB chage RF mode if wifi is at 5G,
+ * or antenna path is separated
+ */
+ if (coex_stat->wl_coex_mode == COEX_WLINK_5G ||
+ coex->under_5g || !efuse->share_ant) {
+ if (coex_stat->kt_ver >= 3) {
+ rtw_write8_mask(rtwdev, 0x1860, BIT(3), 0);
+ rtw_write8_mask(rtwdev, 0x1ca7, BIT(3), 1);
+ } else {
+ rtw_write8_mask(rtwdev, 0x1860, BIT(3), 1);
+ }
+ } else {
+ /* shared-antenna */
+ rtw_write8_mask(rtwdev, 0x1860, BIT(3), 0);
+ if (coex_stat->kt_ver >= 3)
+ rtw_write8_mask(rtwdev, 0x1ca7, BIT(3), 0);
+ }
+}
+
+static void rtw8822c_coex_cfg_gnt_debug(struct rtw_dev *rtwdev)
+{
+ rtw_write8_mask(rtwdev, 0x66, BIT(4), 0);
+ rtw_write8_mask(rtwdev, 0x67, BIT(0), 0);
+ rtw_write8_mask(rtwdev, 0x42, BIT(3), 0);
+ rtw_write8_mask(rtwdev, 0x65, BIT(7), 0);
+ rtw_write8_mask(rtwdev, 0x73, BIT(3), 0);
+}
+
+static void rtw8822c_coex_cfg_rfe_type(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_rfe *coex_rfe = &coex->rfe;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+
+ coex_rfe->rfe_module_type = rtwdev->efuse.rfe_option;
+ coex_rfe->ant_switch_polarity = 0;
+ coex_rfe->ant_switch_exist = false;
+ coex_rfe->ant_switch_with_bt = false;
+ coex_rfe->ant_switch_diversity = false;
+
+ if (efuse->share_ant)
+ coex_rfe->wlg_at_btg = true;
+ else
+ coex_rfe->wlg_at_btg = false;
+
+ /* disable LTE coex in wifi side */
+ rtw_coex_write_indirect_reg(rtwdev, 0x38, BIT_LTE_COEX_EN, 0x0);
+ rtw_coex_write_indirect_reg(rtwdev, 0xa0, MASKLWORD, 0xffff);
+ rtw_coex_write_indirect_reg(rtwdev, 0xa4, MASKLWORD, 0xffff);
+}
+
+static void rtw8822c_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+
+ if (wl_pwr == coex_dm->cur_wl_pwr_lvl)
+ return;
+
+ coex_dm->cur_wl_pwr_lvl = wl_pwr;
+}
+
+static void rtw8822c_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+
+ if (low_gain == coex_dm->cur_wl_rx_low_gain_en)
+ return;
+
+ coex_dm->cur_wl_rx_low_gain_en = low_gain;
+
+ if (coex_dm->cur_wl_rx_low_gain_en) {
+ /* set Rx filter corner RCK offset */
+ rtw_write_rf(rtwdev, RF_PATH_A, 0xde, 0xfffff, 0x22);
+ rtw_write_rf(rtwdev, RF_PATH_A, 0x1d, 0xfffff, 0x36);
+ rtw_write_rf(rtwdev, RF_PATH_B, 0xde, 0xfffff, 0x22);
+ rtw_write_rf(rtwdev, RF_PATH_B, 0x1d, 0xfffff, 0x36);
+ } else {
+ /* set Rx filter corner RCK offset */
+ rtw_write_rf(rtwdev, RF_PATH_A, 0xde, 0xfffff, 0x20);
+ rtw_write_rf(rtwdev, RF_PATH_A, 0x1d, 0xfffff, 0x0);
+ rtw_write_rf(rtwdev, RF_PATH_B, 0x1d, 0xfffff, 0x0);
+ }
+}
+
static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = {
{0x0086,
RTW_PWR_CUT_ALL_MSK,
@@ -2232,8 +2397,160 @@ static struct rtw_chip_ops rtw8822c_ops = {
.cfg_ldo25 = rtw8822c_cfg_ldo25,
.false_alarm_statistics = rtw8822c_false_alarm_statistics,
.do_iqk = rtw8822c_do_iqk,
+
+ .coex_set_init = rtw8822c_coex_cfg_init,
+ .coex_set_ant_switch = NULL,
+ .coex_set_gnt_fix = rtw8822c_coex_cfg_gnt_fix,
+ .coex_set_gnt_debug = rtw8822c_coex_cfg_gnt_debug,
+ .coex_set_rfe_type = rtw8822c_coex_cfg_rfe_type,
+ .coex_set_wl_tx_power = rtw8822c_coex_cfg_wl_tx_power,
+ .coex_set_wl_rx_gain = rtw8822c_coex_cfg_wl_rx_gain,
+};
+
+/* Shared-Antenna Coex Table */
+static const struct coex_table_para table_sant_8822c[] = {
+ {0xffffffff, 0xffffffff}, /* case-0 */
+ {0x55555555, 0x55555555},
+ {0x66555555, 0x66555555},
+ {0xaaaaaaaa, 0xaaaaaaaa},
+ {0x5a5a5a5a, 0x5a5a5a5a},
+ {0xfafafafa, 0xfafafafa}, /* case-5 */
+ {0x6a5a6a5a, 0xaaaaaaaa},
+ {0x6a5a56aa, 0x6a5a56aa},
+ {0x6a5a5a5a, 0x6a5a5a5a},
+ {0x66555555, 0x5a5a5a5a},
+ {0x66555555, 0x6a5a5a5a}, /* case-10 */
+ {0x66555555, 0xfafafafa},
+ {0x66555555, 0x6a5a5aaa},
+ {0x66555555, 0x5aaa5aaa},
+ {0x66555555, 0xaaaa5aaa},
+ {0x66555555, 0xaaaaaaaa}, /* case-15 */
+ {0xffff55ff, 0xfafafafa},
+ {0xffff55ff, 0x6afa5afa},
+ {0xaaffffaa, 0xfafafafa},
+ {0xaa5555aa, 0x5a5a5a5a},
+ {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */
+ {0xaa5555aa, 0xaaaaaaaa},
+ {0xffffffff, 0x5a5a5a5a},
+ {0xffffffff, 0x6a5a5a5a},
+ {0xffffffff, 0x55555555},
+ {0xffffffff, 0x6a5a5aaa}, /* case-25 */
+ {0x55555555, 0x5a5a5a5a},
+ {0x55555555, 0xaaaaaaaa},
+ {0x55555555, 0x6a5a6a5a},
+ {0x66556655, 0x66556655}
+};
+
+/* Non-Shared-Antenna Coex Table */
+static const struct coex_table_para table_nsant_8822c[] = {
+ {0xffffffff, 0xffffffff}, /* case-100 */
+ {0x55555555, 0x55555555},
+ {0x66555555, 0x66555555},
+ {0xaaaaaaaa, 0xaaaaaaaa},
+ {0x5a5a5a5a, 0x5a5a5a5a},
+ {0xfafafafa, 0xfafafafa}, /* case-105 */
+ {0x5afa5afa, 0x5afa5afa},
+ {0x55555555, 0xfafafafa},
+ {0x66555555, 0xfafafafa},
+ {0x66555555, 0x5a5a5a5a},
+ {0x66555555, 0x6a5a5a5a}, /* case-110 */
+ {0x66555555, 0xaaaaaaaa},
+ {0xffff55ff, 0xfafafafa},
+ {0xffff55ff, 0x5afa5afa},
+ {0xffff55ff, 0xaaaaaaaa},
+ {0xaaffffaa, 0xfafafafa}, /* case-115 */
+ {0xaaffffaa, 0x5afa5afa},
+ {0xaaffffaa, 0xaaaaaaaa},
+ {0xffffffff, 0xfafafafa},
+ {0xffffffff, 0x5afa5afa},
+ {0xffffffff, 0xaaaaaaaa},/* case-120 */
+ {0x55ff55ff, 0x5afa5afa},
+ {0x55ff55ff, 0xaaaaaaaa},
+ {0x55ff55ff, 0x55ff55ff}
+};
+
+/* Shared-Antenna TDMA */
+static const struct coex_tdma_para tdma_sant_8822c[] = {
+ { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */
+ { {0x61, 0x45, 0x03, 0x11, 0x11} },
+ { {0x61, 0x3a, 0x03, 0x11, 0x11} },
+ { {0x61, 0x30, 0x03, 0x11, 0x11} },
+ { {0x61, 0x20, 0x03, 0x11, 0x11} },
+ { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-5 */
+ { {0x61, 0x45, 0x03, 0x11, 0x10} },
+ { {0x61, 0x3a, 0x03, 0x11, 0x10} },
+ { {0x61, 0x30, 0x03, 0x11, 0x10} },
+ { {0x61, 0x20, 0x03, 0x11, 0x10} },
+ { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */
+ { {0x61, 0x08, 0x03, 0x11, 0x14} },
+ { {0x61, 0x08, 0x03, 0x10, 0x14} },
+ { {0x51, 0x08, 0x03, 0x10, 0x54} },
+ { {0x51, 0x08, 0x03, 0x10, 0x55} },
+ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */
+ { {0x51, 0x45, 0x03, 0x10, 0x10} },
+ { {0x51, 0x3a, 0x03, 0x10, 0x50} },
+ { {0x51, 0x30, 0x03, 0x10, 0x50} },
+ { {0x51, 0x20, 0x03, 0x10, 0x50} },
+ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-20 */
+ { {0x51, 0x4a, 0x03, 0x10, 0x50} },
+ { {0x51, 0x0c, 0x03, 0x10, 0x54} },
+ { {0x55, 0x08, 0x03, 0x10, 0x54} },
+ { {0x65, 0x10, 0x03, 0x11, 0x11} },
+ { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */
+ { {0x51, 0x08, 0x03, 0x10, 0x50} }
};
+/* Non-Shared-Antenna TDMA */
+static const struct coex_tdma_para tdma_nsant_8822c[] = {
+ { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-100 */
+ { {0x61, 0x45, 0x03, 0x11, 0x11} },
+ { {0x61, 0x3a, 0x03, 0x11, 0x11} },
+ { {0x61, 0x30, 0x03, 0x11, 0x11} },
+ { {0x61, 0x20, 0x03, 0x11, 0x11} },
+ { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-105 */
+ { {0x61, 0x45, 0x03, 0x11, 0x10} },
+ { {0x61, 0x3a, 0x03, 0x11, 0x10} },
+ { {0x61, 0x30, 0x03, 0x11, 0x10} },
+ { {0x61, 0x20, 0x03, 0x11, 0x10} },
+ { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-110 */
+ { {0x61, 0x08, 0x03, 0x11, 0x14} },
+ { {0x61, 0x08, 0x03, 0x10, 0x14} },
+ { {0x51, 0x08, 0x03, 0x10, 0x54} },
+ { {0x51, 0x08, 0x03, 0x10, 0x55} },
+ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-115 */
+ { {0x51, 0x45, 0x03, 0x10, 0x50} },
+ { {0x51, 0x3a, 0x03, 0x10, 0x50} },
+ { {0x51, 0x30, 0x03, 0x10, 0x50} },
+ { {0x51, 0x20, 0x03, 0x10, 0x50} },
+ { {0x51, 0x10, 0x03, 0x10, 0x50} } /* case-120 */
+};
+
+/* rssi in percentage % (dbm = % - 100) */
+static const u8 wl_rssi_step_8822c[] = {60, 50, 44, 30};
+static const u8 bt_rssi_step_8822c[] = {8, 15, 20, 25};
+static const struct coex_5g_afh_map afh_5g_8822c[] = { {0, 0, 0} };
+
+/* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */
+static const struct coex_rf_para rf_para_tx_8822c[] = {
+ {0, 0, false, 7}, /* for normal */
+ {0, 16, false, 7}, /* for WL-CPT */
+ {8, 17, true, 4},
+ {7, 18, true, 4},
+ {6, 19, true, 4},
+ {5, 20, true, 4}
+};
+
+static const struct coex_rf_para rf_para_rx_8822c[] = {
+ {0, 0, false, 7}, /* for normal */
+ {0, 16, false, 7}, /* for WL-CPT */
+ {3, 24, true, 5},
+ {2, 26, true, 5},
+ {1, 27, true, 5},
+ {0, 28, true, 5}
+};
+
+static_assert(ARRAY_SIZE(rf_para_tx_8822c) == ARRAY_SIZE(rf_para_rx_8822c));
+
struct rtw_chip_info rtw8822c_hw_spec = {
.ops = &rtw8822c_ops,
.id = RTW_CHIP_TYPE_8822C,
@@ -2272,6 +2589,32 @@ struct rtw_chip_info rtw8822c_hw_spec = {
.rf_tbl = {&rtw8822c_rf_a_tbl, &rtw8822c_rf_b_tbl},
.rfe_defs = rtw8822c_rfe_defs,
.rfe_defs_size = ARRAY_SIZE(rtw8822c_rfe_defs),
+
+ .coex_para_ver = 0x19062706,
+ .bt_desired_ver = 0x6,
+ .scbd_support = true,
+ .new_scbd10_def = true,
+ .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
+ .bt_rssi_type = COEX_BTRSSI_DBM,
+ .ant_isolation = 15,
+ .rssi_tolerance = 2,
+ .wl_rssi_step = wl_rssi_step_8822c,
+ .bt_rssi_step = bt_rssi_step_8822c,
+ .table_sant_num = ARRAY_SIZE(table_sant_8822c),
+ .table_sant = table_sant_8822c,
+ .table_nsant_num = ARRAY_SIZE(table_nsant_8822c),
+ .table_nsant = table_nsant_8822c,
+ .tdma_sant_num = ARRAY_SIZE(tdma_sant_8822c),
+ .tdma_sant = tdma_sant_8822c,
+ .tdma_nsant_num = ARRAY_SIZE(tdma_nsant_8822c),
+ .tdma_nsant = tdma_nsant_8822c,
+ .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8822c),
+ .wl_rf_para_tx = rf_para_tx_8822c,
+ .wl_rf_para_rx = rf_para_rx_8822c,
+ .bt_afh_span_bw20 = 0x24,
+ .bt_afh_span_bw40 = 0x36,
+ .afh_5g_num = ARRAY_SIZE(afh_5g_8822c),
+ .afh_5g = afh_5g_8822c,
};
EXPORT_SYMBOL(rtw8822c_hw_spec);
--
2.7.4
^ permalink raw reply related
* [PATCH v2 4/5] rtw88: enclose c2h cmd handle with mutex
From: yhchuang @ 2019-07-25 2:53 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, sgruszka, briannorris
In-Reply-To: <1564023211-3138-1-git-send-email-yhchuang@realtek.com>
From: Yan-Hsuan Chuang <yhchuang@realtek.com>
C2H commands that cannot be handled in IRQ context should
be protected by rtwdev->mutex. Because they might have a
sequece of hardware operations that does not want to be
interfered.
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---
v1 -> v2
no change
drivers/net/wireless/realtek/rtw88/fw.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 3c4dcb7..3b06f71 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -36,6 +36,8 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
len = skb->len - pkt_offset - 2;
+ mutex_lock(&rtwdev->mutex);
+
switch (c2h->id) {
case C2H_HALMAC:
rtw_fw_c2h_cmd_handle_ext(rtwdev, skb);
@@ -43,6 +45,8 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
default:
break;
}
+
+ mutex_unlock(&rtwdev->mutex);
}
void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
--
2.7.4
^ permalink raw reply related
* [PATCH v2 3/5] rtw88: allow c2h operation in irq context
From: yhchuang @ 2019-07-25 2:53 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, sgruszka, briannorris
In-Reply-To: <1564023211-3138-1-git-send-email-yhchuang@realtek.com>
From: Yan-Hsuan Chuang <yhchuang@realtek.com>
Some of the c2h operations are small and can be done
under interrupt context. For the rest that requires
more operations or can go sleep, enqueue onto c2h queue.
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---
v1 -> v2
rebase onto the latest wireless-drivers-next
fixed conflicts in pci.c
drivers/net/wireless/realtek/rtw88/fw.c | 27 ++++++++++++++++++++++++---
drivers/net/wireless/realtek/rtw88/fw.h | 2 ++
drivers/net/wireless/realtek/rtw88/pci.c | 6 ++----
3 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 62847797..3c4dcb7 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -36,9 +36,6 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
len = skb->len - pkt_offset - 2;
- rtw_dbg(rtwdev, RTW_DBG_FW, "recv C2H, id=0x%02x, seq=0x%02x, len=%d\n",
- c2h->id, c2h->seq, len);
-
switch (c2h->id) {
case C2H_HALMAC:
rtw_fw_c2h_cmd_handle_ext(rtwdev, skb);
@@ -48,6 +45,30 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
}
}
+void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
+ struct sk_buff *skb)
+{
+ struct rtw_c2h_cmd *c2h;
+ u8 len;
+
+ c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
+ len = skb->len - pkt_offset - 2;
+ *((u32 *)skb->cb) = pkt_offset;
+
+ rtw_dbg(rtwdev, RTW_DBG_FW, "recv C2H, id=0x%02x, seq=0x%02x, len=%d\n",
+ c2h->id, c2h->seq, len);
+
+ switch (c2h->id) {
+ default:
+ /* pass offset for further operation */
+ *((u32 *)skb->cb) = pkt_offset;
+ skb_queue_tail(&rtwdev->c2h_queue, skb);
+ ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work);
+ break;
+ }
+}
+EXPORT_SYMBOL(rtw_fw_c2h_cmd_rx_irqsafe);
+
static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
u8 *h2c)
{
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index 7034663..67f6cf7 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -200,6 +200,8 @@ static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb)
return (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
}
+void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
+ struct sk_buff *skb);
void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
void rtw_fw_send_general_info(struct rtw_dev *rtwdev);
void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index 23dd06a..4776195 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -8,6 +8,7 @@
#include "pci.h"
#include "tx.h"
#include "rx.h"
+#include "fw.h"
#include "debug.h"
static u32 rtw_pci_tx_queue_idx_addr[] = {
@@ -822,10 +823,7 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
skb_put_data(new, skb->data, new_len);
if (pkt_stat.is_c2h) {
- /* pass rx_desc & offset for further operation */
- *((u32 *)new->cb) = pkt_offset;
- skb_queue_tail(&rtwdev->c2h_queue, new);
- ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work);
+ rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, new);
} else {
/* remove rx_desc */
skb_pull(new, pkt_offset);
--
2.7.4
^ permalink raw reply related
* [PATCH v2 2/5] rtw88: check efuse for BT FT S1
From: yhchuang @ 2019-07-25 2:53 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, sgruszka, briannorris
In-Reply-To: <1564023211-3138-1-git-send-email-yhchuang@realtek.com>
From: Yan-Hsuan Chuang <yhchuang@realtek.com>
Some modules might not have full programed efuse.
Driver should check the BT FT S1 type to know that
if BT has been programed. If BT is not programed,
throw a warning to notify that this module is not
capable of working with WiFi + BT concurrently.
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---
v1 -> v2
no change
drivers/net/wireless/realtek/rtw88/efuse.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw88/efuse.c b/drivers/net/wireless/realtek/rtw88/efuse.c
index 66e56f3..82aa26a 100644
--- a/drivers/net/wireless/realtek/rtw88/efuse.c
+++ b/drivers/net/wireless/realtek/rtw88/efuse.c
@@ -8,6 +8,11 @@
#include "debug.h"
#define RTW_EFUSE_BANK_WIFI 0x0
+#define RTW_EFUSE_BANK_BT 0x1
+
+#define EFUSE_BT_S1_ADDR 0x4a
+#define EFUSE_BT_S1_TYPE1 0xff
+#define EFUSE_BT_S1_TYPE2 0x00
static void switch_efuse_bank(struct rtw_dev *rtwdev, u8 efuse_bank)
{
@@ -89,6 +94,7 @@ static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
u32 efuse_ctl;
u32 addr;
u32 cnt;
+ u8 ft_ver;
switch_efuse_bank(rtwdev, RTW_EFUSE_BANK_WIFI);
@@ -113,6 +119,24 @@ static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
*(map + addr) = (u8)(efuse_ctl & BIT_MASK_EF_DATA);
}
+ /* verify BT FT S1 efuse type */
+ switch_efuse_bank(rtwdev, RTW_EFUSE_BANK_BT);
+
+ efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL);
+ efuse_ctl &= ~(BIT_MASK_EF_DATA | BITS_EF_ADDR);
+ efuse_ctl |= (EFUSE_BT_S1_ADDR & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR;
+ rtw_write32(rtwdev, REG_EFUSE_CTRL, efuse_ctl & (~BIT_EF_FLAG));
+
+ if (!check_hw_ready(rtwdev, REG_EFUSE_CTRL, BIT_EF_FLAG, 0x1)) {
+ rtw_err(rtwdev, "failed to read BT efuse\n");
+ return -EBUSY;
+ }
+
+ efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL);
+ ft_ver = (u8)(efuse_ctl & BIT_MASK_EF_DATA);
+ if (ft_ver == EFUSE_BT_S1_TYPE1 || ft_ver == EFUSE_BT_S1_TYPE2)
+ rtw_warn(rtwdev, "BT S1 not calibrated, not recommended to verify BT for this module\n");
+
return 0;
}
--
2.7.4
^ permalink raw reply related
* [PATCH v2 0/5] rtw88: add support for BT co-existence mechanism
From: yhchuang @ 2019-07-25 2:53 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, sgruszka, briannorris
From: Yan-Hsuan Chuang <yhchuang@realtek.com>
This patch set mainly adds a BT co-existence mechanism, which
helps WiFi device to work with BT device concurrently without
interfering each other. For Realtek's WiFi/BT combo devices,
the co-existence mechanism is on the WiFi side.
The first two patches "rtw88: switch specified efuse bank" and
"rtw88: check efuse for BT FT S1" aim to check if the device
is able to run with WiFi + BT, because some of the earlier
devices manufactured are in development for testing. These
device hence did not program the efuse for BT. Without being
programed, some of the hardware parameters are incorrect.
The rest of the patches add BTcoex support. BTcoex needs to
wake up events that is waiting for some C2H reported in IRQ
context, so these C2H skbs do not required to be queued into
workqueues to be processed. What we need to do is to simply
wake it uin IRQ context.
And actually C2H workqueue context should be protected by
rtwdev->mutex lock to perform some hardware operations
against mac80211 callbacks.
The final patch contains the most of the BTcoex logic.
It is not that complicated, just to gather information and
make decision on WiFi driver side. What makes the code so
much is that the mechanism needs to take care of a lot of
WiFi/BT combinations. Such as if WiFi is at 2G or is having
a lot of traffic or is connecting to AP. And BT has many
profiles such as A2DP/HID/PAN or it is slave or not.
v1 -> v2
rebase onto the latest wireless-drivers-next
the conflicts is in pci.c with patch
"rtw88: pci: Rearrange the memory usage for skb in RX ISR"
Yan-Hsuan Chuang (5):
rtw88: switch specified efuse bank
rtw88: check efuse for BT FT S1
rtw88: allow c2h operation in irq context
rtw88: enclose c2h cmd handle with mutex
rtw88: add BT co-existence support
drivers/net/wireless/realtek/rtw88/Makefile | 1 +
drivers/net/wireless/realtek/rtw88/coex.c | 2462 +++++++++++++++++++++++++
drivers/net/wireless/realtek/rtw88/coex.h | 363 ++++
drivers/net/wireless/realtek/rtw88/efuse.c | 30 +-
drivers/net/wireless/realtek/rtw88/fw.c | 135 +-
drivers/net/wireless/realtek/rtw88/fw.h | 73 +
drivers/net/wireless/realtek/rtw88/mac80211.c | 19 +
drivers/net/wireless/realtek/rtw88/main.c | 45 +-
drivers/net/wireless/realtek/rtw88/main.h | 233 +++
drivers/net/wireless/realtek/rtw88/pci.c | 6 +-
drivers/net/wireless/realtek/rtw88/ps.c | 9 +
drivers/net/wireless/realtek/rtw88/reg.h | 62 +
drivers/net/wireless/realtek/rtw88/rtw8822b.c | 460 ++++-
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 355 +++-
14 files changed, 4216 insertions(+), 37 deletions(-)
create mode 100644 drivers/net/wireless/realtek/rtw88/coex.c
create mode 100644 drivers/net/wireless/realtek/rtw88/coex.h
--
2.7.4
^ permalink raw reply
* [PATCH v2 1/5] rtw88: switch specified efuse bank
From: yhchuang @ 2019-07-25 2:53 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, sgruszka, briannorris
In-Reply-To: <1564023211-3138-1-git-send-email-yhchuang@realtek.com>
From: Yan-Hsuan Chuang <yhchuang@realtek.com>
Allows to switch different type of efuse bank by passing
the bank type to swtich to.
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---
v1 -> v2
no change
drivers/net/wireless/realtek/rtw88/efuse.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/efuse.c b/drivers/net/wireless/realtek/rtw88/efuse.c
index 212c837..66e56f3 100644
--- a/drivers/net/wireless/realtek/rtw88/efuse.c
+++ b/drivers/net/wireless/realtek/rtw88/efuse.c
@@ -9,10 +9,10 @@
#define RTW_EFUSE_BANK_WIFI 0x0
-static void switch_efuse_bank(struct rtw_dev *rtwdev)
+static void switch_efuse_bank(struct rtw_dev *rtwdev, u8 efuse_bank)
{
rtw_write32_mask(rtwdev, REG_LDO_EFUSE_CTRL, BIT_MASK_EFUSE_BANK_SEL,
- RTW_EFUSE_BANK_WIFI);
+ efuse_bank);
}
#define invalid_efuse_header(hdr1, hdr2) \
@@ -90,7 +90,7 @@ static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
u32 addr;
u32 cnt;
- switch_efuse_bank(rtwdev);
+ switch_efuse_bank(rtwdev, RTW_EFUSE_BANK_WIFI);
/* disable 2.5V LDO */
chip->ops->cfg_ldo25(rtwdev, false);
--
2.7.4
^ permalink raw reply related
* [PATCH v2] staging: wilc1000: Merge memcpy + le32_to_cpus to get_unaligned_le32
From: Chuhong Yuan @ 2019-07-25 2:52 UTC (permalink / raw)
Cc: Adham Abozaeid, Ajay Singh, Greg Kroah-Hartman, linux-wireless,
devel, linux-kernel, Chuhong Yuan
Merge the combo use of memcpy and le32_to_cpus.
Use get_unaligned_le32 instead.
This simplifies the code.
Signed-off-by: Chuhong Yuan <hslester96@gmail.com>
---
Changes in v2:
- Merge the previous two patches which
have the same subject line.
drivers/staging/wilc1000/wilc_mon.c | 3 +--
drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 3 +--
drivers/staging/wilc1000/wilc_wlan.c | 9 +++------
3 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/staging/wilc1000/wilc_mon.c b/drivers/staging/wilc1000/wilc_mon.c
index 7d7933d40924..d6f14f69ad64 100644
--- a/drivers/staging/wilc1000/wilc_mon.c
+++ b/drivers/staging/wilc1000/wilc_mon.c
@@ -35,8 +35,7 @@ void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size)
return;
/* Get WILC header */
- memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
- le32_to_cpus(&header);
+ header = get_unaligned_le32(buff - HOST_HDR_OFFSET);
/*
* The packet offset field contain info about what type of management
* the frame we are dealing with and ack status
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index d72fdd333050..12fb4add05ec 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -1038,8 +1038,7 @@ void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)
s32 freq;
__le16 fc;
- memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
- le32_to_cpus(&header);
+ header = get_unaligned_le32(buff - HOST_HDR_OFFSET);
pkt_offset = GET_PKT_OFFSET(header);
if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index d46876edcfeb..7d438ae90c3e 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -703,8 +703,7 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)
do {
buff_ptr = buffer + offset;
- memcpy(&header, buff_ptr, 4);
- le32_to_cpus(&header);
+ header = get_unaligned_le32(buff_ptr);
is_cfg_packet = (header >> 31) & 0x1;
pkt_offset = (header >> 22) & 0x1ff;
@@ -874,10 +873,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
offset = 0;
do {
- memcpy(&addr, &buffer[offset], 4);
- memcpy(&size, &buffer[offset + 4], 4);
- le32_to_cpus(&addr);
- le32_to_cpus(&size);
+ addr = get_unaligned_le32(&buffer[offset]);
+ size = get_unaligned_le32(&buffer[offset + 4]);
acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
offset += 8;
while (((int)size) && (offset < buffer_size)) {
--
2.20.1
^ permalink raw reply related
* Re: [PATCH] rtlwifi: remove unneeded function _rtl_dump_channel_map()
From: Pkshih @ 2019-07-25 2:50 UTC (permalink / raw)
To: yuehaibing@huawei.com, kvalo@codeaurora.org
Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org, davem@davemloft.net
In-Reply-To: <20190724141020.58800-1-yuehaibing@huawei.com>
On Wed, 2019-07-24 at 22:10 +0800, YueHaibing wrote:
> Now _rtl_dump_channel_map() does not do any actual
> thing using the channel. So remove it.
>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
> drivers/net/wireless/realtek/rtlwifi/regd.c | 18 ------------------
> 1 file changed, 18 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c
> b/drivers/net/wireless/realtek/rtlwifi/regd.c
> index 6ccb5b9..c10432c 100644
> --- a/drivers/net/wireless/realtek/rtlwifi/regd.c
> +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c
> @@ -276,22 +276,6 @@ static void _rtl_reg_apply_world_flags(struct wiphy
> *wiphy,
> return;
> }
>
> -static void _rtl_dump_channel_map(struct wiphy *wiphy)
> -{
> - enum nl80211_band band;
> - struct ieee80211_supported_band *sband;
> - struct ieee80211_channel *ch;
> - unsigned int i;
> -
> - for (band = 0; band < NUM_NL80211_BANDS; band++) {
> - if (!wiphy->bands[band])
> - continue;
> - sband = wiphy->bands[band];
> - for (i = 0; i < sband->n_channels; i++)
> - ch = &sband->channels[i];
> - }
> -}
> -
> static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
> struct regulatory_request *request,
> struct rtl_regulatory *reg)
> @@ -309,8 +293,6 @@ static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
> break;
> }
>
> - _rtl_dump_channel_map(wiphy);
> -
> return 0;
> }
>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
^ permalink raw reply
* [PATCH v2] staging: wilc1000: Merge memcpy + le32_to_cpus to get_unaligned_le32
From: Chuhong Yuan @ 2019-07-25 2:46 UTC (permalink / raw)
Cc: Adham Abozaeid, Ajay Singh, Greg Kroah-Hartman, linux-wireless,
devel, linux-kernel, Chuhong Yuan
Merge the combo use of memcpy and le32_to_cpus.
Use get_unaligned_le32 instead.
This simplifies the code.
Signed-off-by: Chuhong Yuan <hslester96@gmail.com>
---
drivers/staging/wilc1000/wilc_mon.c | 3 +--
drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 3 +--
drivers/staging/wilc1000/wilc_wlan.c | 9 +++------
3 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/staging/wilc1000/wilc_mon.c b/drivers/staging/wilc1000/wilc_mon.c
index 7d7933d40924..d6f14f69ad64 100644
--- a/drivers/staging/wilc1000/wilc_mon.c
+++ b/drivers/staging/wilc1000/wilc_mon.c
@@ -35,8 +35,7 @@ void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size)
return;
/* Get WILC header */
- memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
- le32_to_cpus(&header);
+ header = get_unaligned_le32(buff - HOST_HDR_OFFSET);
/*
* The packet offset field contain info about what type of management
* the frame we are dealing with and ack status
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index d72fdd333050..12fb4add05ec 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -1038,8 +1038,7 @@ void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)
s32 freq;
__le16 fc;
- memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
- le32_to_cpus(&header);
+ header = get_unaligned_le32(buff - HOST_HDR_OFFSET);
pkt_offset = GET_PKT_OFFSET(header);
if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index d46876edcfeb..7d438ae90c3e 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -703,8 +703,7 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)
do {
buff_ptr = buffer + offset;
- memcpy(&header, buff_ptr, 4);
- le32_to_cpus(&header);
+ header = get_unaligned_le32(buff_ptr);
is_cfg_packet = (header >> 31) & 0x1;
pkt_offset = (header >> 22) & 0x1ff;
@@ -874,10 +873,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
offset = 0;
do {
- memcpy(&addr, &buffer[offset], 4);
- memcpy(&size, &buffer[offset + 4], 4);
- le32_to_cpus(&addr);
- le32_to_cpus(&size);
+ addr = get_unaligned_le32(&buffer[offset]);
+ size = get_unaligned_le32(&buffer[offset + 4]);
acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
offset += 8;
while (((int)size) && (offset < buffer_size)) {
--
2.20.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox