-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathmac.c
More file actions
7269 lines (6051 loc) · 225 KB
/
mac.c
File metadata and controls
7269 lines (6051 loc) · 225 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright 2017-2023 Morse Micro
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
*/
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/crc32.h>
#include <net/mac80211.h>
#include <asm/div64.h>
#include <linux/kernel.h>
#include "morse.h"
#include "mac.h"
#include "s1g_ies.h"
#include "bus.h"
#include "debug.h"
#include "command.h"
#include "vendor.h"
#include "vendor_ie.h"
#include "mac_config.h"
#include "dot11ah/dot11ah.h"
#include "skb_header.h"
#include "ps.h"
#include "raw.h"
#include "twt.h"
#include "mbssid.h"
#include "watchdog.h"
#include "firmware.h"
#include "offload.h"
#include "mesh.h"
#ifdef CONFIG_MORSE_RC
#include "rc.h"
#else
#include "minstrel_rc.h"
#endif
#include "ipmon.h"
#include "wiphy.h"
#include "mesh.h"
#include "pv1.h"
#include "peer.h"
#ifdef CONFIG_MORSE_HW_TRACE
#include "hw_trace.h"
#endif
#include "led.h"
#include "monitor.h"
#define RATE(rate100m, _flags) { \
.bitrate = (rate100m), \
.flags = (_flags), \
.hw_value = 0, \
}
#define CHAN5GHZ(channel, chflags) { \
.band = NL80211_BAND_5GHZ, \
.center_freq = 5000 + 5 * (channel), \
.hw_value = (channel), \
.flags = chflags, \
.max_antenna_gain = 0, \
.max_power = 22, \
}
#define STA_PRIV_TIMEOUT_MSEC (2000)
/* Supported TX/RX MCS mask: 0x03FF -> Each bit represents MCS0-9 */
#define DEFAULT_MCS_RATE_MASK IEEE80211_HT_MCS_RX_HIGHEST_MASK
/* Mask for MCS0-7 */
#define MCS_RATE_MASK_0_TO_7 GENMASK(7, 0)
/* Offset for MCS 8 and 9 bits */
#define MCS_RATE_MASK_8_TO_9_OFFSET (8)
/* Max 32 for legacy BA. 8 for 1MHZ NDP BA. 16 for 2+MHZ NDP BA */
#define DOT11AH_BA_MAX_MPDU_PER_AMPDU (32)
/* Default alpha-2 code */
#define USER_ASSIGNED_ALPHA "ZZ"
/** When automatically trying MCS0 before MCS10, this is how many MCS0 attempts to make */
#define MCS0_BEFORE_MCS10_COUNT (1)
/* Arbitrary size limit for the filter command address list, to ensure that the command
* does not exceed page/MTU size. This will be far greater than the number of filters
* supported by the firmware.
*/
#define MCAST_FILTER_COUNT_MAX (1024 / sizeof(filter->addr_list[0]))
/* Calculation of average RSSI */
#define CALC_AVG_RSSI(_avg, _sample) ((((_avg) * 9 + (_sample)) / 10))
#define MORSE_ECSA_DBG(_m, _f, _a...) morse_dbg(FEATURE_ID_ECSA, _m, _f, ##_a)
#define MORSE_ECSA_INFO(_m, _f, _a...) morse_info(FEATURE_ID_ECSA, _m, _f, ##_a)
#define MORSE_ECSA_WARN(_m, _f, _a...) morse_warn(FEATURE_ID_ECSA, _m, _f, ##_a)
#define MORSE_ECSA_ERR(_m, _f, _a...) morse_err(FEATURE_ID_ECSA, _m, _f, ##_a)
/**
* Interval in milliseconds at which a work queue is scheduled to evaluate the rate
* to be used for multicast packets transmission
*/
#define MULTICAST_TX_RATE_EVAL_WORK_PERIOD_MS 60000
#define MORSE_HEALTH_CHECK_RETRIES 1
enum dot11ah_powersave_mode {
POWERSAVE_MODE_DISABLED = 0x00,
POWERSAVE_MODE_PROTOCOL_ENABLED = 0x01,
POWERSAVE_MODE_FULLY_ENABLED = 0x02,
POWERSAVE_MODE_UNKNOWN = 0xFF
};
enum morse_mac_mcs10_mode {
MCS10_MODE_DISABLED = 0x00,
MCS10_MODE_FORCED = 0x01,
MCS10_MODE_AUTO = 0x02
};
/* Custom Module parameters */
/* On chip hardware encryption can be disabled through modparam */
static bool no_hwcrypt;
module_param(no_hwcrypt, bool, 0644);
MODULE_PARM_DESC(no_hwcrypt, "Disable on-chip hardware encryption");
/* TX/RX MCS mask. Default 0x3FF limits max MCS to 9 for both Tx and Rx. */
static uint mcs_mask __read_mostly = DEFAULT_MCS_RATE_MASK;
module_param(mcs_mask, uint, 0644);
MODULE_PARM_DESC(mcs_mask, "Supported MCS mask, e.g. MCS0-2 use mask 0x07");
/**
* Set the MCS10 configuration
* 0 - MCS10 disabled
* 1 - MCS10 replaces MCS0
* 2 - Initally try MCS0 and then MCS10
*/
static enum morse_mac_mcs10_mode mcs10_mode __read_mostly = MCS10_MODE_DISABLED;
module_param(mcs10_mode, uint, 0644);
MODULE_PARM_DESC(mcs10_mode, "MCS10 mode");
/* Enable/Disable channel survey */
static bool enable_survey __read_mostly = ENABLE_SURVEY_DEFAULT;
module_param(enable_survey, bool, 0644);
MODULE_PARM_DESC(enable_survey, "Enable channel survey");
/* Enable/Disable Subband transmission */
static enum morse_mac_subbands_mode
enable_subbands __read_mostly = SUBBANDS_MODE_ENABLED;
module_param(enable_subbands, uint, 0644);
MODULE_PARM_DESC(enable_subbands, "Enable subband transmission");
/* Enable/Disable Powersave */
static enum dot11ah_powersave_mode enable_ps __read_mostly = CONFIG_MORSE_POWERSAVE_MODE;
module_param(enable_ps, uint, 0644);
MODULE_PARM_DESC(enable_ps, "Enable PS");
/* Enable/Disable Powersave */
static bool enable_dynamic_ps_offload __read_mostly = true;
module_param(enable_dynamic_ps_offload, bool, 0644);
MODULE_PARM_DESC(enable_dynamic_ps_offload, "Enable dynamic PS firmware offload");
/*
* When set to a value greater than 0, Thin LMAC Mode is enabled.
*/
static bool thin_lmac __read_mostly;
module_param(thin_lmac, bool, 0644);
MODULE_PARM_DESC(thin_lmac, "Thin LMAC mode");
/*
* When set to a value greater than 0, Virtual Station Test Mode is enabled, allowing up to
* virtual_sta_max virtual interfaces to be configured in STA mode for emulating multiple physical
* stations.
*/
static u32 virtual_sta_max __read_mostly;
module_param(virtual_sta_max, uint, 0644);
MODULE_PARM_DESC(virtual_sta_max, "Virtual STA test mode (max virtual STAs or 0 to disable)");
/* Enable/disable MBSSID IE addition in beacon/probe response */
static bool enable_mbssid_ie __read_mostly;
module_param(enable_mbssid_ie, bool, 0644);
MODULE_PARM_DESC(enable_mbssid_ie, "Enable MBSSID IE support in beacon and probe responses");
/* Allow/Disallow rate control to use SGI */
static bool enable_sgi_rc __read_mostly = true;
module_param(enable_sgi_rc, bool, 0644);
MODULE_PARM_DESC(enable_sgi_rc, "Enable SGI use in rate control");
/* Enable/Disable broadcasting travelling pilot support */
static bool enable_trav_pilot __read_mostly = true;
module_param(enable_trav_pilot, bool, 0644);
MODULE_PARM_DESC(enable_trav_pilot, "Enable travelling pilots");
/* Enable/Disable RTS/CTS for 8MHz (Disabled by default) */
static bool enable_rts_8mhz __read_mostly;
module_param(enable_rts_8mhz, bool, 0644);
MODULE_PARM_DESC(enable_rts_8mhz, "Enable RTS/CTS protection for 8MHz");
/* Use CTS-to-self in place of RTS/CTS */
static bool enable_cts_to_self __read_mostly;
module_param(enable_cts_to_self, bool, 0644);
MODULE_PARM_DESC(enable_cts_to_self, "Use CTS-to-self in place of RTS/CTS");
/* Parse the regulatory domain, 2 char ISO-Alpha2 */
static char country[MORSE_COUNTRY_LEN] = CONFIG_MORSE_COUNTRY;
module_param_string(country, country, sizeof(country), 0644);
MODULE_PARM_DESC(country,
"The ISO/IEC alpha2 country code for the country in which this device is currently operating.");
/* Enable/Disable watchdog support */
static bool enable_watchdog __read_mostly = ENABLE_WATCHDOG_DEFAULT;
module_param(enable_watchdog, bool, 0644);
MODULE_PARM_DESC(enable_watchdog, "Enable watchdog");
/* Set watchdog interval. User can update the watchdog interval in run time */
static uint watchdog_interval_secs __read_mostly = 30;
module_param(watchdog_interval_secs, uint, 0644);
MODULE_PARM_DESC(watchdog_interval_secs, "Watchdog interval in seconds");
/* Enable/Disable watchdog reset */
static bool enable_watchdog_reset __read_mostly;
module_param(enable_watchdog_reset, bool, 0644);
MODULE_PARM_DESC(enable_watchdog_reset, "Enable driver reset from watchdog");
/* Set limit on rate chain: could be 1, 2, 3 or 4 */
static uint max_rates __read_mostly = INIT_MAX_RATES_NUM;
module_param(max_rates, uint, 0644);
MODULE_PARM_DESC(max_rates, "Maximum number of rates to try");
/* Set maximum rate attempts, could be 1, 2, 3 or 4 */
static uint max_rate_tries __read_mostly = 1;
module_param(max_rate_tries, uint, 0644);
MODULE_PARM_DESC(max_rate_tries, "Maximum retries per rate");
/* Set maximum aggregation count */
static uint max_aggregation_count __read_mostly;
module_param(max_aggregation_count, uint, 0644);
MODULE_PARM_DESC(max_aggregation_count, "Maximum number of aggregated packets we can receive");
/* Enable/Disable RAW */
static bool enable_raw __read_mostly = true;
module_param(enable_raw, bool, 0644);
MODULE_PARM_DESC(enable_raw, "Enable RAW");
/* Enable/Disable mac80211 pull interface for airtime fairness */
static bool enable_airtime_fairness __read_mostly;
module_param(enable_airtime_fairness, bool, 0644);
MODULE_PARM_DESC(enable_airtime_fairness, "Enable mac80211 pull interface for airtime fairness");
/* Enable/disable the mac802.11 connection monitor */
static bool enable_mac80211_connection_monitor __read_mostly;
module_param(enable_mac80211_connection_monitor, bool, 0644);
MODULE_PARM_DESC(enable_mac80211_connection_monitor, "Enable mac80211 connection monitor");
/* Enable/disable the TWT feature */
static bool enable_twt __read_mostly = true;
module_param(enable_twt, bool, 0644);
MODULE_PARM_DESC(enable_twt, "Enable TWT support");
/* Maximum TX power (default) */
static int tx_max_power_mbm __read_mostly = 2200;
module_param(tx_max_power_mbm, int, 0644);
MODULE_PARM_DESC(tx_max_power_mbm, "Maximum transmitted power in mbm");
/* Set maximum multicast frames after DTIM (0 - Do not limit) */
static uint max_mc_frames __read_mostly = MORSE_MAX_MC_FRAMES_AFTER_DTIM;
module_param(max_mc_frames, uint, 0644);
MODULE_PARM_DESC(max_mc_frames, "Maximum multicast frames after DTIM (0 for unlimited)");
/* Enable CAC (Centralized Authentication Control) (AP mode only) */
static bool enable_cac __read_mostly;
module_param(enable_cac, bool, 0644);
MODULE_PARM_DESC(enable_cac, "Enable Centralized Authentication Control (CAC)");
/* Enable Monitoring of Beacon Change Seq (STA mode only) */
static bool enable_bcn_change_seq_monitor __read_mostly;
module_param(enable_bcn_change_seq_monitor, bool, 0644);
MODULE_PARM_DESC(enable_bcn_change_seq_monitor,
"Enable monitoring of Change Sequence field in S1G Beacon");
/* Enable/Disable FW ARP response offloading */
static bool enable_arp_offload __read_mostly = ENABLE_ARP_OFFLOAD_DEFAULT;
module_param(enable_arp_offload, bool, 0644);
MODULE_PARM_DESC(enable_arp_offload, "Enable ARP offload");
static bool enable_dhcpc_offload __read_mostly = ENABLE_DHCP_OFFLOAD_DEFAULT;
module_param(enable_dhcpc_offload, bool, 0644);
MODULE_PARM_DESC(enable_dhcpc_offload, "Enable DHCP client offload");
/* Enable/Disable FW IBSS Probe Req Filtering */
bool enable_ibss_probe_filtering __read_mostly = true;
module_param(enable_ibss_probe_filtering, bool, 0644);
MODULE_PARM_DESC(enable_ibss_probe_filtering, "Enable IBSS probe request filtering in firmware");
char dhcpc_lease_update_script[DHCPC_LEASE_UPDATE_SCRIPT_NAME_SIZE_MAX] =
"/morse/scripts/dhcpc_update.sh";
module_param_string(dhcpc_lease_update_script, dhcpc_lease_update_script,
sizeof(dhcpc_lease_update_script), 0644);
MODULE_PARM_DESC(dhcpc_lease_update_script, "Path to script called on DHCP lease updates");
/* Enable/Disable automatic duty cycle based on regulatory domain */
static bool enable_auto_duty_cycle __read_mostly = true;
module_param(enable_auto_duty_cycle, bool, 0644);
MODULE_PARM_DESC(enable_auto_duty_cycle, "Enable automatic duty cycling setting");
/**
* Configure the duty cycle mode of operation when enabled.
* 0 - SPREAD mode (default)
* 1 - BURST mode
*/
static enum morse_cmd_duty_cycle_mode duty_cycle_mode
__read_mostly = MORSE_CMD_DUTY_CYCLE_MODE_SPREAD;
module_param(duty_cycle_mode, uint, 0644);
MODULE_PARM_DESC(duty_cycle_mode, "Duty cycle mode when automatic duty cycling enabled");
/** Default Duty Cycle probe retry threshold */
#define MORSE_DUTY_CYCLE_PROBE_RETRY_THRESHOLD (2500)
/** Maximum Duty Cycle probe retry threshold */
#define MORSE_DUTY_CYCLE_PROBE_RETRY_THRESHOLD_MAX (10000)
/**
* Duty Cycle threshold at or below which retries will be disabled for probe requests and responses.
* The value is in 100ths of a percent, between 1 and 10000. E.g. 2500 is 25%.
* A value of 10000 disables all probe request/response retries.
*/
static int duty_cycle_probe_retry_threshold __read_mostly = MORSE_DUTY_CYCLE_PROBE_RETRY_THRESHOLD;
module_param(duty_cycle_probe_retry_threshold, uint, 0644);
MODULE_PARM_DESC(duty_cycle_probe_retry_threshold,
"Duty Cycle threshold at which to disable retries for probe requests and responses");
/* Enable/Disable automatic minimum packet spacing configuration based on regulatory domain */
static bool enable_auto_mpsw __read_mostly = true;
module_param(enable_auto_mpsw, bool, 0644);
MODULE_PARM_DESC(enable_auto_mpsw, "Enable automatic minimum packet spacing window setting");
/* Enable/disable FullMAC mode */
static bool enable_wiphy;
module_param(enable_wiphy, bool, 0644);
MODULE_PARM_DESC(enable_wiphy, "Enable FullMAC (Wiphy) interface");
/* OCS type */
uint ocs_type __read_mostly = MORSE_CMD_OCS_TYPE_RAW;
module_param(ocs_type, uint, 0644);
MODULE_PARM_DESC(ocs_type, "OCS Type (0: use QoS Null frames, 1: use RAW)");
/* Enable/Disable multicast whitelisting */
bool enable_mcast_whitelist __read_mostly = true;
module_param(enable_mcast_whitelist, bool, 0644);
MODULE_PARM_DESC(enable_mcast_whitelist, "Enable multicast whitelisting");
/* Enable multicast rate control */
static bool enable_mcast_rate_control __read_mostly;
module_param(enable_mcast_rate_control, bool, 0644);
MODULE_PARM_DESC(enable_mcast_rate_control,
"Enable multicast rate control tracking to transmit at highest possible rate, bandwidth and GI");
/* Enable/Disable automatic logging of modparams on boot */
static bool log_modparams_on_boot __read_mostly = true;
module_param(log_modparams_on_boot, bool, 0644);
MODULE_PARM_DESC(log_modparams_on_boot, "Log all module parameters during boot");
/* Enable/Disable page slicing (dev only) */
static bool enable_page_slicing __read_mostly;
module_param(enable_page_slicing, bool, 0644);
MODULE_PARM_DESC(enable_page_slicing, "Enable page slicing");
/* Enable/disable the PV1 frame support */
static bool enable_pv1 __read_mostly;
module_param(enable_pv1, bool, 0644);
MODULE_PARM_DESC(enable_pv1, "Enable PV1 frame support (dev only)");
static bool enable_hw_scan __read_mostly = true;
module_param(enable_hw_scan, bool, 0644);
MODULE_PARM_DESC(enable_hw_scan, "Enable SoftMAC hardware scan support");
static bool enable_sched_scan __read_mostly = true;
module_param(enable_sched_scan, bool, 0644);
MODULE_PARM_DESC(enable_sched_scan, "Enable scheduled scanning");
/* Enable/Disable always sending probe requests at 1MHz */
static bool enable_1mhz_probes __read_mostly = true;
module_param(enable_1mhz_probes, bool, 0644);
MODULE_PARM_DESC(enable_1mhz_probes, "Enable sending all probe requests at 1MHz");
/* Set clock source selection mode */
static enum morse_cmd_slow_clock_mode
slow_clock_mode __read_mostly = MORSE_CMD_SLOW_CLOCK_MODE_AUTO;
module_param(slow_clock_mode, uint, 0644);
MODULE_PARM_DESC(slow_clock_mode, "Slow clock source selection mode");
static struct ieee80211_channel mors_5ghz_channels[] = {
/* UNII-1 */
CHAN5GHZ(36, 0),
CHAN5GHZ(40, 0),
CHAN5GHZ(44, 0),
CHAN5GHZ(48, 0),
/* UNII-2 */
CHAN5GHZ(52, 0),
CHAN5GHZ(56, 0),
CHAN5GHZ(60, 0),
CHAN5GHZ(64, 0),
CHAN5GHZ(100, 0),
CHAN5GHZ(104, 0),
CHAN5GHZ(108, 0),
CHAN5GHZ(112, 0),
CHAN5GHZ(116, 0),
CHAN5GHZ(120, 0),
CHAN5GHZ(124, 0),
CHAN5GHZ(128, 0),
CHAN5GHZ(132, 0),
CHAN5GHZ(136, 0),
/* UNII-3 */
CHAN5GHZ(149, 0),
CHAN5GHZ(153, 0),
CHAN5GHZ(157, 0),
CHAN5GHZ(161, 0),
CHAN5GHZ(165, 0),
CHAN5GHZ(169, 0),
CHAN5GHZ(173, 0),
CHAN5GHZ(177, 0),
/* 40MHz mapping */
/* UNII-1 */
CHAN5GHZ(38, 0),
CHAN5GHZ(46, 0),
/* UNII-2 */
CHAN5GHZ(54, 0),
CHAN5GHZ(62, 0),
CHAN5GHZ(102, 0),
CHAN5GHZ(110, 0),
CHAN5GHZ(118, 0),
CHAN5GHZ(126, 0),
CHAN5GHZ(134, 0),
CHAN5GHZ(151, 0),
CHAN5GHZ(159, 0),
CHAN5GHZ(167, 0),
CHAN5GHZ(175, 0),
/* 80MHz mapping */
CHAN5GHZ(42, 0),
CHAN5GHZ(58, 0),
CHAN5GHZ(106, 0),
CHAN5GHZ(122, 0),
CHAN5GHZ(155, 0),
CHAN5GHZ(171, 0),
/* 160MHz mapping */
CHAN5GHZ(50, 0),
CHAN5GHZ(114, 0),
CHAN5GHZ(163, 0),
};
static struct ieee80211_rate mors_2ghz_rates[] = {
RATE(5, 0),
RATE(10, 0), /* 0x02 = 1.0 Mbps, basic rates for 2.4GHz */
RATE(15, 0),
RATE(20, 0), /* 0x04 = 2.0 Mbps, basic rates for 2.4GHz */
RATE(25, 0),
RATE(30, 0),
RATE(35, 0),
RATE(40, 0),
RATE(45, 0),
RATE(55, 0), /* 0x0B = 5.5 Mbps, basic rates for 2.4GHz */
RATE(60, 0), /* 0x0C = 6.0 Mbps, basic rates for 5GHz */
RATE(65, 0),
RATE(70, 0),
RATE(85, 0),
RATE(90, 0),
RATE(110, 0), /* 0x16 = 11.0 Mbps, basic rates for 2.4GHz */
RATE(120, 0), /* 0x18 = 12.0 Mbps, basic rates for 5GHz */
RATE(125, 0),
RATE(135, 0),
RATE(150, 0),
RATE(180, 0),
RATE(240, 0) /* 0x30 = 24.0 Mbps, basic rates for 5GHz */
};
struct ieee80211_supported_band mors_band_5ghz = {
.band = NL80211_BAND_5GHZ,
.channels = mors_5ghz_channels,
.n_channels = ARRAY_SIZE(mors_5ghz_channels),
.bitrates = mors_2ghz_rates,
.n_bitrates = ARRAY_SIZE(mors_2ghz_rates),
.ht_cap = {
.cap = IEEE80211_HT_CAP_GRN_FLD |
(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | IEEE80211_HT_CAP_MAX_AMSDU,
.ht_supported = 1,
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
.mcs = {
.rx_mask[0] = (DEFAULT_MCS_RATE_MASK & MCS_RATE_MASK_0_TO_7),
.rx_mask[1] = (DEFAULT_MCS_RATE_MASK >> MCS_RATE_MASK_8_TO_9_OFFSET),
.rx_highest = __cpu_to_le16(0x41),
.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
},
},
.vht_cap = {
.vht_mcs = {
.rx_highest = __cpu_to_le16(0x41),
},
},
};
bool is_fullmac_mode(void)
{
return enable_wiphy;
}
/* Returns true if only STA mode is supported */
static bool is_sta_mode_only(void)
{
if (is_fullmac_mode() || is_virtual_sta_test_mode())
return true;
return false;
}
bool is_thin_lmac_mode(void)
{
return (thin_lmac > 0);
}
bool is_virtual_sta_test_mode(void)
{
return (virtual_sta_max > 0);
}
bool is_sw_crypto_mode(void)
{
return no_hwcrypt;
}
bool morse_mac_ps_enabled(struct morse *mors)
{
if (mors->bus_type == MORSE_HOST_BUS_TYPE_USB)
return (enable_ps != POWERSAVE_MODE_DISABLED);
return (enable_ps != POWERSAVE_MODE_DISABLED) &&
mors->cfg->mm_ps_gpios_supported;
}
enum morse_cmd_slow_clock_mode morse_mac_slow_clock_mode(void)
{
return slow_clock_mode;
}
static inline int morse_vif_max_tx_bw(struct morse_vif *mors_vif)
{
int max_bw_mhz;
struct morse_caps *capabs = &mors_vif->capabilities;
max_bw_mhz = MORSE_CAPAB_SUPPORTED(capabs, 8MHZ) ? 8 :
MORSE_CAPAB_SUPPORTED(capabs, 4MHZ) ? 4 :
MORSE_CAPAB_SUPPORTED(capabs, 2MHZ) ? 2 : 1;
return max_bw_mhz;
}
struct ieee80211_vif *morse_get_vif_from_tx_status(struct morse *mors,
struct morse_skb_tx_status *hdr_tx_status)
{
u8 vif_id = MORSE_TX_CONF_FLAGS_VIF_ID_GET(le32_to_cpu(hdr_tx_status->flags));
return morse_get_vif_from_vif_id(mors, vif_id);
}
struct ieee80211_vif *__morse_get_vif_from_vif_id(struct morse *mors, int vif_id)
{
struct ieee80211_vif *vif = NULL;
vif_id = array_index_nospec(vif_id, mors->max_vifs);
if (likely(vif_id < mors->max_vifs && mors->vif))
vif = mors->vif[vif_id];
return vif;
}
struct ieee80211_vif *morse_get_vif_from_vif_id(struct morse *mors, int vif_id)
{
struct ieee80211_vif *vif = NULL;
spin_lock_bh(&mors->vif_list_lock);
vif = __morse_get_vif_from_vif_id(mors, vif_id);
spin_unlock_bh(&mors->vif_list_lock);
return vif;
}
static void morse_vif_remove(struct morse *mors, u8 idx)
{
spin_lock_bh(&mors->vif_list_lock);
mors->vif[idx] = NULL;
spin_unlock_bh(&mors->vif_list_lock);
}
static void morse_vif_add(struct morse *mors, u8 idx, struct ieee80211_vif *vif)
{
/* The vif array is indexed by the vif_id reported from the firmware.
* As such the driver must always obey the vif_id given. Warn if there is a stale entry,
* but overwrite it anyway.
* We do not need to free stale entries as the memory is managed by mac80211
*/
spin_lock_bh(&mors->vif_list_lock);
WARN_ON(mors->vif[idx] && mors->vif[idx] != vif);
mors->vif[idx] = vif;
spin_unlock_bh(&mors->vif_list_lock);
}
struct ieee80211_vif *morse_get_vif(struct morse *mors)
{
int vif_id = 0;
struct ieee80211_vif *vif = NULL;
spin_lock_bh(&mors->vif_list_lock);
for (vif_id = 0; vif_id < mors->max_vifs; vif_id++) {
vif = __morse_get_vif_from_vif_id(mors, vif_id);
if (vif)
break;
}
spin_unlock_bh(&mors->vif_list_lock);
return vif;
}
struct ieee80211_vif *morse_get_vif_from_rx_status(struct morse *mors,
const struct morse_skb_rx_status *hdr_rx_status)
{
u8 vif_id = MORSE_RX_STATUS_FLAGS_VIF_ID_GET(le32_to_cpu(hdr_rx_status->flags));
return morse_get_vif_from_vif_id(mors, vif_id);
}
static struct ieee80211_vif *morse_get_first_vif_of_type(struct morse *mors,
enum nl80211_iftype type)
{
int vif_id = 0;
struct ieee80211_vif *vif = NULL;
spin_lock_bh(&mors->vif_list_lock);
for (vif_id = 0; vif_id < mors->max_vifs; vif_id++) {
vif = __morse_get_vif_from_vif_id(mors, vif_id);
if (vif && vif->type == type)
break;
vif = NULL;
}
spin_unlock_bh(&mors->vif_list_lock);
return vif;
}
struct ieee80211_vif *morse_get_ap_vif(struct morse *mors)
{
return morse_get_first_vif_of_type(mors, NL80211_IFTYPE_AP);
}
struct ieee80211_vif *morse_get_sta_vif(struct morse *mors)
{
return morse_get_first_vif_of_type(mors, NL80211_IFTYPE_STATION);
}
struct ieee80211_vif *morse_get_ibss_vif(struct morse *mors)
{
return morse_get_first_vif_of_type(mors, NL80211_IFTYPE_ADHOC);
}
struct ieee80211_vif *morse_get_mesh_vif(struct morse *mors)
{
return morse_get_first_vif_of_type(mors, NL80211_IFTYPE_MESH_POINT);
}
char *morse_vif_name(struct ieee80211_vif *vif)
{
struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif);
if (!wdev)
return "Unknown";
return wdev->netdev->name;
}
#if KERNEL_VERSION(4, 12, 0) <= MAC80211_VERSION_CODE
static u8 morse_mac_rx_bw_to_skb_vht(struct morse *mors, u8 rx_bw_mhz)
{
struct ieee80211_conf *conf = &mors->hw->conf;
u8 default_rate = RATE_INFO_BW_20;
/* Can't do 3 x subbands for channel does not support VHT80 or VHT160 */
if (conf->chandef.width != NL80211_CHAN_WIDTH_80 &&
conf->chandef.width != NL80211_CHAN_WIDTH_160)
return (rx_bw_mhz == 1) ? RATE_INFO_BW_20 : RATE_INFO_BW_40;
switch (rx_bw_mhz) {
case 1:
return RATE_INFO_BW_20;
case 2:
return RATE_INFO_BW_40;
case 4:
return RATE_INFO_BW_80;
case 8:
return conf->chandef.width !=
NL80211_CHAN_WIDTH_160 ? RATE_INFO_BW_80 : RATE_INFO_BW_160;
default:
MORSE_WARN_RATELIMITED(mors, "%s: Invalid S1G bandwidth\n", __func__);
return default_rate;
}
}
#endif
static void morse_mac_apply_mcs10_mode_auto(struct morse *mors, struct morse_skb_tx_info *tx_info)
{
u8 i;
u8 j;
int mcs0_first_idx = -1;
int mcs0_last_idx = -1;
/* Find out where our first and last MCS0 entries are. */
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
enum dot11_bandwidth bw_idx =
morse_ratecode_bw_index_get(tx_info->rates[i].morse_ratecode);
if (bw_idx == DOT11_BANDWIDTH_1MHZ) {
mcs0_last_idx = i;
if (mcs0_first_idx == -1)
mcs0_first_idx = i;
}
/* If the count is 0 then we are at the end of the table. Break to
* allow us to reuse i indicating the end of the table.
*/
if (tx_info->rates[i].count == 0)
break;
}
/* If there aren't any MCS0 (at 1MHz) entries we are done. */
if (mcs0_first_idx < 0)
return;
/*
* If we are in MCS10_MODE_AUTO add MCS10 counts to the table if they
* will fit.
* There should be three cases:
* - There is one MSC0 entry and the table is full -> do nothing
* - There is one MSC0 entry and the table has space -> adjust MSC0 down and
* add MCS 10
* - There are multiple MCS0 entries -> replace entries after the first
* with MCS 10
*/
/* Case 3 - replace additional entries. */
if (mcs0_last_idx > mcs0_first_idx) {
mors->debug.mcs_stats_tbl.mcs0.tx_count += tx_info->rates[mcs0_first_idx].count;
for (j = mcs0_first_idx + 1; j < i; j++) {
enum dot11_bandwidth bw_idx =
morse_ratecode_bw_index_get(tx_info->rates[j].morse_ratecode);
u8 mcs_index =
morse_ratecode_mcs_index_get(tx_info->rates[j].morse_ratecode);
if (mcs_index == 0 && bw_idx == DOT11_BANDWIDTH_1MHZ) {
morse_ratecode_mcs_index_set(&tx_info->rates[j].morse_ratecode, 10);
mors->debug.mcs_stats_tbl.mcs10.tx_count += tx_info->rates[j].count;
}
}
/* Case 2 - add additional MCS10 entry. */
} else if (mcs0_last_idx == mcs0_first_idx &&
i < (IEEE80211_TX_MAX_RATES)) {
int pre_mcs10_mcs0_count = min_t(u8, tx_info->rates[mcs0_last_idx].count,
MCS0_BEFORE_MCS10_COUNT);
int mcs10_count = tx_info->rates[mcs0_last_idx].count - pre_mcs10_mcs0_count;
/* If there were less retries than our desired minimum MCS0 we don't
* add MCS10 retries.
*/
if (mcs10_count > 0) {
/* Use the same flags for MCS10 as MCS0. */
tx_info->rates[i].morse_ratecode =
tx_info->rates[mcs0_last_idx].morse_ratecode;
morse_ratecode_mcs_index_set(&tx_info->rates[i].morse_ratecode, 10);
tx_info->rates[mcs0_last_idx].count = pre_mcs10_mcs0_count;
tx_info->rates[i].count = mcs10_count;
}
/* Update our statistics. */
mors->debug.mcs_stats_tbl.mcs10.tx_count += mcs10_count;
mors->debug.mcs_stats_tbl.mcs0.tx_count += pre_mcs10_mcs0_count;
/* Case 1 full table - increment MCS0 count. */
} else {
for (j = mcs0_first_idx; j < IEEE80211_TX_MAX_RATES; j++) {
u8 mcs_index =
morse_ratecode_mcs_index_get(tx_info->rates[i].morse_ratecode);
if (mcs_index == 0)
mors->debug.mcs_stats_tbl.mcs0.tx_count += tx_info->rates[j].count;
}
}
}
static void morse_mac_apply_mcs10(struct morse *mors, struct morse_skb_tx_info *tx_info)
{
u8 i;
switch (mcs10_mode) {
case MCS10_MODE_DISABLED:
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
enum dot11_bandwidth bw_idx =
morse_ratecode_bw_index_get(tx_info->rates[i].morse_ratecode);
u8 mcs_index =
morse_ratecode_mcs_index_get(tx_info->rates[i].morse_ratecode);
if (bw_idx == DOT11_BANDWIDTH_1MHZ && mcs_index == 0)
mors->debug.mcs_stats_tbl.mcs0.tx_count += tx_info->rates[i].count;
}
return;
case MCS10_MODE_FORCED:
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
enum dot11_bandwidth bw_idx =
morse_ratecode_bw_index_get(tx_info->rates[i].morse_ratecode);
u8 mcs_index =
morse_ratecode_mcs_index_get(tx_info->rates[i].morse_ratecode);
if (bw_idx == DOT11_BANDWIDTH_1MHZ && mcs_index == 0) {
morse_ratecode_mcs_index_set(&tx_info->rates[i].morse_ratecode, 10);
/* Update our statistics. */
mors->debug.mcs_stats_tbl.mcs10.tx_count += tx_info->rates[i].count;
}
}
return;
case MCS10_MODE_AUTO:
morse_mac_apply_mcs10_mode_auto(mors, tx_info);
}
}
bool morse_mac_is_subband_enable(void)
{
return (enable_subbands == SUBBANDS_MODE_ENABLED);
}
uint morse_mac_get_max_rate_tries(void)
{
return max_rate_tries;
}
uint morse_mac_get_max_rate(void)
{
return max_rates;
}
bool morse_mac_is_1mhz_probe_req_enabled(void)
{
return enable_1mhz_probes;
}
bool morse_mac_is_rts_8mhz_enabled(void)
{
return enable_rts_8mhz;
}
#ifdef CONFIG_MORSE_RC
static bool morse_mac_pkt_over_rts_threshold(struct morse *mors,
struct ieee80211_tx_info *info, struct sk_buff *skb)
{
if (info->control.hw_key) {
u8 ccmp_len;
if (info->control.hw_key->keylen == 32)
ccmp_len = IEEE80211_CCMP_256_HDR_LEN + IEEE80211_CCMP_256_MIC_LEN;
else if (info->control.hw_key->keylen == 16)
ccmp_len = IEEE80211_CCMP_HDR_LEN + IEEE80211_CCMP_MIC_LEN;
else
ccmp_len = 0;
return ((skb->len + FCS_LEN + ccmp_len) > mors->rts_threshold);
}
return ((skb->len + FCS_LEN) > mors->rts_threshold);
}
#endif
void morse_mac_fill_tx_info(struct morse *mors,
struct morse_skb_tx_info *tx_info,
struct sk_buff *skb,
struct ieee80211_vif *vif,
int tx_bw_mhz, struct ieee80211_sta *sta)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct morse_vif *mors_vif = ieee80211_vif_to_morse_vif(vif);
struct morse_sta *mors_sta = NULL;
__le16 fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
int op_bw_mhz = mors->custom_configs.channel_info.op_bw_mhz;
int i;
u8 ampdu_mmss = 0;
u8 morse_mmss_offset = 0;
bool rts_allowed = op_bw_mhz < 8 || enable_rts_8mhz; /* Disable 8MHz RTS/CTS for now */
if (sta)
mors_sta = (struct morse_sta *)sta->drv_priv;
#ifdef CONFIG_MORSE_RC
rts_allowed &= morse_mac_pkt_over_rts_threshold(mors, info, skb);
#else
rts_allowed &= info->control.use_rts;
#endif
morse_rc_sta_fill_tx_rates(mors, tx_info, skb, sta, tx_bw_mhz, rts_allowed);
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
/* SW-3200: WAR to prevent firmware crash when
* RTS/CTS is attempted to be sent at 4MHz
*/
if (rts_allowed) {
/* || (info->control.flags & IEEE80211_TX_RC_USE_RTS_CTS)) */
if (enable_cts_to_self)
morse_ratecode_enable_cts2self(&tx_info->rates[i].morse_ratecode);
else
morse_ratecode_enable_rts(&tx_info->rates[i].morse_ratecode);
}
if (mors_vif->ctrl_resp_in_1mhz_en)
morse_ratecode_enable_ctrl_resp_1mhz(&tx_info->rates[i].morse_ratecode);
/* If travelling pilot reception is supported always use it */
if (mors_sta && enable_trav_pilot &&
(mors_sta->trav_pilot_support == TRAV_PILOT_RX_1NSS ||
mors_sta->trav_pilot_support == TRAV_PILOT_RX_1_2_NSS))
morse_ratecode_enable_trav_pilots(&tx_info->rates[i].morse_ratecode);
if (info->control.rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
morse_ratecode_enable_sgi(&tx_info->rates[i].morse_ratecode);
}
/* Disable probe retries in constrained environments */
if (mors->duty_cycle > 0 && mors->duty_cycle <= duty_cycle_probe_retry_threshold) {
if (ieee80211_is_probe_req(fc) || ieee80211_is_probe_resp(fc)) {
mors->debug.page_stats.tx_duty_cycle_retry_disabled++;
tx_info->rates[0].count = 1;
tx_info->rates[1].count = 0;
}
}
/* Apply change of MCS0 to MCS10 if required. */
morse_mac_apply_mcs10(mors, tx_info);
tx_info->flags |= cpu_to_le32(MORSE_TX_CONF_FLAGS_VIF_ID_SET(mors_vif->id));
if (info->flags & IEEE80211_TX_CTL_AMPDU)
tx_info->flags |= cpu_to_le32(MORSE_TX_CONF_FLAGS_CTL_AMPDU);
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)
tx_info->flags |= cpu_to_le32(MORSE_TX_CONF_FLAGS_SEND_AFTER_DTIM);
if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) {
tx_info->flags |= cpu_to_le32(MORSE_TX_CONF_NO_PS_BUFFER);
if (info->flags & IEEE80211_TX_STATUS_EOSP)
tx_info->flags |= cpu_to_le32(MORSE_TX_CONF_FLAGS_IMMEDIATE_REPORT);
#if KERNEL_VERSION(6, 6, 0) > LINUX_VERSION_CODE
} else if (ieee80211_is_mgmt(fc) && !ieee80211_is_bufferable_mmpdu(fc)) {
#else
} else if (ieee80211_is_mgmt(fc) && !ieee80211_is_bufferable_mmpdu(skb)) {
#endif
/*
* Note, this does not handle the special IBSS case where probe responses
* to unicast probe requests should be buffered. That will need to be added
* if power save support for IBSS is added.
*/
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
tx_info->flags |= cpu_to_le32(MORSE_TX_CONF_NO_PS_BUFFER);
}
if (info->control.hw_key) {
tx_info->flags |= cpu_to_le32(MORSE_TX_CONF_FLAGS_HW_ENCRYPT);
tx_info->flags |=
cpu_to_le32(MORSE_TX_CONF_FLAGS_KEY_IDX_SET(info->control.hw_key->hw_key_idx));
}
tx_info->tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
if (ieee80211_is_data_qos(fc)) {
u8 frame_tid = MORSE_IEEE80211_GET_TID((struct ieee80211_hdr *)skb->data);
MORSE_WARN_ON_ONCE(FEATURE_ID_DEFAULT, tx_info->tid != frame_tid);
tx_info->tid = frame_tid;
}
if (mors_sta) {
tx_info->tid_params = mors_sta->tid_params[tx_info->tid];
if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) {
if (mors_sta->tx_ps_filter_en)
MORSE_DBG(mors, "TX ps filter cleared sta[%pM]\n", mors_sta->addr);
mors_sta->tx_ps_filter_en = false;
}
}
if (morse_is_pv1_protected_frame(skb))
tx_info->flags |= cpu_to_le32(MORSE_TX_CONF_HAS_PV1_BPN_IN_BODY);
/* Fill MMSS (Minimum MPDU start spacing) fields */
if (morse_mac_is_iface_ap_type(vif)) {
if (mors_sta) {
ampdu_mmss = mors_sta->ampdu_mmss;
morse_mmss_offset = mors_sta->vendor_info.morse_mmss_offset;
}
} else {
ampdu_mmss = mors_vif->bss_ampdu_mmss;
morse_mmss_offset = mors_vif->bss_vendor_info.morse_mmss_offset;