@@ -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 );
@@ -2254,6 +2310,7 @@ static int vwifi_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
22542310
22552311 return 0 ;
22562312}
2313+
22572314/* Callback to handle manual bitrate configuration via iw */
22582315static int vwifi_set_bitrate_mask (struct wiphy * wiphy ,
22592316 struct net_device * dev ,
@@ -2262,18 +2319,13 @@ static int vwifi_set_bitrate_mask(struct wiphy *wiphy,
22622319 const struct cfg80211_bitrate_mask * mask )
22632320{
22642321 struct vwifi_vif * vif = netdev_priv (dev );
2265- int mcs_index = -1 ;
2322+ int i ;
22662323
22672324 if (!vif ) {
22682325 pr_err ("vwifi: Failed to get vwifi_vif for dev %s\n" , dev -> name );
22692326 return - EINVAL ;
22702327 }
22712328
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-
22772329 pr_info ("vwifi: set_bitrate_mask called for dev %s, link_id %u, peer %pM\n" ,
22782330 dev -> name , link_id , peer ? peer : vif -> bssid );
22792331 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,
22822334 mask -> control [NL80211_BAND_2GHZ ].ht_mcs [2 ],
22832335 mask -> control [NL80211_BAND_2GHZ ].ht_mcs [3 ]);
22842336
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 );
22992339
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 ];
23042343
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+ }
23092352 }
23102353
2311- vif -> manual_mcs = mcs_index ;
23122354 vif -> manual_mcs_set = true;
2313- pr_info ("vwifi: Set manual MCS %d for dev %s\n" , mcs_index , dev -> name );
2314-
23152355 return 0 ;
23162356}
23172357
@@ -2362,6 +2402,13 @@ static struct cfg80211_ops vwifi_cfg_ops = {
23622402 .bitrate = (_rate), .hw_value = (_hw_value), \
23632403 }
23642404
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+
23652412/* Array of "supported" channels in 2GHz band. It is required for wiphy. */
23662413static const struct ieee80211_channel vwifi_supported_channels_2ghz [] = {
23672414 CHAN_2GHZ (1 , 2412 ), CHAN_2GHZ (2 , 2417 ), CHAN_2GHZ (3 , 2422 ),
@@ -2393,6 +2440,45 @@ static const struct ieee80211_rate vwifi_supported_rates[] = {
23932440 RATE_ENT (360 , 0x200 ), RATE_ENT (480 , 0x400 ), RATE_ENT (540 , 0x800 ),
23942441};
23952442
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+
23962482static struct ieee80211_supported_band nf_band_2ghz = {
23972483 .band = NL80211_BAND_2GHZ ,
23982484 .channels = vwifi_supported_channels_2ghz ,
0 commit comments