@@ -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,93 @@ 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 :
1509
+ case 8 :
1510
+ case 16 :
1511
+ case 24 :
1512
+ modulation = "BPSK" ;
1513
+ coding_rate = "1/2" ;
1514
+ break ;
1515
+ case 1 :
1516
+ case 9 :
1517
+ case 17 :
1518
+ case 25 :
1519
+ modulation = "QPSK" ;
1520
+ coding_rate = "1/2" ;
1521
+ break ;
1522
+ case 2 :
1523
+ case 10 :
1524
+ case 18 :
1525
+ case 26 :
1526
+ modulation = "QPSK" ;
1527
+ coding_rate = "3/4" ;
1528
+ break ;
1529
+ case 3 :
1530
+ case 11 :
1531
+ case 19 :
1532
+ case 27 :
1533
+ modulation = "16-QAM" ;
1534
+ coding_rate = "1/2" ;
1535
+ break ;
1536
+ case 4 :
1537
+ case 12 :
1538
+ case 20 :
1539
+ case 28 :
1540
+ modulation = "16-QAM" ;
1541
+ coding_rate = "3/4" ;
1542
+ break ;
1543
+ case 5 :
1544
+ case 13 :
1545
+ case 21 :
1546
+ case 29 :
1547
+ modulation = "64-QAM" ;
1548
+ coding_rate = "2/3" ;
1549
+ break ;
1550
+ case 6 :
1551
+ case 14 :
1552
+ case 22 :
1553
+ case 30 :
1554
+ modulation = "64-QAM" ;
1555
+ coding_rate = "3/4" ;
1556
+ break ;
1557
+ case 7 :
1558
+ case 15 :
1559
+ case 23 :
1560
+ case 31 :
1561
+ modulation = "64-QAM" ;
1562
+ coding_rate = "5/6" ;
1563
+ break ;
1564
+ default :
1565
+ mcs_index = 0 ;
1566
+ modulation = "BPSK" ;
1567
+ coding_rate = "1/2" ;
1568
+ break ;
1569
+ }
1570
+
1571
+ pr_info ("vwifi: Station %pM signal %d dBm, MCS %d (%s, %s), GI %s\n" , mac ,
1572
+ mcs_index , modulation , coding_rate ,
1573
+ vif -> gi == VWIFI_TXRATE_GI_400NS ? "0.4µs" : "0.8µs" );
1574
+
1527
1575
/* Configure RX and TX rates */
1528
1576
sinfo -> rxrate .flags = RATE_INFO_FLAGS_MCS ;
1577
+ if (vif -> gi == VWIFI_TXRATE_GI_400NS )
1578
+ sinfo -> rxrate .flags |= RATE_INFO_FLAGS_SHORT_GI ;
1529
1579
sinfo -> rxrate .mcs = mcs_index ;
1530
1580
sinfo -> rxrate .bw = RATE_INFO_BW_20 ;
1531
1581
sinfo -> rxrate .n_bonded_ch = 1 ;
1532
1582
1533
1583
sinfo -> txrate .flags = RATE_INFO_FLAGS_MCS ;
1584
+ if (vif -> gi == VWIFI_TXRATE_GI_400NS )
1585
+ sinfo -> txrate .flags |= RATE_INFO_FLAGS_SHORT_GI ;
1534
1586
sinfo -> txrate .mcs = mcs_index ;
1535
1587
sinfo -> txrate .bw = RATE_INFO_BW_20 ;
1536
1588
sinfo -> txrate .n_bonded_ch = 1 ;
1537
1589
1590
+
1538
1591
/* Log rate configuration for verification */
1539
1592
pr_info ("vwifi: Station %pM txrate MCS %d, rxrate MCS %d\n" , mac ,
1540
1593
sinfo -> txrate .mcs , sinfo -> rxrate .mcs );
@@ -1550,9 +1603,13 @@ static int vwifi_dump_station(struct wiphy *wiphy,
1550
1603
{
1551
1604
struct vwifi_vif * ap_vif = ndev_get_vwifi_vif (dev );
1552
1605
1606
+ if (!ap_vif ) {
1607
+ pr_err ("vwifi: Failed to get ap_vif for dev %s\n" , dev -> name );
1608
+ return - EINVAL ;
1609
+ }
1610
+
1553
1611
pr_info ("Dump station at the idx %d\n" , idx );
1554
1612
1555
- int ret = - ENONET ;
1556
1613
struct vwifi_vif * sta_vif = NULL ;
1557
1614
int i = 0 ;
1558
1615
@@ -1564,10 +1621,9 @@ static int vwifi_dump_station(struct wiphy *wiphy,
1564
1621
break ;
1565
1622
}
1566
1623
1567
- if (sta_vif == ap_vif )
1568
- return ret ;
1569
-
1570
- ret = 0 ;
1624
+ if (!sta_vif ) {
1625
+ return - ENONET ;
1626
+ }
1571
1627
1572
1628
memcpy (mac , sta_vif -> ndev -> dev_addr , ETH_ALEN );
1573
1629
return vwifi_get_station (wiphy , dev , mac , sinfo );
@@ -2265,6 +2321,7 @@ static int vwifi_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
2265
2321
2266
2322
return 0 ;
2267
2323
}
2324
+
2268
2325
/* Callback to handle manual bitrate configuration via iw */
2269
2326
static int vwifi_set_bitrate_mask (struct wiphy * wiphy ,
2270
2327
struct net_device * dev ,
@@ -2273,18 +2330,13 @@ static int vwifi_set_bitrate_mask(struct wiphy *wiphy,
2273
2330
const struct cfg80211_bitrate_mask * mask )
2274
2331
{
2275
2332
struct vwifi_vif * vif = netdev_priv (dev );
2276
- int mcs_index = -1 ;
2333
+ int i ;
2277
2334
2278
2335
if (!vif ) {
2279
2336
pr_err ("vwifi: Failed to get vwifi_vif for dev %s\n" , dev -> name );
2280
2337
return - EINVAL ;
2281
2338
}
2282
2339
2283
- if (vif -> sme_state != SME_CONNECTED ) {
2284
- pr_err ("vwifi: Dev %s not connected, cannot set bitrate\n" , dev -> name );
2285
- return - EINVAL ;
2286
- }
2287
-
2288
2340
pr_info ("vwifi: set_bitrate_mask called for dev %s, link_id %u, peer %pM\n" ,
2289
2341
dev -> name , link_id , peer ? peer : vif -> bssid );
2290
2342
pr_info ("vwifi: 2.4GHz MCS mask: %02x %02x %02x %02x\n" ,
@@ -2293,36 +2345,24 @@ static int vwifi_set_bitrate_mask(struct wiphy *wiphy,
2293
2345
mask -> control [NL80211_BAND_2GHZ ].ht_mcs [2 ],
2294
2346
mask -> control [NL80211_BAND_2GHZ ].ht_mcs [3 ]);
2295
2347
2296
- /* Find the requested MCS index */
2297
- for (int i = 0 ; i < 4 ; i ++ ) {
2298
- if (mask -> control [NL80211_BAND_2GHZ ].ht_mcs [i ]) {
2299
- for (int j = 0 ; j < 8 ; j ++ ) {
2300
- if (mask -> control [NL80211_BAND_2GHZ ].ht_mcs [i ] & (1 << j )) {
2301
- mcs_index = i * 8 + j ;
2302
- pr_info ("vwifi: Requested MCS index %d\n" , mcs_index );
2303
- break ;
2304
- }
2305
- }
2306
- if (mcs_index != -1 )
2307
- break ;
2308
- }
2309
- }
2348
+ memset (vif -> bitrate_mask .control [NL80211_BAND_2GHZ ].ht_mcs , 0 ,
2349
+ IEEE80211_HT_MCS_MASK_LEN );
2310
2350
2311
- if (mcs_index == -1 ) {
2312
- pr_err ("vwifi: No valid MCS index found\n" );
2313
- return - EINVAL ;
2314
- }
2351
+ for (i = 0 ; i < IEEE80211_HT_MCS_MASK_LEN ; i ++ )
2352
+ vif -> bitrate_mask .control [NL80211_BAND_2GHZ ].ht_mcs [i ] =
2353
+ mask -> control [NL80211_BAND_2GHZ ].ht_mcs [i ];
2315
2354
2316
- /* Restrict to supported 4-stream MCS indices 24–31 */
2317
- if (mcs_index < 24 || mcs_index > 31 ) {
2318
- pr_err ("vwifi: Unsupported MCS index %d\n" , mcs_index );
2319
- return - EINVAL ;
2355
+ vif -> gi = gi_mode ; /* Use gi module parameter */
2356
+ pr_info ("vwifi: Set GI to %s\n" , gi_mode ? "0.4µs" : "0.8µs" );
2357
+
2358
+ for (i = 0 ; i < 32 ; i ++ ) {
2359
+ if (vif -> bitrate_mask .control [NL80211_BAND_2GHZ ].ht_mcs [i / 8 ] &
2360
+ (1 << (i % 8 ))) {
2361
+ pr_info ("vwifi: Enabled MCS %d\n" , i );
2362
+ }
2320
2363
}
2321
2364
2322
- vif -> manual_mcs = mcs_index ;
2323
2365
vif -> manual_mcs_set = true;
2324
- pr_info ("vwifi: Set manual MCS %d for dev %s\n" , mcs_index , dev -> name );
2325
-
2326
2366
return 0 ;
2327
2367
}
2328
2368
@@ -2373,6 +2413,13 @@ static struct cfg80211_ops vwifi_cfg_ops = {
2373
2413
.bitrate = (_rate), .hw_value = (_hw_value), \
2374
2414
}
2375
2415
2416
+ /* Macro for HT MCS rate table */
2417
+ #define HT_MCS_RATE (_mcs , _ss , _rate_800ns , _rate_400ns ) \
2418
+ { \
2419
+ .mcs_index = (_mcs), .spatial_streams = (_ss), \
2420
+ .rate_800ns = (_rate_800ns), .rate_400ns = (_rate_400ns), \
2421
+ }
2422
+
2376
2423
/* Array of "supported" channels in 2GHz band. It is required for wiphy. */
2377
2424
static const struct ieee80211_channel vwifi_supported_channels_2ghz [] = {
2378
2425
CHAN_2GHZ (1 , 2412 ), CHAN_2GHZ (2 , 2417 ), CHAN_2GHZ (3 , 2422 ),
@@ -2404,6 +2451,45 @@ static const struct ieee80211_rate vwifi_supported_rates[] = {
2404
2451
RATE_ENT (360 , 0x200 ), RATE_ENT (480 , 0x400 ), RATE_ENT (540 , 0x800 ),
2405
2452
};
2406
2453
2454
+
2455
+ struct ht_mcs_rate {
2456
+ u8 mcs_index ;
2457
+ u8 spatial_streams ;
2458
+ float rate_800ns ; /* Mbps */
2459
+ float rate_400ns ; /* Mbps */
2460
+ };
2461
+
2462
+ /* HT MCS table for 20 MHz, 1–4 spatial streams, 0.8 µs and 0.4 µs GI */
2463
+ static const struct ht_mcs_rate ht_mcs_table [] = {
2464
+ HT_MCS_RATE (0 , 1 , 6.5 , 7.2 ), HT_MCS_RATE (1 , 1 , 13.0 , 14.4 ),
2465
+ HT_MCS_RATE (2 , 1 , 19.5 , 21.7 ), HT_MCS_RATE (3 , 1 , 26.0 , 28.9 ),
2466
+ HT_MCS_RATE (4 , 1 , 39.0 , 43.3 ), HT_MCS_RATE (5 , 1 , 52.0 , 57.8 ),
2467
+ HT_MCS_RATE (6 , 1 , 58.5 , 65.0 ), HT_MCS_RATE (7 , 1 , 65.0 , 72.2 ),
2468
+ HT_MCS_RATE (8 , 2 , 13.0 , 14.4 ), HT_MCS_RATE (9 , 2 , 26.0 , 28.9 ),
2469
+ HT_MCS_RATE (10 , 2 , 39.0 , 43.3 ), HT_MCS_RATE (11 , 2 , 52.0 , 57.8 ),
2470
+ HT_MCS_RATE (12 , 2 , 78.0 , 86.7 ), HT_MCS_RATE (13 , 2 , 104.0 , 115.6 ),
2471
+ HT_MCS_RATE (14 , 2 , 117.0 , 130.0 ), HT_MCS_RATE (15 , 2 , 130.0 , 144.4 ),
2472
+ HT_MCS_RATE (16 , 3 , 19.5 , 21.7 ), HT_MCS_RATE (17 , 3 , 39.0 , 43.3 ),
2473
+ HT_MCS_RATE (18 , 3 , 58.5 , 65.0 ), HT_MCS_RATE (19 , 3 , 78.0 , 86.7 ),
2474
+ HT_MCS_RATE (20 , 3 , 117.0 , 130.0 ), HT_MCS_RATE (21 , 3 , 156.0 , 173.3 ),
2475
+ HT_MCS_RATE (22 , 3 , 175.5 , 195.0 ), HT_MCS_RATE (23 , 3 , 195.0 , 216.7 ),
2476
+ HT_MCS_RATE (24 , 4 , 26.0 , 28.9 ), HT_MCS_RATE (25 , 4 , 52.0 , 57.8 ),
2477
+ HT_MCS_RATE (26 , 4 , 78.0 , 86.7 ), HT_MCS_RATE (27 , 4 , 104.0 , 115.6 ),
2478
+ HT_MCS_RATE (28 , 4 , 156.0 , 173.3 ), HT_MCS_RATE (29 , 4 , 208.0 , 231.1 ),
2479
+ HT_MCS_RATE (30 , 4 , 234.0 , 260.0 ), HT_MCS_RATE (31 , 4 , 260.0 , 288.9 ),
2480
+ };
2481
+
2482
+ /* Lookup data rate for given MCS index and GI */
2483
+ static float vwifi_get_mcs_rate (u8 mcs_index , enum vwifi_txrate_gi gi )
2484
+ {
2485
+ for (int i = 0 ; i < ARRAY_SIZE (ht_mcs_table ); i ++ ) {
2486
+ if (ht_mcs_table [i ].mcs_index == mcs_index )
2487
+ return (gi == VWIFI_TXRATE_GI_800NS ) ? ht_mcs_table [i ].rate_800ns
2488
+ : ht_mcs_table [i ].rate_400ns ;
2489
+ }
2490
+ return 6.5 ; /* Default to MCS 0, 0.8 µs GI */
2491
+ }
2492
+
2407
2493
static struct ieee80211_supported_band nf_band_2ghz = {
2408
2494
.band = NL80211_BAND_2GHZ ,
2409
2495
.channels = vwifi_supported_channels_2ghz ,
0 commit comments