@@ -75,6 +75,16 @@ static DEFINE_SPINLOCK(vif_list_lock);
75
75
/* SME stands for "station management entity" */
76
76
enum sme_state { SME_DISCONNECTED , SME_CONNECTING , SME_CONNECTED };
77
77
78
+ /* Spec GI enum */
79
+ enum vwifi_txrate_gi {
80
+ VWIFI_TXRATE_GI_800NS , /* Long GI, 0.8 µs */
81
+ VWIFI_TXRATE_GI_400NS , /* Short GI, 0.4 µs */
82
+ };
83
+
84
+ static int gi_mode = VWIFI_TXRATE_GI_800NS ;
85
+ module_param (gi_mode , int , 0644 );
86
+ MODULE_PARM_DESC (gi_mode , "Guard interval: 0 = 0.8µs, 1 = 0.4µs" );
87
+
78
88
/* Each virtual interface contains a wiphy, vwifi_wiphy_counter is responsible
79
89
* for recording the number of wiphy in vwifi.
80
90
*/
@@ -90,6 +100,8 @@ struct vwifi_vif {
90
100
struct net_device_stats stats ;
91
101
int manual_mcs ;
92
102
bool manual_mcs_set ;
103
+ struct cfg80211_bitrate_mask bitrate_mask ;
104
+ enum vwifi_txrate_gi gi ; /* for GI tracking */
93
105
94
106
size_t ssid_len ;
95
107
/* Currently connected BSS id */
@@ -1443,50 +1455,18 @@ static int vwifi_get_station(struct wiphy *wiphy,
1443
1455
int mcs_index ;
1444
1456
const char * modulation ;
1445
1457
const char * coding_rate ;
1458
+
1459
+ /* Select MCS dynamically or use manual settings */
1446
1460
if (vif -> manual_mcs_set ) {
1447
- mcs_index = vif -> manual_mcs ;
1448
- switch (mcs_index ) {
1449
- case 24 :
1450
- modulation = "BPSK" ;
1451
- coding_rate = "1/2" ;
1452
- break ;
1453
- case 25 :
1454
- modulation = "QPSK" ;
1455
- coding_rate = "1/2" ;
1456
- break ;
1457
- case 26 :
1458
- modulation = "QPSK" ;
1459
- coding_rate = "3/4" ;
1460
- break ;
1461
- case 27 :
1462
- modulation = "16-QAM" ;
1463
- coding_rate = "1/2" ;
1464
- break ;
1465
- case 28 :
1466
- modulation = "16-QAM" ;
1467
- coding_rate = "3/4" ;
1468
- break ;
1469
- case 29 :
1470
- modulation = "64-QAM" ;
1471
- coding_rate = "2/3" ;
1472
- break ;
1473
- case 30 :
1474
- modulation = "64-QAM" ;
1475
- coding_rate = "3/4" ;
1476
- break ;
1477
- case 31 :
1478
- modulation = "64-QAM" ;
1479
- coding_rate = "5/6" ;
1480
- break ;
1481
- default :
1482
- pr_err ("vwifi: Unsupported MCS index %d\n" , mcs_index );
1483
- mcs_index = 24 ; /* Default to lowest 4-stream MCS */
1484
- modulation = "BPSK" ;
1485
- coding_rate = "1/2" ;
1486
- break ;
1461
+ /* Select highest enabled MCS from bitrate_mask */
1462
+ mcs_index = 31 ;
1463
+ for (int i = 31 ; i >= 0 ; i -- ) {
1464
+ if (vif -> bitrate_mask .control [NL80211_BAND_2GHZ ].ht_mcs [i / 8 ] &
1465
+ (1 << (i % 8 ))) {
1466
+ mcs_index = i ;
1467
+ break ;
1468
+ }
1487
1469
}
1488
- pr_info ("vwifi: Station %pM using manual MCS %d (%s, %s)\n" , mac ,
1489
- mcs_index , modulation , coding_rate );
1490
1470
} else {
1491
1471
if (sinfo -> signal > -45 ) {
1492
1472
mcs_index = 31 ;
@@ -1521,20 +1501,51 @@ static int vwifi_get_station(struct wiphy *wiphy,
1521
1501
modulation = "BPSK" ;
1522
1502
coding_rate = "1/2" ;
1523
1503
}
1524
- pr_info ("vwifi: Station %pM signal %d dBm, using MCS %d (%s, %s)\n" ,
1525
- mac , sinfo -> signal , mcs_index , modulation , coding_rate );
1526
1504
}
1505
+
1506
+ /* Assign modulation and coding rate based on MCS */
1507
+ switch (mcs_index ) {
1508
+ case 0 : case 8 : case 16 : case 24 :
1509
+ modulation = "BPSK" ; coding_rate = "1/2" ; break ;
1510
+ case 1 : case 9 : case 17 : case 25 :
1511
+ modulation = "QPSK" ; coding_rate = "1/2" ; break ;
1512
+ case 2 : case 10 : case 18 : case 26 :
1513
+ modulation = "QPSK" ; coding_rate = "3/4" ; break ;
1514
+ case 3 : case 11 : case 19 : case 27 :
1515
+ modulation = "16-QAM" ; coding_rate = "1/2" ; break ;
1516
+ case 4 : case 12 : case 20 : case 28 :
1517
+ modulation = "16-QAM" ; coding_rate = "3/4" ; break ;
1518
+ case 5 : case 13 : case 21 : case 29 :
1519
+ modulation = "64-QAM" ; coding_rate = "2/3" ; break ;
1520
+ case 6 : case 14 : case 22 : case 30 :
1521
+ modulation = "64-QAM" ; coding_rate = "3/4" ; break ;
1522
+ case 7 : case 15 : case 23 : case 31 :
1523
+ modulation = "64-QAM" ; coding_rate = "5/6" ; break ;
1524
+ default :
1525
+ mcs_index = 0 ;
1526
+ modulation = "BPSK" ; coding_rate = "1/2" ; break ;
1527
+ }
1528
+
1529
+ pr_info ("vwifi: Station %pM signal %d dBm, MCS %d (%s, %s), GI %s\n" ,
1530
+ mac , mcs_index , modulation , coding_rate ,
1531
+ vif -> gi == VWIFI_TXRATE_GI_400NS ? "0.4µs" : "0.8µs" );
1532
+
1527
1533
/* Configure RX and TX rates */
1528
1534
sinfo -> rxrate .flags = RATE_INFO_FLAGS_MCS ;
1535
+ if (vif -> gi == VWIFI_TXRATE_GI_400NS )
1536
+ sinfo -> rxrate .flags |= RATE_INFO_FLAGS_SHORT_GI ;
1529
1537
sinfo -> rxrate .mcs = mcs_index ;
1530
1538
sinfo -> rxrate .bw = RATE_INFO_BW_20 ;
1531
1539
sinfo -> rxrate .n_bonded_ch = 1 ;
1532
-
1540
+
1533
1541
sinfo -> txrate .flags = RATE_INFO_FLAGS_MCS ;
1542
+ if (vif -> gi == VWIFI_TXRATE_GI_400NS )
1543
+ sinfo -> txrate .flags |= RATE_INFO_FLAGS_SHORT_GI ;
1534
1544
sinfo -> txrate .mcs = mcs_index ;
1535
1545
sinfo -> txrate .bw = RATE_INFO_BW_20 ;
1536
1546
sinfo -> txrate .n_bonded_ch = 1 ;
1537
1547
1548
+
1538
1549
/* Log rate configuration for verification */
1539
1550
pr_info ("vwifi: Station %pM txrate MCS %d, rxrate MCS %d\n" , mac ,
1540
1551
sinfo -> txrate .mcs , sinfo -> rxrate .mcs );
@@ -1550,9 +1561,13 @@ static int vwifi_dump_station(struct wiphy *wiphy,
1550
1561
{
1551
1562
struct vwifi_vif * ap_vif = ndev_get_vwifi_vif (dev );
1552
1563
1564
+ if (!ap_vif ) {
1565
+ pr_err ("vwifi: Failed to get ap_vif for dev %s\n" , dev -> name );
1566
+ return - EINVAL ;
1567
+ }
1568
+
1553
1569
pr_info ("Dump station at the idx %d\n" , idx );
1554
1570
1555
- int ret = - ENONET ;
1556
1571
struct vwifi_vif * sta_vif = NULL ;
1557
1572
int i = 0 ;
1558
1573
@@ -1564,10 +1579,9 @@ static int vwifi_dump_station(struct wiphy *wiphy,
1564
1579
break ;
1565
1580
}
1566
1581
1567
- if (sta_vif == ap_vif )
1568
- return ret ;
1569
-
1570
- ret = 0 ;
1582
+ if (!sta_vif ) {
1583
+ return - ENONET ;
1584
+ }
1571
1585
1572
1586
memcpy (mac , sta_vif -> ndev -> dev_addr , ETH_ALEN );
1573
1587
return vwifi_get_station (wiphy , dev , mac , sinfo );
@@ -2254,26 +2268,22 @@ static int vwifi_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
2254
2268
2255
2269
return 0 ;
2256
2270
}
2271
+
2257
2272
/* Callback to handle manual bitrate configuration via iw */
2258
2273
static int vwifi_set_bitrate_mask (struct wiphy * wiphy ,
2259
- struct net_device * dev ,
2260
- unsigned int link_id ,
2261
- const u8 * peer ,
2262
- const struct cfg80211_bitrate_mask * mask )
2274
+ struct net_device * dev ,
2275
+ unsigned int link_id ,
2276
+ const u8 * peer ,
2277
+ const struct cfg80211_bitrate_mask * mask )
2263
2278
{
2264
2279
struct vwifi_vif * vif = netdev_priv (dev );
2265
- int mcs_index = -1 ;
2280
+ int i ;
2266
2281
2267
2282
if (!vif ) {
2268
2283
pr_err ("vwifi: Failed to get vwifi_vif for dev %s\n" , dev -> name );
2269
2284
return - EINVAL ;
2270
2285
}
2271
2286
2272
- if (vif -> sme_state != SME_CONNECTED ) {
2273
- pr_err ("vwifi: Dev %s not connected, cannot set bitrate\n" , dev -> name );
2274
- return - EINVAL ;
2275
- }
2276
-
2277
2287
pr_info ("vwifi: set_bitrate_mask called for dev %s, link_id %u, peer %pM\n" ,
2278
2288
dev -> name , link_id , peer ? peer : vif -> bssid );
2279
2289
pr_info ("vwifi: 2.4GHz MCS mask: %02x %02x %02x %02x\n" ,
@@ -2282,36 +2292,24 @@ static int vwifi_set_bitrate_mask(struct wiphy *wiphy,
2282
2292
mask -> control [NL80211_BAND_2GHZ ].ht_mcs [2 ],
2283
2293
mask -> control [NL80211_BAND_2GHZ ].ht_mcs [3 ]);
2284
2294
2285
- /* Find the requested MCS index */
2286
- for (int i = 0 ; i < 4 ; i ++ ) {
2287
- if (mask -> control [NL80211_BAND_2GHZ ].ht_mcs [i ]) {
2288
- for (int j = 0 ; j < 8 ; j ++ ) {
2289
- if (mask -> control [NL80211_BAND_2GHZ ].ht_mcs [i ] & (1 << j )) {
2290
- mcs_index = i * 8 + j ;
2291
- pr_info ("vwifi: Requested MCS index %d\n" , mcs_index );
2292
- break ;
2293
- }
2294
- }
2295
- if (mcs_index != -1 )
2296
- break ;
2297
- }
2298
- }
2295
+ memset (vif -> bitrate_mask .control [NL80211_BAND_2GHZ ].ht_mcs , 0 ,
2296
+ IEEE80211_HT_MCS_MASK_LEN );
2299
2297
2300
- if (mcs_index == -1 ) {
2301
- pr_err ("vwifi: No valid MCS index found\n" );
2302
- return - EINVAL ;
2303
- }
2298
+ for (i = 0 ; i < IEEE80211_HT_MCS_MASK_LEN ; i ++ )
2299
+ vif -> bitrate_mask .control [NL80211_BAND_2GHZ ].ht_mcs [i ] =
2300
+ mask -> control [NL80211_BAND_2GHZ ].ht_mcs [i ];
2304
2301
2305
- /* Restrict to supported 4-stream MCS indices 24–31 */
2306
- if (mcs_index < 24 || mcs_index > 31 ) {
2307
- pr_err ("vwifi: Unsupported MCS index %d\n" , mcs_index );
2308
- return - EINVAL ;
2302
+ vif -> gi = gi_mode ; /* Use gi module parameter */
2303
+ pr_info ("vwifi: Set GI to %s\n" , gi_mode ? "0.4µs" : "0.8µs" );
2304
+
2305
+ for (i = 0 ; i < 32 ; i ++ ) {
2306
+ if (vif -> bitrate_mask .control [NL80211_BAND_2GHZ ].ht_mcs [i / 8 ] &
2307
+ (1 << (i % 8 ))) {
2308
+ pr_info ("vwifi: Enabled MCS %d\n" , i );
2309
+ }
2309
2310
}
2310
2311
2311
- vif -> manual_mcs = mcs_index ;
2312
2312
vif -> manual_mcs_set = true;
2313
- pr_info ("vwifi: Set manual MCS %d for dev %s\n" , mcs_index , dev -> name );
2314
-
2315
2313
return 0 ;
2316
2314
}
2317
2315
@@ -2362,6 +2360,15 @@ static struct cfg80211_ops vwifi_cfg_ops = {
2362
2360
.bitrate = (_rate), .hw_value = (_hw_value), \
2363
2361
}
2364
2362
2363
+ /* Macro for HT MCS rate table */
2364
+ #define HT_MCS_RATE (_mcs , _ss , _rate_800ns , _rate_400ns ) \
2365
+ { \
2366
+ .mcs_index = (_mcs), \
2367
+ .spatial_streams = (_ss), \
2368
+ .rate_800ns = (_rate_800ns), \
2369
+ .rate_400ns = (_rate_400ns), \
2370
+ }
2371
+
2365
2372
/* Array of "supported" channels in 2GHz band. It is required for wiphy. */
2366
2373
static const struct ieee80211_channel vwifi_supported_channels_2ghz [] = {
2367
2374
CHAN_2GHZ (1 , 2412 ), CHAN_2GHZ (2 , 2417 ), CHAN_2GHZ (3 , 2422 ),
@@ -2393,6 +2400,62 @@ static const struct ieee80211_rate vwifi_supported_rates[] = {
2393
2400
RATE_ENT (360 , 0x200 ), RATE_ENT (480 , 0x400 ), RATE_ENT (540 , 0x800 ),
2394
2401
};
2395
2402
2403
+
2404
+ struct ht_mcs_rate {
2405
+ u8 mcs_index ;
2406
+ u8 spatial_streams ;
2407
+ float rate_800ns ; /* Mbps */
2408
+ float rate_400ns ; /* Mbps */
2409
+ };
2410
+
2411
+ /* HT MCS table for 20 MHz, 1–4 spatial streams, 0.8 µs and 0.4 µs GI */
2412
+ static const struct ht_mcs_rate ht_mcs_table [] = {
2413
+ HT_MCS_RATE (0 , 1 , 6.5 , 7.2 ),
2414
+ HT_MCS_RATE (1 , 1 , 13.0 , 14.4 ),
2415
+ HT_MCS_RATE (2 , 1 , 19.5 , 21.7 ),
2416
+ HT_MCS_RATE (3 , 1 , 26.0 , 28.9 ),
2417
+ HT_MCS_RATE (4 , 1 , 39.0 , 43.3 ),
2418
+ HT_MCS_RATE (5 , 1 , 52.0 , 57.8 ),
2419
+ HT_MCS_RATE (6 , 1 , 58.5 , 65.0 ),
2420
+ HT_MCS_RATE (7 , 1 , 65.0 , 72.2 ),
2421
+ HT_MCS_RATE (8 , 2 , 13.0 , 14.4 ),
2422
+ HT_MCS_RATE (9 , 2 , 26.0 , 28.9 ),
2423
+ HT_MCS_RATE (10 , 2 , 39.0 , 43.3 ),
2424
+ HT_MCS_RATE (11 , 2 , 52.0 , 57.8 ),
2425
+ HT_MCS_RATE (12 , 2 , 78.0 , 86.7 ),
2426
+ HT_MCS_RATE (13 , 2 , 104.0 , 115.6 ),
2427
+ HT_MCS_RATE (14 , 2 , 117.0 , 130.0 ),
2428
+ HT_MCS_RATE (15 , 2 , 130.0 , 144.4 ),
2429
+ HT_MCS_RATE (16 , 3 , 19.5 , 21.7 ),
2430
+ HT_MCS_RATE (17 , 3 , 39.0 , 43.3 ),
2431
+ HT_MCS_RATE (18 , 3 , 58.5 , 65.0 ),
2432
+ HT_MCS_RATE (19 , 3 , 78.0 , 86.7 ),
2433
+ HT_MCS_RATE (20 , 3 , 117.0 , 130.0 ),
2434
+ HT_MCS_RATE (21 , 3 , 156.0 , 173.3 ),
2435
+ HT_MCS_RATE (22 , 3 , 175.5 , 195.0 ),
2436
+ HT_MCS_RATE (23 , 3 , 195.0 , 216.7 ),
2437
+ HT_MCS_RATE (24 , 4 , 26.0 , 28.9 ),
2438
+ HT_MCS_RATE (25 , 4 , 52.0 , 57.8 ),
2439
+ HT_MCS_RATE (26 , 4 , 78.0 , 86.7 ),
2440
+ HT_MCS_RATE (27 , 4 , 104.0 , 115.6 ),
2441
+ HT_MCS_RATE (28 , 4 , 156.0 , 173.3 ),
2442
+ HT_MCS_RATE (29 , 4 , 208.0 , 231.1 ),
2443
+ HT_MCS_RATE (30 , 4 , 234.0 , 260.0 ),
2444
+ HT_MCS_RATE (31 , 4 , 260.0 , 288.9 ),
2445
+ };
2446
+
2447
+ /* Lookup data rate for given MCS index and GI */
2448
+ static float vwifi_get_mcs_rate (u8 mcs_index , enum vwifi_txrate_gi gi )
2449
+ {
2450
+ for (int i = 0 ; i < ARRAY_SIZE (ht_mcs_table ); i ++ ) {
2451
+ if (ht_mcs_table [i ].mcs_index == mcs_index )
2452
+ return (gi == VWIFI_TXRATE_GI_800NS ) ?
2453
+ ht_mcs_table [i ].rate_800ns :
2454
+ ht_mcs_table [i ].rate_400ns ;
2455
+ }
2456
+ return 6.5 ; /* Default to MCS 0, 0.8 µs GI */
2457
+ }
2458
+
2396
2459
static struct ieee80211_supported_band nf_band_2ghz = {
2397
2460
.band = NL80211_BAND_2GHZ ,
2398
2461
.channels = vwifi_supported_channels_2ghz ,
0 commit comments