@@ -88,6 +88,8 @@ struct vwifi_vif {
8888 struct wireless_dev wdev ;
8989 struct net_device * ndev ;
9090 struct net_device_stats stats ;
91+ int manual_mcs ;
92+ bool manual_mcs_set ;
9193
9294 size_t ssid_len ;
9395 /* Currently connected BSS id */
@@ -1436,38 +1438,52 @@ static int vwifi_get_station(struct wiphy *wiphy,
14361438 * https://semfionetworks.com/blog/mcs-table-updated-with-80211ax-data-rates/
14371439 * IEEE 802.11n : https://zh.wikipedia.org/zh-tw/IEEE_802.11n
14381440 */
1439- /* Log byte counters for debugging */
1440- pr_info ("vwifi: Station %pM tx_bytes %llu, rx_bytes %llu\n" , mac ,
1441- sinfo -> tx_bytes , sinfo -> rx_bytes );
1442-
1443- /* Dynamic modulation based on signal strength */
1441+ /* Checks vif->manual_mcs_set to use vif->manual_mcs if set;
1442+ * Assign modulation string for manual MCS ; else auto change based
1443+ * on signal strength
1444+ */
14441445 int mcs_index ;
14451446 const char * modulation ;
1446- unsigned int data_rate_mbps ;
1447- if (sinfo -> signal > -50 ) {
1448- /* Strong signal: 64-QAM, MCS 31 */
1449- mcs_index = 31 ;
1450- modulation = "64-QAM" ;
1451- } else if (sinfo -> signal > -70 && sinfo -> signal <= -50 ) {
1452- /* Medium signal: 16-QAM, MCS 23 */
1453- mcs_index = 23 ;
1454- modulation = "16-QAM" ;
1455- } else if (sinfo -> signal > -90 && sinfo -> signal <= -70 ) {
1456- /* Weak signal: QPSK, MCS 15 */
1457- mcs_index = 15 ;
1458- modulation = "QPSK" ;
1447+ if (vif -> manual_mcs_set ) {
1448+ mcs_index = vif -> manual_mcs ;
1449+ switch (mcs_index ) {
1450+ case 7 :
1451+ modulation = "BPSK" ;
1452+ break ;
1453+ case 15 :
1454+ modulation = "QPSK" ;
1455+ break ;
1456+ case 23 :
1457+ modulation = "16-QAM" ;
1458+ break ;
1459+ case 31 :
1460+ modulation = "64-QAM" ;
1461+ break ;
1462+ default :
1463+ modulation = "Unknown" ;
1464+ break ;
1465+ }
1466+ pr_info ("vwifi: Station %pM using manual MCS %d (%s)\n" , mac , mcs_index ,
1467+ modulation );
14591468 } else {
1460- /* Very weak signal: BPSK, MCS 7 */
1461- mcs_index = 7 ;
1462- modulation = "BPSK" ;
1469+ if (sinfo -> signal > -50 ) {
1470+ mcs_index = 31 ;
1471+ modulation = "64-QAM" ;
1472+ } else if (sinfo -> signal > -70 && sinfo -> signal <= -50 ) {
1473+ mcs_index = 23 ;
1474+ modulation = "16-QAM" ;
1475+ } else if (sinfo -> signal > -90 && sinfo -> signal <= -70 ) {
1476+ mcs_index = 15 ;
1477+ modulation = "QPSK" ;
1478+ } else {
1479+ mcs_index = 7 ;
1480+ modulation = "BPSK" ;
1481+ }
1482+ pr_info (
1483+ "vwifi: Station %pM signal %d dBm, using modulation %s (MCS %d)\n" ,
1484+ mac , sinfo -> signal , modulation , mcs_index );
14631485 }
14641486
1465- /* Log signal, modulation, and data rate for debugging */
1466- pr_info (
1467- "vwifi: Station %pM signal %d dBm, using modulation %s (MCS %d, %u "
1468- "Mbps)\n" ,
1469- mac , sinfo -> signal , modulation , mcs_index , data_rate_mbps );
1470-
14711487 /* Configure RX and TX rates */
14721488 sinfo -> rxrate .flags = RATE_INFO_FLAGS_MCS ;
14731489 sinfo -> rxrate .mcs = mcs_index ;
@@ -2199,6 +2215,66 @@ static int vwifi_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
21992215
22002216 return 0 ;
22012217}
2218+ /* Callback to handle manual bitrate configuration via iw */
2219+ static int vwifi_set_bitrate_mask (struct wiphy * wiphy ,
2220+ struct net_device * dev ,
2221+ unsigned int link_id ,
2222+ const u8 * peer ,
2223+ const struct cfg80211_bitrate_mask * mask )
2224+ {
2225+ struct vwifi_vif * vif = netdev_priv (dev );
2226+ int mcs_index = -1 ;
2227+
2228+ if (!vif ) {
2229+ pr_err ("vwifi: Failed to get vwifi_vif for dev %s\n" , dev -> name );
2230+ return - EINVAL ;
2231+ }
2232+
2233+ if (vif -> sme_state != SME_CONNECTED ) {
2234+ pr_err ("vwifi: Dev %s not connected, cannot set bitrate\n" , dev -> name );
2235+ return - EINVAL ;
2236+ }
2237+
2238+ pr_info ("vwifi: set_bitrate_mask called for dev %s, link_id %u, peer %pM\n" ,
2239+ dev -> name , link_id , peer ? peer : vif -> bssid );
2240+ pr_info ("vwifi: 2.4GHz MCS mask: %02x %02x %02x %02x\n" ,
2241+ mask -> control [NL80211_BAND_2GHZ ].ht_mcs [0 ],
2242+ mask -> control [NL80211_BAND_2GHZ ].ht_mcs [1 ],
2243+ mask -> control [NL80211_BAND_2GHZ ].ht_mcs [2 ],
2244+ mask -> control [NL80211_BAND_2GHZ ].ht_mcs [3 ]);
2245+
2246+ /* Find the requested MCS index */
2247+ for (int i = 0 ; i < 4 ; i ++ ) {
2248+ if (mask -> control [NL80211_BAND_2GHZ ].ht_mcs [i ]) {
2249+ for (int j = 0 ; j < 8 ; j ++ ) {
2250+ if (mask -> control [NL80211_BAND_2GHZ ].ht_mcs [i ] & (1 << j )) {
2251+ mcs_index = i * 8 + j ;
2252+ pr_info ("vwifi: Requested MCS index %d\n" , mcs_index );
2253+ break ;
2254+ }
2255+ }
2256+ if (mcs_index != -1 )
2257+ break ;
2258+ }
2259+ }
2260+
2261+ if (mcs_index == -1 ) {
2262+ pr_err ("vwifi: No valid MCS index found\n" );
2263+ return - EINVAL ;
2264+ }
2265+
2266+ if (mcs_index != 7 && mcs_index != 15 && mcs_index != 23 &&
2267+ mcs_index != 31 ) {
2268+ pr_err ("vwifi: Unsupported MCS index %d\n" , mcs_index );
2269+ return - EINVAL ;
2270+ }
2271+
2272+ vif -> manual_mcs = mcs_index ;
2273+ vif -> manual_mcs_set = true;
2274+ pr_info ("vwifi: Set manual MCS %d for dev %s\n" , mcs_index , dev -> name );
2275+
2276+ return 0 ;
2277+ }
22022278
22032279/* Structure of functions for FullMAC 80211 drivers. Functions implemented
22042280 * along with fields/flags in the wiphy structure represent driver features.
@@ -2224,6 +2300,7 @@ static struct cfg80211_ops vwifi_cfg_ops = {
22242300 .get_tx_power = vwifi_get_tx_power ,
22252301 .join_ibss = vwifi_join_ibss ,
22262302 .leave_ibss = vwifi_leave_ibss ,
2303+ .set_bitrate_mask = vwifi_set_bitrate_mask ,
22272304};
22282305
22292306/* Macro for defining 2GHZ channel array */
@@ -2276,10 +2353,29 @@ static const struct ieee80211_rate vwifi_supported_rates[] = {
22762353 RATE_ENT (120 , 0x40 ), RATE_ENT (180 , 0x80 ), RATE_ENT (240 , 0x100 ),
22772354 RATE_ENT (360 , 0x200 ), RATE_ENT (480 , 0x400 ), RATE_ENT (540 , 0x800 ),
22782355};
2279-
22802356/* Describes supported band of 2GHz. */
2281- static struct ieee80211_supported_band nf_band_2ghz ;
2282-
2357+ static struct ieee80211_supported_band nf_band_2ghz = {
2358+ .band = NL80211_BAND_2GHZ ,
2359+ .channels = vwifi_supported_channels_2ghz ,
2360+ .n_channels = ARRAY_SIZE (vwifi_supported_channels_2ghz ),
2361+ .bitrates = vwifi_supported_rates ,
2362+ .n_bitrates = ARRAY_SIZE (vwifi_supported_rates ),
2363+ .ht_cap =
2364+ {
2365+ .ht_supported = true,
2366+ .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_GRN_FLD |
2367+ IEEE80211_HT_CAP_MAX_AMSDU |
2368+ IEEE80211_HT_CAP_SUP_WIDTH_20_40 ,
2369+ .mcs =
2370+ {
2371+ .rx_mask = {0xff , 0xff , 0xff , 0xff }, /* MCS 0-31 */
2372+ .rx_highest = cpu_to_le16 (300 ),
2373+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED ,
2374+ },
2375+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K ,
2376+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16 ,
2377+ },
2378+ };
22832379/* Describes supported band of 5GHz. */
22842380static struct ieee80211_supported_band nf_band_5ghz ;
22852381
0 commit comments