@@ -75,6 +75,16 @@ static DEFINE_SPINLOCK(vif_list_lock);
7575/* SME stands for "station management entity" */
7676enum sme_state { SME_DISCONNECTED , SME_CONNECTING , SME_CONNECTED };
7777
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+
7888/* Each virtual interface contains a wiphy, vwifi_wiphy_counter is responsible
7989 * for recording the number of wiphy in vwifi.
8090 */
@@ -90,6 +100,8 @@ struct vwifi_vif {
90100 struct net_device_stats stats ;
91101 int manual_mcs ;
92102 bool manual_mcs_set ;
103+ struct cfg80211_bitrate_mask bitrate_mask ;
104+ enum vwifi_txrate_gi gi ; /* for GI tracking */
93105
94106 size_t ssid_len ;
95107 /* Currently connected BSS id */
@@ -1443,50 +1455,18 @@ static int vwifi_get_station(struct wiphy *wiphy,
14431455 int mcs_index ;
14441456 const char * modulation ;
14451457 const char * coding_rate ;
1458+
1459+ /* Select MCS dynamically or use manual settings */
14461460 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+ }
14871469 }
1488- pr_info ("vwifi: Station %pM using manual MCS %d (%s, %s)\n" , mac ,
1489- mcs_index , modulation , coding_rate );
14901470 } else {
14911471 if (sinfo -> signal > -45 ) {
14921472 mcs_index = 31 ;
@@ -1521,20 +1501,93 @@ static int vwifi_get_station(struct wiphy *wiphy,
15211501 modulation = "BPSK" ;
15221502 coding_rate = "1/2" ;
15231503 }
1524- pr_info ("vwifi: Station %pM signal %d dBm, using MCS %d (%s, %s)\n" ,
1525- mac , sinfo -> signal , mcs_index , modulation , coding_rate );
15261504 }
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+
15271575 /* Configure RX and TX rates */
15281576 sinfo -> rxrate .flags = RATE_INFO_FLAGS_MCS ;
1577+ if (vif -> gi == VWIFI_TXRATE_GI_400NS )
1578+ sinfo -> rxrate .flags |= RATE_INFO_FLAGS_SHORT_GI ;
15291579 sinfo -> rxrate .mcs = mcs_index ;
15301580 sinfo -> rxrate .bw = RATE_INFO_BW_20 ;
15311581 sinfo -> rxrate .n_bonded_ch = 1 ;
15321582
15331583 sinfo -> txrate .flags = RATE_INFO_FLAGS_MCS ;
1584+ if (vif -> gi == VWIFI_TXRATE_GI_400NS )
1585+ sinfo -> txrate .flags |= RATE_INFO_FLAGS_SHORT_GI ;
15341586 sinfo -> txrate .mcs = mcs_index ;
15351587 sinfo -> txrate .bw = RATE_INFO_BW_20 ;
15361588 sinfo -> txrate .n_bonded_ch = 1 ;
15371589
1590+
15381591 /* Log rate configuration for verification */
15391592 pr_info ("vwifi: Station %pM txrate MCS %d, rxrate MCS %d\n" , mac ,
15401593 sinfo -> txrate .mcs , sinfo -> rxrate .mcs );
@@ -1550,9 +1603,13 @@ static int vwifi_dump_station(struct wiphy *wiphy,
15501603{
15511604 struct vwifi_vif * ap_vif = ndev_get_vwifi_vif (dev );
15521605
1606+ if (!ap_vif ) {
1607+ pr_err ("vwifi: Failed to get ap_vif for dev %s\n" , dev -> name );
1608+ return - EINVAL ;
1609+ }
1610+
15531611 pr_info ("Dump station at the idx %d\n" , idx );
15541612
1555- int ret = - ENONET ;
15561613 struct vwifi_vif * sta_vif = NULL ;
15571614 int i = 0 ;
15581615
@@ -1564,10 +1621,9 @@ static int vwifi_dump_station(struct wiphy *wiphy,
15641621 break ;
15651622 }
15661623
1567- if (sta_vif == ap_vif )
1568- return ret ;
1569-
1570- ret = 0 ;
1624+ if (!sta_vif ) {
1625+ return - ENONET ;
1626+ }
15711627
15721628 memcpy (mac , sta_vif -> ndev -> dev_addr , ETH_ALEN );
15731629 return vwifi_get_station (wiphy , dev , mac , sinfo );
@@ -2265,6 +2321,7 @@ static int vwifi_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
22652321
22662322 return 0 ;
22672323}
2324+
22682325/* Callback to handle manual bitrate configuration via iw */
22692326static int vwifi_set_bitrate_mask (struct wiphy * wiphy ,
22702327 struct net_device * dev ,
@@ -2273,18 +2330,13 @@ static int vwifi_set_bitrate_mask(struct wiphy *wiphy,
22732330 const struct cfg80211_bitrate_mask * mask )
22742331{
22752332 struct vwifi_vif * vif = netdev_priv (dev );
2276- int mcs_index = -1 ;
2333+ int i ;
22772334
22782335 if (!vif ) {
22792336 pr_err ("vwifi: Failed to get vwifi_vif for dev %s\n" , dev -> name );
22802337 return - EINVAL ;
22812338 }
22822339
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-
22882340 pr_info ("vwifi: set_bitrate_mask called for dev %s, link_id %u, peer %pM\n" ,
22892341 dev -> name , link_id , peer ? peer : vif -> bssid );
22902342 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,
22932345 mask -> control [NL80211_BAND_2GHZ ].ht_mcs [2 ],
22942346 mask -> control [NL80211_BAND_2GHZ ].ht_mcs [3 ]);
22952347
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 );
23102350
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 ];
23152354
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+ }
23202363 }
23212364
2322- vif -> manual_mcs = mcs_index ;
23232365 vif -> manual_mcs_set = true;
2324- pr_info ("vwifi: Set manual MCS %d for dev %s\n" , mcs_index , dev -> name );
2325-
23262366 return 0 ;
23272367}
23282368
@@ -2373,6 +2413,13 @@ static struct cfg80211_ops vwifi_cfg_ops = {
23732413 .bitrate = (_rate), .hw_value = (_hw_value), \
23742414 }
23752415
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+
23762423/* Array of "supported" channels in 2GHz band. It is required for wiphy. */
23772424static const struct ieee80211_channel vwifi_supported_channels_2ghz [] = {
23782425 CHAN_2GHZ (1 , 2412 ), CHAN_2GHZ (2 , 2417 ), CHAN_2GHZ (3 , 2422 ),
@@ -2404,6 +2451,45 @@ static const struct ieee80211_rate vwifi_supported_rates[] = {
24042451 RATE_ENT (360 , 0x200 ), RATE_ENT (480 , 0x400 ), RATE_ENT (540 , 0x800 ),
24052452};
24062453
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+
24072493static struct ieee80211_supported_band nf_band_2ghz = {
24082494 .band = NL80211_BAND_2GHZ ,
24092495 .channels = vwifi_supported_channels_2ghz ,
0 commit comments