[driver][wlan] Fix HT capability negotiation for Ralink
- Correct the false claim of LDPC for Ralink chipset
- Reflects the BlockAck Session buffer size of the Ralink chipset
- Enable a primitive negotiation on the BlockAck buffer size
between the originator (AP) and the responder (Client)
- Add warning notes and TODOs
APs from different vendors exhibited different behaviors in this regards.
Aruba AP has been most stringent. This CL unblocks that case.
As a result, Fuchsia with Ralink WiFi chipset can receive the HT MCS
frames sent from Aruba AP.
NET-232 #done
NET-208 #done
Change-Id: I8427bd38a01cd69783e1e3b82210f48622900105
diff --git a/drivers/wlan/mediatek/ralink/device.cpp b/drivers/wlan/mediatek/ralink/device.cpp
index 9345598..8a43179 100644
--- a/drivers/wlan/mediatek/ralink/device.cpp
+++ b/drivers/wlan/mediatek/ralink/device.cpp
@@ -2831,9 +2831,7 @@
uint8_t rate = 0; // Mbps * 2
uint8_t rate_tbl_idx = 255; // Init with invalid idx.
- if (phy_mode >= fbl::count_of(kDataRates)) {
- return rate;
- }
+ if (phy_mode >= fbl::count_of(kDataRates)) { return rate; }
switch (phy_mode) {
case PhyMode::kLegacyCck:
@@ -2885,9 +2883,7 @@
constexpr uint8_t subcarriers_data_20 = 52; // counts
rate = rate * subcarriers_data_40 / subcarriers_data_20;
}
- if (is_sgi) {
- rate = static_cast<uint8_t>((static_cast<uint16_t>(rate) * 10) / 9);
- }
+ if (is_sgi) { rate = static_cast<uint8_t>((static_cast<uint16_t>(rate) * 10) / 9); }
return rate;
}
@@ -2940,7 +2936,7 @@
info->chan_width = rxwi1.bw() ? WLAN_CHAN_WIDTH_40MHZ : WLAN_CHAN_WIDTH_20MHZ;
uint8_t phy_mode = rxwi1.phy_mode();
- bool is_ht = phy_mode == PhyMode::kHtMixMode || phy_mode == PhyMode::kHtMixMode;
+ bool is_ht = phy_mode == PhyMode::kHtMixMode || phy_mode == PhyMode::kHtGreenfield;
if (is_ht && rxwi1.mcs() < kMaxHtMcs) {
info->valid_fields |= WLAN_RX_INFO_VALID_MCS;
info->mcs = rxwi1.mcs();
@@ -3167,7 +3163,7 @@
if (pkt->packet_tail != nullptr) {
uint8_t* tail_data = static_cast<uint8_t*>(pkt->packet_tail->data);
std::memcpy(dest + pkt->packet_head->len, tail_data + pkt->tail_offset,
- pkt->packet_tail->len - pkt->tail_offset);
+ pkt->packet_tail->len - pkt->tail_offset);
}
}
@@ -3176,9 +3172,7 @@
size_t len = pkt->packet_head->len;
if (pkt->packet_tail != nullptr) {
- if (pkt->packet_tail->len < pkt->tail_offset) {
- return ZX_ERR_INVALID_ARGS;
- }
+ if (pkt->packet_tail->len < pkt->tail_offset) { return ZX_ERR_INVALID_ARGS; }
len += pkt->packet_tail->len - pkt->tail_offset;
}
@@ -3249,8 +3243,8 @@
}
txwi0.set_mcs(mcs);
- if (pkt->info.valid_fields & WLAN_TX_INFO_VALID_CHAN_WIDTH
- && pkt->info.chan_width == WLAN_CHAN_WIDTH_40MHZ) {
+ if (pkt->info.valid_fields & WLAN_TX_INFO_VALID_CHAN_WIDTH &&
+ pkt->info.chan_width == WLAN_CHAN_WIDTH_40MHZ) {
txwi0.set_bw(1); // for 40 Mhz
} else {
txwi0.set_bw(0); // for 20 Mhz
@@ -3268,13 +3262,20 @@
txwi0.set_phy_mode(PhyMode::kLegacyOfdm);
}
+ // TODO(porce): Incorporate this into pkt->info
+ // txwi0.set_phy_mode(PhyMode::kHtMixMode);
+
// The frame header is always in the packet head.
- auto wcid = LookupTxWcid(static_cast<const uint8_t*>(pkt->packet_head->data),
- pkt->packet_head->len);
+ auto wcid =
+ LookupTxWcid(static_cast<const uint8_t*>(pkt->packet_head->data), pkt->packet_head->len);
Txwi1& txwi1 = packet->txwi1;
txwi1.set_ack(0);
txwi1.set_nseq(0);
- txwi1.set_ba_win_size(0);
+
+ // TODO(porce): Study if BlockAck window size can change without resetting the radio
+ // upon completing the BlockAck session negotiation at MLME layer.
+ // Separate the workflow for the BlockAck originator case from the responder case.
+ txwi1.set_ba_win_size(64);
txwi1.set_wcid(wcid);
txwi1.set_mpdu_total_byte_count(len);
txwi1.set_tx_packet_id(10);
diff --git a/drivers/wlan/wlan/station.cpp b/drivers/wlan/wlan/station.cpp
index 1e448fc..23a0497 100644
--- a/drivers/wlan/wlan/station.cpp
+++ b/drivers/wlan/wlan/station.cpp
@@ -252,6 +252,7 @@
// request.
auto assoc = packet->mut_field<AssociationRequest>(sizeof(MgmtFrameHeader));
assoc->cap.set_ess(1);
+ assoc->cap.set_short_preamble(1);
assoc->listen_interval = 0;
ElementWriter w(assoc->elements,
packet->len() - sizeof(MgmtFrameHeader) - sizeof(AssociationRequest));
@@ -548,17 +549,24 @@
resp->action = action::BaAction::kAddBaResponse;
resp->dialog_token = addbar->dialog_token;
- // TODO(porce): Research this.
- // Use kSuccess to refuse, instead of kRefused.
- // Aruba APs are persistent in asking again after refusal.
- // resp->status_code = status_code::kRefused;
+ // TODO(porce): Implement DelBa as a response to AddBar for decline
+
+ // Note: Returning AddBaResponse with status_code::kRefused seems ineffective.
+ // ArubaAP is persistent not honoring that.
resp->status_code = status_code::kSuccess;
+ // TODO(porce): Query the radio chipset capability to build the response.
resp->params.set_amsdu(0);
resp->params.set_policy(BlockAckParameters::kImmediate);
resp->params.set_tid(addbar->params.tid());
- resp->params.set_buffer_size(addbar->params.buffer_size());
- resp->params.set_buffer_size(0);
+
+ // TODO(porce): Once chipset capability is ready, refactor below buffer_size
+ // calculation.
+ auto buffer_size_ap = addbar->params.buffer_size();
+ constexpr size_t buffer_size_ralink = 64;
+ auto buffer_size = (buffer_size_ap <= buffer_size_ralink) ? buffer_size_ap : buffer_size_ralink;
+ resp->params.set_buffer_size(buffer_size);
+
resp->timeout = addbar->timeout;
zx_status_t status = device_->SendWlan(std::move(packet));
@@ -1235,7 +1243,7 @@
HtCapabilities htc;
HtCapabilityInfo& hci = htc.ht_cap_info;
- hci.set_ldpc_coding_cap(1);
+ hci.set_ldpc_coding_cap(0); // Ralink RT5370 is incapable of LDPC.
hci.set_chan_width_set(HtCapabilityInfo::TWENTY_ONLY);
// hci.set_chan_width_set(HtCapabilityInfo::TWENTY_FORTY);
hci.set_sm_power_save(HtCapabilityInfo::DISABLED);