From 13f1771d4e0c827f0dcae0dccfb5c47042bfac31 Mon Sep 17 00:00:00 2001 From: dingsen-Greenhorn Date: Sun, 8 Jun 2025 04:16:49 +0800 Subject: [PATCH 1/4] Implement dynamic MCS selection based on signal strength in vWIFI driver This commit enhances the vWIFI driver by implementing dynamic Modulation and Coding Scheme (MCS) selection in the `vwifi_get_station` function, adjusting the MCS index based on signal strength After implement dynamic MCS can avoid TX power waste for a bad channel quality --- vwifi.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/vwifi.c b/vwifi.c index eebd149..b91f2e6 100644 --- a/vwifi.c +++ b/vwifi.c @@ -1403,8 +1403,19 @@ static int vwifi_get_station(struct wiphy *wiphy, sinfo->tx_failed = vif->stats.tx_dropped; sinfo->tx_bytes = vif->stats.tx_bytes; sinfo->rx_bytes = vif->stats.rx_bytes; + + + /* Log byte counters for debugging */ /* CHANGED */ + pr_info( + "vwifi: Station %pM tx_bytes %llu, rx_bytes %llu, tx_packets %u, " + "rx_packets %u, tx_failed %u\n", + mac, sinfo->tx_bytes, sinfo->rx_bytes, sinfo->tx_packets, + sinfo->rx_packets, sinfo->tx_failed); + /* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in dBm */ sinfo->signal = rand_int_smooth(-100, -30, jiffies); + pr_info("vwifi: Station %pM signal %d dBm (raw)\n", mac, + sinfo->signal); /* ADDED */ sinfo->inactive_time = jiffies_to_msecs(jiffies - vif->active_time); /* * Using 802.11n (HT) as the PHY, configure as follows: @@ -1425,18 +1436,58 @@ static int vwifi_get_station(struct wiphy *wiphy, * https://semfionetworks.com/blog/mcs-table-updated-with-80211ax-data-rates/ * IEEE 802.11n : https://zh.wikipedia.org/zh-tw/IEEE_802.11n */ - sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; - sinfo->rxrate.mcs = 31; + + + + /* Log byte counters for debugging */ + pr_info("vwifi: Station %pM tx_bytes %llu, rx_bytes %llu\n", mac, + sinfo->tx_bytes, sinfo->rx_bytes); + + /* Dynamic modulation based on signal strength */ + int mcs_index; + const char *modulation; + unsigned int data_rate_mbps; + if (sinfo->signal > -50) { + /* Strong signal: 64-QAM, MCS 31 */ + mcs_index = 31; + modulation = "64-QAM"; + } else if (sinfo->signal > -70 && sinfo->signal <= -50) { + /* Medium signal: 16-QAM, MCS 23 */ + mcs_index = 23; + modulation = "16-QAM"; + } else if (sinfo->signal > -90 && sinfo->signal <= -70) { + /* Weak signal: QPSK, MCS 15 */ + mcs_index = 15; + modulation = "QPSK"; + } else { + /* Very weak signal: BPSK, MCS 7 */ + mcs_index = 7; + modulation = "BPSK"; + } + + /* Log signal, modulation, and data rate for debugging */ + pr_info( + "vwifi: Station %pM signal %d dBm, using modulation %s (MCS %d, %u " + "Mbps)\n", + mac, sinfo->signal, modulation, mcs_index, data_rate_mbps); + + /* Configure RX and TX rates */ + sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS; + sinfo->rxrate.mcs = mcs_index; sinfo->rxrate.bw = RATE_INFO_BW_20; sinfo->rxrate.n_bonded_ch = 1; - sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; - sinfo->txrate.mcs = 31; + sinfo->txrate.flags = RATE_INFO_FLAGS_MCS; + sinfo->txrate.mcs = mcs_index; sinfo->txrate.bw = RATE_INFO_BW_20; sinfo->txrate.n_bonded_ch = 1; + + /* Log rate configuration for verification */ + pr_info("vwifi: Station %pM txrate MCS %d, rxrate MCS %d\n", mac, + sinfo->txrate.mcs, sinfo->rxrate.mcs); + return 0; } - /* dump station callback -- resume dump at index @idx */ static int vwifi_dump_station(struct wiphy *wiphy, struct net_device *dev, @@ -2191,6 +2242,7 @@ static struct cfg80211_ops vwifi_cfg_ops = { .center_freq = 5000 + (5 * (channel)), \ } + /* Macro for defining rate table */ #define RATE_ENT(_rate, _hw_value) \ { \ From fed10f612c8d74e72a6a33767a1b2b4e6024b44c Mon Sep 17 00:00:00 2001 From: dingsen-Greenhorn Date: Sun, 8 Jun 2025 23:14:02 +0800 Subject: [PATCH 2/4] Add manual MCS configuration via set_bitrate_mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement the set_bitrate_mask callback in cfg80211_ops to support manual MCS settings using `iw dev set bitrates ht-mcs-2.4 `, addressing reviewer feedback. Store the selected MCS in vwifi_vif->manual_mcs and track its state with vwifi_vif->manual_mcs_set. Support MCS indices 7, 15, 23, and 31, with validation and logging. Enable High Throughput (HT) in nf_band_2ghz with MCS 0–31, using IEEE80211_HT_CAP_SUP_WIDTH_20_40 for 20 MHz compatibility. Fix compilation errors by initializing rx_mask statically and removing const qualifiers from channel/rate arrays. Improve vwifi_connect to ensure stable association. Tested with `iw dev vw1 set bitrates ht-mcs-2.4 15`, achieving MCS 15 at 130.0 MBit/s (bitrate calculation pending refinement to ~52 MBit/s). Test commands format $sudo ip netns exec ns1 iw dev vw1 link $sudo ip netns exec ns1 iw dev vw1 set bitrates ht-mcs-2.4 15 /*(changable 7,15,23,31)*/ $sudo ip netns exec ns1 iw dev vw1 link --- scripts/hostapd.conf | 4 +- vwifi.c | 166 +++++++++++++++++++++++++++++++++---------- 2 files changed, 130 insertions(+), 40 deletions(-) diff --git a/scripts/hostapd.conf b/scripts/hostapd.conf index e55bb22..bdae256 100644 --- a/scripts/hostapd.conf +++ b/scripts/hostapd.conf @@ -2,7 +2,7 @@ interface=vw0 driver=nl80211 debug=1 ctrl_interface=/var/run/hostapd -ctrl_interface_group=0 +ctrl_interface_group=root channel=6 ssid=test wpa=2 @@ -12,4 +12,4 @@ wpa_pairwise=CCMP # Beacon interval (kibi-us : 1.024 ms) beacon_int=100 -dtim_period=1 \ No newline at end of file +dtim_period=1 diff --git a/vwifi.c b/vwifi.c index b91f2e6..384033f 100644 --- a/vwifi.c +++ b/vwifi.c @@ -88,6 +88,8 @@ struct vwifi_vif { struct wireless_dev wdev; struct net_device *ndev; struct net_device_stats stats; + int manual_mcs; /* ADDED: Store user-specified MCS */ + bool manual_mcs_set; /* ADDED: Flag to indicate manual MCS override */ size_t ssid_len; /* Currently connected BSS id */ @@ -1345,7 +1347,6 @@ static int vwifi_get_station(struct wiphy *wiphy, struct station_info *sinfo) { struct vwifi_vif *vif = ndev_get_vwifi_vif(dev); - bool found_sta = false; switch (dev->ieee80211_ptr->iftype) { case NL80211_IFTYPE_AP:; @@ -1439,38 +1440,52 @@ static int vwifi_get_station(struct wiphy *wiphy, - /* Log byte counters for debugging */ - pr_info("vwifi: Station %pM tx_bytes %llu, rx_bytes %llu\n", mac, - sinfo->tx_bytes, sinfo->rx_bytes); - - /* Dynamic modulation based on signal strength */ + /* Checks vif->manual_mcs_set to use vif->manual_mcs if set; + * Assigns modulation string for manual MCS ; else auto change based + * on signal strength + */ int mcs_index; const char *modulation; - unsigned int data_rate_mbps; - if (sinfo->signal > -50) { - /* Strong signal: 64-QAM, MCS 31 */ - mcs_index = 31; - modulation = "64-QAM"; - } else if (sinfo->signal > -70 && sinfo->signal <= -50) { - /* Medium signal: 16-QAM, MCS 23 */ - mcs_index = 23; - modulation = "16-QAM"; - } else if (sinfo->signal > -90 && sinfo->signal <= -70) { - /* Weak signal: QPSK, MCS 15 */ - mcs_index = 15; - modulation = "QPSK"; + if (vif->manual_mcs_set) { + mcs_index = vif->manual_mcs; + switch (mcs_index) { + case 7: + modulation = "BPSK"; + break; + case 15: + modulation = "QPSK"; + break; + case 23: + modulation = "16-QAM"; + break; + case 31: + modulation = "64-QAM"; + break; + default: + modulation = "Unknown"; + break; + } + pr_info("vwifi: Station %pM using manual MCS %d (%s)\n", mac, mcs_index, + modulation); } else { - /* Very weak signal: BPSK, MCS 7 */ - mcs_index = 7; - modulation = "BPSK"; + if (sinfo->signal > -50) { + mcs_index = 31; + modulation = "64-QAM"; + } else if (sinfo->signal > -70 && sinfo->signal <= -50) { + mcs_index = 23; + modulation = "16-QAM"; + } else if (sinfo->signal > -90 && sinfo->signal <= -70) { + mcs_index = 15; + modulation = "QPSK"; + } else { + mcs_index = 7; + modulation = "BPSK"; + } + pr_info( + "vwifi: Station %pM signal %d dBm, using modulation %s (MCS %d)\n", + mac, sinfo->signal, modulation, mcs_index); } - /* Log signal, modulation, and data rate for debugging */ - pr_info( - "vwifi: Station %pM signal %d dBm, using modulation %s (MCS %d, %u " - "Mbps)\n", - mac, sinfo->signal, modulation, mcs_index, data_rate_mbps); - /* Configure RX and TX rates */ sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS; sinfo->rxrate.mcs = mcs_index; @@ -1728,13 +1743,8 @@ static int vwifi_start_ap(struct wiphy *wiphy, /* Initialize hrtimer of beacon */ pr_info("vwifi: init beacon_timer.\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) - hrtimer_setup(&vif->beacon_timer, vwifi_beacon, CLOCK_MONOTONIC, - HRTIMER_MODE_ABS_SOFT); -#else hrtimer_init(&vif->beacon_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_SOFT); vif->beacon_timer.function = vwifi_beacon; -#endif if (!hrtimer_is_queued(&vif->beacon_timer)) { u64 tsf, until_tbtt; @@ -2201,6 +2211,66 @@ static int vwifi_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) return 0; } +/* Callback to handle manual bitrate configuration via iw */ +static int vwifi_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + unsigned int link_id, + const u8 *peer, + const struct cfg80211_bitrate_mask *mask) +{ + struct vwifi_vif *vif = netdev_priv(dev); + int mcs_index = -1; + + if (!vif) { + pr_err("vwifi: Failed to get vwifi_vif for dev %s\n", dev->name); + return -EINVAL; + } + + if (vif->sme_state != SME_CONNECTED) { + pr_err("vwifi: Dev %s not connected, cannot set bitrate\n", dev->name); + return -EINVAL; + } + + pr_info("vwifi: set_bitrate_mask called for dev %s, link_id %u, peer %pM\n", + dev->name, link_id, peer ? peer : vif->bssid); + pr_info("vwifi: 2.4GHz MCS mask: %02x %02x %02x %02x\n", + mask->control[NL80211_BAND_2GHZ].ht_mcs[0], + mask->control[NL80211_BAND_2GHZ].ht_mcs[1], + mask->control[NL80211_BAND_2GHZ].ht_mcs[2], + mask->control[NL80211_BAND_2GHZ].ht_mcs[3]); + + /* Find the requested MCS index */ + for (int i = 0; i < 4; i++) { + if (mask->control[NL80211_BAND_2GHZ].ht_mcs[i]) { + for (int j = 0; j < 8; j++) { + if (mask->control[NL80211_BAND_2GHZ].ht_mcs[i] & (1 << j)) { + mcs_index = i * 8 + j; + pr_info("vwifi: Requested MCS index %d\n", mcs_index); + break; + } + } + if (mcs_index != -1) + break; + } + } + + if (mcs_index == -1) { + pr_err("vwifi: No valid MCS index found\n"); + return -EINVAL; + } + + if (mcs_index != 7 && mcs_index != 15 && mcs_index != 23 && + mcs_index != 31) { + pr_err("vwifi: Unsupported MCS index %d\n", mcs_index); + return -EINVAL; + } + + vif->manual_mcs = mcs_index; + vif->manual_mcs_set = true; + pr_info("vwifi: Set manual MCS %d for dev %s\n", mcs_index, dev->name); + + return 0; +} /* Structure of functions for FullMAC 80211 drivers. Functions implemented * along with fields/flags in the wiphy structure represent driver features. @@ -2226,6 +2296,7 @@ static struct cfg80211_ops vwifi_cfg_ops = { .get_tx_power = vwifi_get_tx_power, .join_ibss = vwifi_join_ibss, .leave_ibss = vwifi_leave_ibss, + .set_bitrate_mask = vwifi_set_bitrate_mask, }; /* Macro for defining 2GHZ channel array */ @@ -2250,7 +2321,7 @@ static struct cfg80211_ops vwifi_cfg_ops = { } /* Array of "supported" channels in 2GHz band. It is required for wiphy. */ -static const struct ieee80211_channel vwifi_supported_channels_2ghz[] = { +static struct ieee80211_channel vwifi_supported_channels_2ghz[] = { CHAN_2GHZ(1, 2412), CHAN_2GHZ(2, 2417), CHAN_2GHZ(3, 2422), CHAN_2GHZ(4, 2427), CHAN_2GHZ(5, 2432), CHAN_2GHZ(6, 2437), CHAN_2GHZ(7, 2442), CHAN_2GHZ(8, 2447), CHAN_2GHZ(9, 2452), @@ -2273,16 +2344,35 @@ static const struct ieee80211_channel vwifi_supported_channels_5ghz[] = { /* Array of supported rates, required to support those next rates * for 2GHz and 5GHz band. */ -static const struct ieee80211_rate vwifi_supported_rates[] = { +static struct ieee80211_rate vwifi_supported_rates[] = { RATE_ENT(10, 0x1), RATE_ENT(20, 0x2), RATE_ENT(55, 0x4), RATE_ENT(110, 0x8), RATE_ENT(60, 0x10), RATE_ENT(90, 0x20), RATE_ENT(120, 0x40), RATE_ENT(180, 0x80), RATE_ENT(240, 0x100), RATE_ENT(360, 0x200), RATE_ENT(480, 0x400), RATE_ENT(540, 0x800), }; -/* Describes supported band of 2GHz. */ -static struct ieee80211_supported_band nf_band_2ghz; - +static struct ieee80211_supported_band nf_band_2ghz = { + .band = NL80211_BAND_2GHZ, + .channels = vwifi_supported_channels_2ghz, + .n_channels = ARRAY_SIZE(vwifi_supported_channels_2ghz), + .bitrates = vwifi_supported_rates, + .n_bitrates = ARRAY_SIZE(vwifi_supported_rates), + .ht_cap = + { + .ht_supported = true, + .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_GRN_FLD | + IEEE80211_HT_CAP_MAX_AMSDU | + IEEE80211_HT_CAP_SUP_WIDTH_20_40, + .mcs = + { + .rx_mask = {0xff, 0xff, 0xff, 0xff}, /* MCS 0-31 */ + .rx_highest = cpu_to_le16(300), + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, + }, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, + }, +}; /* Describes supported band of 5GHz. */ static struct ieee80211_supported_band nf_band_5ghz; From fe2deb6f05f02094a70498a19ef6e2f9cf276faa Mon Sep 17 00:00:00 2001 From: dingsen-Greenhorn Date: Mon, 9 Jun 2025 00:19:54 +0800 Subject: [PATCH 3/4] Fix the misalignment with previous code and redundant comment --- vwifi.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/vwifi.c b/vwifi.c index 384033f..d936032 100644 --- a/vwifi.c +++ b/vwifi.c @@ -88,9 +88,8 @@ struct vwifi_vif { struct wireless_dev wdev; struct net_device *ndev; struct net_device_stats stats; - int manual_mcs; /* ADDED: Store user-specified MCS */ - bool manual_mcs_set; /* ADDED: Flag to indicate manual MCS override */ - + int manual_mcs; + bool manual_mcs_set; size_t ssid_len; /* Currently connected BSS id */ u8 bssid[ETH_ALEN]; @@ -1406,7 +1405,7 @@ static int vwifi_get_station(struct wiphy *wiphy, sinfo->rx_bytes = vif->stats.rx_bytes; - /* Log byte counters for debugging */ /* CHANGED */ + /* Log byte counters for debugging */ pr_info( "vwifi: Station %pM tx_bytes %llu, rx_bytes %llu, tx_packets %u, " "rx_packets %u, tx_failed %u\n", @@ -1415,8 +1414,7 @@ static int vwifi_get_station(struct wiphy *wiphy, /* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in dBm */ sinfo->signal = rand_int_smooth(-100, -30, jiffies); - pr_info("vwifi: Station %pM signal %d dBm (raw)\n", mac, - sinfo->signal); /* ADDED */ + pr_info("vwifi: Station %pM signal %d dBm (raw)\n", mac, sinfo->signal); sinfo->inactive_time = jiffies_to_msecs(jiffies - vif->active_time); /* * Using 802.11n (HT) as the PHY, configure as follows: @@ -1743,8 +1741,13 @@ static int vwifi_start_ap(struct wiphy *wiphy, /* Initialize hrtimer of beacon */ pr_info("vwifi: init beacon_timer.\n"); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) + hrtimer_setup(&vif->beacon_timer, vwifi_beacon, CLOCK_MONOTONIC, + HRTIMER_MODE_ABS_SOFT); +#else hrtimer_init(&vif->beacon_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_SOFT); vif->beacon_timer.function = vwifi_beacon; +#endif if (!hrtimer_is_queued(&vif->beacon_timer)) { u64 tsf, until_tbtt; From af4eeb52e2d43ba0e1e86cdbd760bcdb736bae21 Mon Sep 17 00:00:00 2001 From: dingsen-Greenhorn Date: Thu, 12 Jun 2025 23:10:56 +0800 Subject: [PATCH 4/4] =?UTF-8?q?Expand=20MCS=20support=20manual=2024?= =?UTF-8?q?=E2=80=9331=20range=20for=204-stream?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the vwifi_set_bitrate_mask callback to support the full range of MCS indices 24 through 31, aligning with the 4-spatial-stream configuration in nf_band_2ghz. This change enabling support for manual MCS from 24-31 coding schemes (1/2, 3/4, 2/3, 5/6) and modulations (BPSK, QPSK,16-QAM, 64-QAM) as defined by the IEEE 802.11n specification. The callback now rejects indices outside 24–31, ensuring compliance with 4-stream capabilities and allowing comprehensive rate testing (26–260 Mbps). The auto MCS selection ,due to this function is based on only signal strength, while the MCS should construct with modulation and coding scheme ,which the coding scheme is related with BER (bite error rate),previous vWiFI only implement random signal strength.the bit error rate should also based on the channel state info. --- scripts/hostapd.conf | 2 +- vwifi.c | 57 +++++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/scripts/hostapd.conf b/scripts/hostapd.conf index bdae256..63a79da 100644 --- a/scripts/hostapd.conf +++ b/scripts/hostapd.conf @@ -2,7 +2,7 @@ interface=vw0 driver=nl80211 debug=1 ctrl_interface=/var/run/hostapd -ctrl_interface_group=root +ctrl_interface_group=0 channel=6 ssid=test wpa=2 diff --git a/vwifi.c b/vwifi.c index d936032..bb87962 100644 --- a/vwifi.c +++ b/vwifi.c @@ -1444,46 +1444,74 @@ static int vwifi_get_station(struct wiphy *wiphy, */ int mcs_index; const char *modulation; + const char *coding_rate; if (vif->manual_mcs_set) { mcs_index = vif->manual_mcs; switch (mcs_index) { - case 7: + case 24: modulation = "BPSK"; + coding_rate = "1/2"; break; - case 15: + case 25: modulation = "QPSK"; + coding_rate = "1/2"; break; - case 23: + case 26: + modulation = "QPSK"; + coding_rate = "3/4"; + break; + case 27: + modulation = "16-QAM"; + coding_rate = "1/2"; + break; + case 28: modulation = "16-QAM"; + coding_rate = "3/4"; + break; + case 29: + modulation = "64-QAM"; + coding_rate = "2/3"; + break; + case 30: + modulation = "64-QAM"; + coding_rate = "3/4"; break; case 31: modulation = "64-QAM"; + coding_rate = "5/6"; break; default: - modulation = "Unknown"; + pr_err("vwifi: Unsupported MCS index %d\n", mcs_index); + mcs_index = 24; /* Default to lowest 4-stream MCS */ + modulation = "BPSK"; + coding_rate = "1/2"; break; } - pr_info("vwifi: Station %pM using manual MCS %d (%s)\n", mac, mcs_index, - modulation); + pr_info("vwifi: Station %pM using manual MCS %d (%s, %s)\n", mac, + mcs_index, modulation, coding_rate); } else { if (sinfo->signal > -50) { mcs_index = 31; modulation = "64-QAM"; + coding_rate = "5/6"; } else if (sinfo->signal > -70 && sinfo->signal <= -50) { - mcs_index = 23; + mcs_index = 28; modulation = "16-QAM"; + coding_rate = "3/4"; } else if (sinfo->signal > -90 && sinfo->signal <= -70) { - mcs_index = 15; + mcs_index = 25; modulation = "QPSK"; + coding_rate = "1/2"; } else { - mcs_index = 7; + mcs_index = 24; modulation = "BPSK"; + coding_rate = "1/2"; } - pr_info( - "vwifi: Station %pM signal %d dBm, using modulation %s (MCS %d)\n", - mac, sinfo->signal, modulation, mcs_index); + pr_info("vwifi: Station %pM signal %d dBm, using MCS %d (%s, %s)\n", + mac, sinfo->signal, mcs_index, modulation, coding_rate); } + /* Configure RX and TX rates */ sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS; sinfo->rxrate.mcs = mcs_index; @@ -2215,6 +2243,7 @@ static int vwifi_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) return 0; } /* Callback to handle manual bitrate configuration via iw */ +/* Callback to handle manual bitrate configuration via iw */ static int vwifi_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, unsigned int link_id, @@ -2262,8 +2291,8 @@ static int vwifi_set_bitrate_mask(struct wiphy *wiphy, return -EINVAL; } - if (mcs_index != 7 && mcs_index != 15 && mcs_index != 23 && - mcs_index != 31) { + /* Restrict to supported 4-stream MCS indices 24–31 */ + if (mcs_index < 24 || mcs_index > 31) { pr_err("vwifi: Unsupported MCS index %d\n", mcs_index); return -EINVAL; }