@@ -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 );
@@ -2254,6 +2310,7 @@ static int vwifi_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
2254
2310
2255
2311
return 0 ;
2256
2312
}
2313
+
2257
2314
/* Callback to handle manual bitrate configuration via iw */
2258
2315
static int vwifi_set_bitrate_mask (struct wiphy * wiphy ,
2259
2316
struct net_device * dev ,
@@ -2262,18 +2319,13 @@ static int vwifi_set_bitrate_mask(struct wiphy *wiphy,
2262
2319
const struct cfg80211_bitrate_mask * mask )
2263
2320
{
2264
2321
struct vwifi_vif * vif = netdev_priv (dev );
2265
- int mcs_index = -1 ;
2322
+ int i ;
2266
2323
2267
2324
if (!vif ) {
2268
2325
pr_err ("vwifi: Failed to get vwifi_vif for dev %s\n" , dev -> name );
2269
2326
return - EINVAL ;
2270
2327
}
2271
2328
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
2329
pr_info ("vwifi: set_bitrate_mask called for dev %s, link_id %u, peer %pM\n" ,
2278
2330
dev -> name , link_id , peer ? peer : vif -> bssid );
2279
2331
pr_info ("vwifi: 2.4GHz MCS mask: %02x %02x %02x %02x\n" ,
@@ -2282,36 +2334,24 @@ static int vwifi_set_bitrate_mask(struct wiphy *wiphy,
2282
2334
mask -> control [NL80211_BAND_2GHZ ].ht_mcs [2 ],
2283
2335
mask -> control [NL80211_BAND_2GHZ ].ht_mcs [3 ]);
2284
2336
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
- }
2337
+ memset (vif -> bitrate_mask .control [NL80211_BAND_2GHZ ].ht_mcs , 0 ,
2338
+ IEEE80211_HT_MCS_MASK_LEN );
2299
2339
2300
- if (mcs_index == -1 ) {
2301
- pr_err ("vwifi: No valid MCS index found\n" );
2302
- return - EINVAL ;
2303
- }
2340
+ for (i = 0 ; i < IEEE80211_HT_MCS_MASK_LEN ; i ++ )
2341
+ vif -> bitrate_mask .control [NL80211_BAND_2GHZ ].ht_mcs [i ] =
2342
+ mask -> control [NL80211_BAND_2GHZ ].ht_mcs [i ];
2304
2343
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 ;
2344
+ vif -> gi = gi_mode ; /* Use gi module parameter */
2345
+ pr_info ("vwifi: Set GI to %s\n" , gi_mode ? "0.4µs" : "0.8µs" );
2346
+
2347
+ for (i = 0 ; i < 32 ; i ++ ) {
2348
+ if (vif -> bitrate_mask .control [NL80211_BAND_2GHZ ].ht_mcs [i / 8 ] &
2349
+ (1 << (i % 8 ))) {
2350
+ pr_info ("vwifi: Enabled MCS %d\n" , i );
2351
+ }
2309
2352
}
2310
2353
2311
- vif -> manual_mcs = mcs_index ;
2312
2354
vif -> manual_mcs_set = true;
2313
- pr_info ("vwifi: Set manual MCS %d for dev %s\n" , mcs_index , dev -> name );
2314
-
2315
2355
return 0 ;
2316
2356
}
2317
2357
@@ -2362,6 +2402,13 @@ static struct cfg80211_ops vwifi_cfg_ops = {
2362
2402
.bitrate = (_rate), .hw_value = (_hw_value), \
2363
2403
}
2364
2404
2405
+ /* Macro for HT MCS rate table */
2406
+ #define HT_MCS_RATE (_mcs , _ss , _rate_800ns , _rate_400ns ) \
2407
+ { \
2408
+ .mcs_index = (_mcs), .spatial_streams = (_ss), \
2409
+ .rate_800ns = (_rate_800ns), .rate_400ns = (_rate_400ns), \
2410
+ }
2411
+
2365
2412
/* Array of "supported" channels in 2GHz band. It is required for wiphy. */
2366
2413
static const struct ieee80211_channel vwifi_supported_channels_2ghz [] = {
2367
2414
CHAN_2GHZ (1 , 2412 ), CHAN_2GHZ (2 , 2417 ), CHAN_2GHZ (3 , 2422 ),
@@ -2393,6 +2440,45 @@ static const struct ieee80211_rate vwifi_supported_rates[] = {
2393
2440
RATE_ENT (360 , 0x200 ), RATE_ENT (480 , 0x400 ), RATE_ENT (540 , 0x800 ),
2394
2441
};
2395
2442
2443
+
2444
+ struct ht_mcs_rate {
2445
+ u8 mcs_index ;
2446
+ u8 spatial_streams ;
2447
+ float rate_800ns ; /* Mbps */
2448
+ float rate_400ns ; /* Mbps */
2449
+ };
2450
+
2451
+ /* HT MCS table for 20 MHz, 1–4 spatial streams, 0.8 µs and 0.4 µs GI */
2452
+ static const struct ht_mcs_rate ht_mcs_table [] = {
2453
+ HT_MCS_RATE (0 , 1 , 6.5 , 7.2 ), HT_MCS_RATE (1 , 1 , 13.0 , 14.4 ),
2454
+ HT_MCS_RATE (2 , 1 , 19.5 , 21.7 ), HT_MCS_RATE (3 , 1 , 26.0 , 28.9 ),
2455
+ HT_MCS_RATE (4 , 1 , 39.0 , 43.3 ), HT_MCS_RATE (5 , 1 , 52.0 , 57.8 ),
2456
+ HT_MCS_RATE (6 , 1 , 58.5 , 65.0 ), HT_MCS_RATE (7 , 1 , 65.0 , 72.2 ),
2457
+ HT_MCS_RATE (8 , 2 , 13.0 , 14.4 ), HT_MCS_RATE (9 , 2 , 26.0 , 28.9 ),
2458
+ HT_MCS_RATE (10 , 2 , 39.0 , 43.3 ), HT_MCS_RATE (11 , 2 , 52.0 , 57.8 ),
2459
+ HT_MCS_RATE (12 , 2 , 78.0 , 86.7 ), HT_MCS_RATE (13 , 2 , 104.0 , 115.6 ),
2460
+ HT_MCS_RATE (14 , 2 , 117.0 , 130.0 ), HT_MCS_RATE (15 , 2 , 130.0 , 144.4 ),
2461
+ HT_MCS_RATE (16 , 3 , 19.5 , 21.7 ), HT_MCS_RATE (17 , 3 , 39.0 , 43.3 ),
2462
+ HT_MCS_RATE (18 , 3 , 58.5 , 65.0 ), HT_MCS_RATE (19 , 3 , 78.0 , 86.7 ),
2463
+ HT_MCS_RATE (20 , 3 , 117.0 , 130.0 ), HT_MCS_RATE (21 , 3 , 156.0 , 173.3 ),
2464
+ HT_MCS_RATE (22 , 3 , 175.5 , 195.0 ), HT_MCS_RATE (23 , 3 , 195.0 , 216.7 ),
2465
+ HT_MCS_RATE (24 , 4 , 26.0 , 28.9 ), HT_MCS_RATE (25 , 4 , 52.0 , 57.8 ),
2466
+ HT_MCS_RATE (26 , 4 , 78.0 , 86.7 ), HT_MCS_RATE (27 , 4 , 104.0 , 115.6 ),
2467
+ HT_MCS_RATE (28 , 4 , 156.0 , 173.3 ), HT_MCS_RATE (29 , 4 , 208.0 , 231.1 ),
2468
+ HT_MCS_RATE (30 , 4 , 234.0 , 260.0 ), HT_MCS_RATE (31 , 4 , 260.0 , 288.9 ),
2469
+ };
2470
+
2471
+ /* Lookup data rate for given MCS index and GI */
2472
+ static float vwifi_get_mcs_rate (u8 mcs_index , enum vwifi_txrate_gi gi )
2473
+ {
2474
+ for (int i = 0 ; i < ARRAY_SIZE (ht_mcs_table ); i ++ ) {
2475
+ if (ht_mcs_table [i ].mcs_index == mcs_index )
2476
+ return (gi == VWIFI_TXRATE_GI_800NS ) ? ht_mcs_table [i ].rate_800ns
2477
+ : ht_mcs_table [i ].rate_400ns ;
2478
+ }
2479
+ return 6.5 ; /* Default to MCS 0, 0.8 µs GI */
2480
+ }
2481
+
2396
2482
static struct ieee80211_supported_band nf_band_2ghz = {
2397
2483
.band = NL80211_BAND_2GHZ ,
2398
2484
.channels = vwifi_supported_channels_2ghz ,
0 commit comments