From nobody Fri Dec 1 22:31:50 2023 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4ShnqC01DCz50mtg; Fri, 1 Dec 2023 22:31:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ShnqB6ysNz4Hjm; Fri, 1 Dec 2023 22:31:50 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1701469910; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=pWcif3y2fvYLF7QSPrxKr7eUc0W1UVYJMho/onusqXQ=; b=MO3MmlFv0m2bWaZ/DPz3kInsMQ5rBUhhdGKR1gd4qarnvHo6101cr0TDVFO+H7yyIFwRCN zoBpRRckmZ5d/xOeJBTKDRsKhX3Sv4RGAj3OmcrrCT1ysLVuvYlHbVXZnow0ANwr/FA2rX 8yrmxTx7lGJl/PaE/h8DOdve6ETHmAFeXkYhzJW3MOmrOkz0yy8v6PtLDOaMsNgmbNNdwq ij+U1A6zndj6CUUTX7M5iaWH8lKUJccVT5ulZdB1MS+uup62HjeS+bLhtyxEM6UbzcRZqJ 7tneH5Z/H2jaWckvNticWBba3vAMppX7C5o5/r7kYhCnmlVpt4gxcJB6GGQJog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1701469910; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=pWcif3y2fvYLF7QSPrxKr7eUc0W1UVYJMho/onusqXQ=; b=sXyfK4mh+D/OMlwaIO+QyAnRBD1bffsDL0o1JeswTT1dX5SfnjvfJYEF+0W/wl+/DZYKBx fq0C6UbwwU4DJ50NOeLv/b1NJzRa0DMKsPPQ6aGB/zSMh87yHEORWvocrdwofQLwfjXSxC Ta1kKY/HpOwARU9BV3oIX1zdugohKuJ/15QD9Yub/qrUeXHZoz6auop7pS+4UgiOLNTfgJ 6o2tNJDraqlPRB510MBpP6W95wd9NJRp5Ja/kdV1qInA2pGsZvTFMzMQXlEpuf1UKtwa/p BWUX0FD/EEQWAAIMZxihoCATl4bzys1xzUWHJjzRhXuNleUQu2lZ5fuVc7iSbg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1701469910; a=rsa-sha256; cv=none; b=VAyaVOs3Y41R95dAFhwcDZoXQNEy1KaCYhR0P2Sy1gVENWCAR6peyOA8TG42vzpIUkJrce Cn9DGZ0fXTx4Skn4SSlS9OPKJEpUZv0zZ9o6Ye6PbkJf1B1UnfrXtlbyP9iGmSSMymV3IF +YyLrPx1UU9BgtvsQwXzAJvvdjC1hR2SvP8x4uX66NUxyg9VQxv9gGWwVTbxiNuRAKEJ/y 1DF/GC1E0qOAqc1Iv9SFJMxB8c9sNf377M1KRssfhXh04uBwM8c5VsK5DhxzI03jx4hkWN iqt6lMWJ7CVUnl81UWMrvg3H5KVtNs8brL9mwI5vknkPEziKhY1vORDzCfJu2Q== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4ShnqB62c9zrym; Fri, 1 Dec 2023 22:31:50 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 3B1MVoCN089771; Fri, 1 Dec 2023 22:31:50 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 3B1MVo89089768; Fri, 1 Dec 2023 22:31:50 GMT (envelope-from git) Date: Fri, 1 Dec 2023 22:31:50 GMT Message-Id: <202312012231.3B1MVo89089768@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: 9fb914634eff - main - LinuxKPI: 802.11: bring in some HT code List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bz X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 9fb914634eff85b3b36bcbf39c1faf2967b0aa9e Auto-Submitted: auto-generated The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=9fb914634eff85b3b36bcbf39c1faf2967b0aa9e commit 9fb914634eff85b3b36bcbf39c1faf2967b0aa9e Author: Bjoern A. Zeeb AuthorDate: 2023-10-26 21:14:44 +0000 Commit: Bjoern A. Zeeb CommitDate: 2023-12-01 22:26:28 +0000 LinuxKPI: 802.11: bring in some HT code Fix defines and structures to use proper types. Bring in basic ni->sta synchronization, some channel width handling, and overload the net80211 functions so that we can talk to driver/firmware to setup parameters. We will likely not need one or two of those but it is good for tracing currently. Cover HT and bits of VHT code in LinuxKPI behind apropriate #ifdef which are currently not enabled (like LKPI_80211_HW_CRYPTO) until confirmed to work. Last, IEEE80211_AMPDU_RX_START made some firmware unhappy. This will allow others to work on it and test as well. Sponsored by: The FreeBSD Foundation MFC after: 10 days --- .../linuxkpi/common/include/linux/ieee80211.h | 3 +- sys/compat/linuxkpi/common/include/net/mac80211.h | 11 +- sys/compat/linuxkpi/common/src/linux_80211.c | 513 +++++++++++++++++++-- sys/compat/linuxkpi/common/src/linux_80211.h | 35 ++ .../linuxkpi/common/src/linux_80211_macops.c | 22 + 5 files changed, 550 insertions(+), 34 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/ieee80211.h b/sys/compat/linuxkpi/common/include/linux/ieee80211.h index 4648a12ec889..5c18bb9fe3d9 100644 --- a/sys/compat/linuxkpi/common/include/linux/ieee80211.h +++ b/sys/compat/linuxkpi/common/include/linux/ieee80211.h @@ -60,8 +60,7 @@ struct ieee80211_mmie_16 { #define IEEE80211_INVAL_HW_QUEUE ((uint8_t)-1) -#define IEEE80211_MAX_AMPDU_BUF 256 /* for HE? */ -#define IEEE80211_MAX_AMPDU_BUF_HT 64 +#define IEEE80211_MAX_AMPDU_BUF_HT IEEE80211_AGGR_BAWMAX #define IEEE80211_MAX_AMPDU_BUF_HE 256 #define IEEE80211_MAX_AMPDU_BUF_EHT 1024 diff --git a/sys/compat/linuxkpi/common/include/net/mac80211.h b/sys/compat/linuxkpi/common/include/net/mac80211.h index 7e6fb1bce16e..fa36bd84ac6e 100644 --- a/sys/compat/linuxkpi/common/include/net/mac80211.h +++ b/sys/compat/linuxkpi/common/include/net/mac80211.h @@ -175,11 +175,13 @@ struct ieee80211_sta; #define IEEE80211_HT_AMPDU_PARM_DENSITY (0x7 << IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) struct ieee80211_ampdu_params { - /* TODO FIXME */ struct ieee80211_sta *sta; - uint8_t tid; + enum ieee80211_ampdu_mlme_action action; + uint16_t buf_size; + uint16_t timeout; uint16_t ssn; - int action, amsdu, buf_size, timeout; + uint8_t tid; + bool amsdu; }; struct ieee80211_bar { @@ -452,7 +454,6 @@ struct ieee80211_hw { struct wiphy *wiphy; /* TODO FIXME */ - int max_rx_aggregation_subframes, max_tx_aggregation_subframes; int extra_tx_headroom, weight_multiplier; int max_rate_tries, max_rates, max_report_rates; struct ieee80211_cipher_scheme *cipher_schemes; @@ -472,6 +473,8 @@ struct ieee80211_hw { uint16_t offchannel_tx_hw_queue; uint16_t uapsd_max_sp_len; uint16_t uapsd_queues; + uint16_t max_rx_aggregation_subframes; + uint16_t max_tx_aggregation_subframes; uint16_t max_tx_fragments; uint16_t max_listen_interval; uint32_t extra_beacon_tailroom; diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index 448f417d1224..5f7528e994b6 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -61,6 +61,7 @@ #include #include #include +#include #define LINUXKPI_NET80211 #include @@ -70,6 +71,11 @@ #define LKPI_80211_WME /* #define LKPI_80211_HW_CRYPTO */ +/* #define LKPI_80211_VHT */ +/* #define LKPI_80211_HT */ +#if defined(LKPI_80211_VHT) && !defined(LKPI_80211_HT) +#define LKPI_80211_HT +#endif static MALLOC_DEFINE(M_LKPI80211, "lkpi80211", "LinuxKPI 80211 compat"); @@ -143,6 +149,79 @@ static void lkpi_ieee80211_free_skb_mbuf(void *); static int lkpi_wme_update(struct lkpi_hw *, struct ieee80211vap *, bool); #endif +#if defined(LKPI_80211_HT) +static void +lkpi_sta_sync_ht_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni, int *ht_rx_nss) +{ + struct ieee80211vap *vap; + uint8_t *ie; + struct ieee80211_ht_cap *htcap; + int i, rx_nss; + + if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) + return; + + if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && + IEEE80211_IS_CHAN_HT40(ni->ni_chan)) + sta->deflink.bandwidth = IEEE80211_STA_RX_BW_40; + + sta->deflink.ht_cap.ht_supported = true; + + /* htcap->ampdu_params_info */ + vap = ni->ni_vap; + sta->deflink.ht_cap.ampdu_density = _IEEE80211_MASKSHIFT(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY); + if (sta->deflink.ht_cap.ampdu_density > vap->iv_ampdu_density) + sta->deflink.ht_cap.ampdu_density = vap->iv_ampdu_density; + sta->deflink.ht_cap.ampdu_factor = _IEEE80211_MASKSHIFT(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU); + if (sta->deflink.ht_cap.ampdu_factor > vap->iv_ampdu_rxmax) + sta->deflink.ht_cap.ampdu_factor = vap->iv_ampdu_rxmax; + + ie = ni->ni_ies.htcap_ie; + KASSERT(ie != NULL, ("%s: HT but no htcap_ie on ni %p\n", __func__, ni)); + if (ie[0] == IEEE80211_ELEMID_VENDOR) + ie += 4; + ie += 2; + htcap = (struct ieee80211_ht_cap *)ie; + sta->deflink.ht_cap.cap = htcap->cap_info; + sta->deflink.ht_cap.mcs = htcap->mcs; + + rx_nss = 0; + for (i = 0; i < nitems(htcap->mcs.rx_mask); i++) { + if (htcap->mcs.rx_mask[i]) + rx_nss++; + } + if (ht_rx_nss != NULL) + *ht_rx_nss = rx_nss; + + IMPROVE("sta->wme, sta->deflink.agg.max*"); +} +#endif + +#if defined(LKPI_80211_VHT) +static void +lkpi_sta_sync_vht_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni, int *vht_rx_nss) +{ + + if ((ni->ni_flags & IEEE80211_NODE_VHT) == 0) + return; + + if (IEEE80211_IS_CHAN_VHT(ni->ni_chan)) { +#ifdef __notyet__ + if (IEEE80211_IS_CHAN_VHT80P80(ni->ni_chan)) { + sta->deflink.bandwidth = IEEE80211_STA_RX_BW_160; /* XXX? */ + } else +#endif + if (IEEE80211_IS_CHAN_VHT160(ni->ni_chan)) + sta->deflink.bandwidth = IEEE80211_STA_RX_BW_160; + else if (IEEE80211_IS_CHAN_VHT80(ni->ni_chan)) + sta->deflink.bandwidth = IEEE80211_STA_RX_BW_80; + } + + IMPROVE("VHT sync ni to sta"); + return; +} +#endif + static void lkpi_lsta_dump(struct lkpi_sta *lsta, struct ieee80211_node *ni, const char *_f, int _l) @@ -197,6 +276,8 @@ lkpi_lsta_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], struct ieee80211_vif *vif; struct ieee80211_sta *sta; int band, i, tid; + int ht_rx_nss; + int vht_rx_nss; lsta = malloc(sizeof(*lsta) + hw->sta_data_size, M_LKPI80211, M_NOWAIT | M_ZERO); @@ -266,9 +347,23 @@ lkpi_lsta_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], sta->deflink.supp_rates[band] |= BIT(i); } } + sta->deflink.smps_mode = IEEE80211_SMPS_OFF; - IMPROVE("ht, vht, he, ... bandwidth, smps_mode, .."); - /* bandwidth = IEEE80211_STA_RX_... */ + sta->deflink.bandwidth = IEEE80211_STA_RX_BW_20; + sta->deflink.rx_nss = 0; + + ht_rx_nss = 0; +#if defined(LKPI_80211_HT) + lkpi_sta_sync_ht_from_ni(sta, ni, &ht_rx_nss); +#endif + vht_rx_nss = 0; +#if defined(LKPI_80211_VHT) + lkpi_sta_sync_vht_from_ni(sta, ni, &vht_rx_nss); +#endif + + sta->deflink.rx_nss = MAX(ht_rx_nss, sta->deflink.rx_nss); + sta->deflink.rx_nss = MAX(vht_rx_nss, sta->deflink.rx_nss); + IMPROVE("he, ... smps_mode, .."); /* Link configuration. */ IEEE80211_ADDR_COPY(sta->deflink.addr, sta->addr); @@ -970,12 +1065,35 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int conf->def.width = NL80211_CHAN_WIDTH_20_NOHT; conf->def.center_freq1 = chan->center_freq; conf->def.center_freq2 = 0; + IMPROVE("Check vht_cap from band not just chan?"); +#ifdef LKPI_80211_HT + if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { + if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { + conf->def.width = NL80211_CHAN_WIDTH_40; + } else + conf->def.width = NL80211_CHAN_WIDTH_20; + } +#endif +#ifdef LKPI_80211_VHT + if (IEEE80211_IS_CHAN_VHT(ni->ni_chan)) { +#ifdef __notyet__ + if (IEEE80211_IS_CHAN_VHT80P80(ni->ni_chan)) { + conf->def.width = NL80211_CHAN_WIDTH_80P80; + conf->def.center_freq2 = 0; /* XXX */ + } else +#endif + if (IEEE80211_IS_CHAN_VHT160(ni->ni_chan)) + conf->def.width = NL80211_CHAN_WIDTH_160; + else if (IEEE80211_IS_CHAN_VHT80(ni->ni_chan)) + conf->def.width = NL80211_CHAN_WIDTH_80; + } +#endif /* Responder ... */ conf->min_def.chan = chan; conf->min_def.width = NL80211_CHAN_WIDTH_20_NOHT; conf->min_def.center_freq1 = chan->center_freq; conf->min_def.center_freq2 = 0; - IMPROVE("currently 20_NOHT only"); + IMPROVE("currently 20_NOHT min_def only"); /* Set bss info (bss_info_changed). */ bss_changed = 0; @@ -1008,6 +1126,15 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int vif->bss_conf.chandef.width = conf->def.width; vif->bss_conf.chandef.center_freq1 = conf->def.center_freq1; +#ifdef LKPI_80211_HT + if (vif->bss_conf.chandef.width == NL80211_CHAN_WIDTH_40) { + /* Note: it is 10 not 20. */ + if (IEEE80211_IS_CHAN_HT40U(ni->ni_chan)) + vif->bss_conf.chandef.center_freq1 += 10; + else if (IEEE80211_IS_CHAN_HT40D(ni->ni_chan)) + vif->bss_conf.chandef.center_freq1 -= 10; + } +#endif vif->bss_conf.chandef.center_freq2 = conf->def.center_freq2; } else { @@ -1650,6 +1777,11 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int IMPROVE("net80211 does not consider node authorized"); } +#if defined(LKPI_80211_HT) + IMPROVE("Is this the right spot, has net80211 done all updates already?"); + lkpi_sta_sync_ht_from_ni(sta, ni, NULL); +#endif + /* Update sta_state (ASSOC to AUTHORIZED). */ KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni)); KASSERT(lsta->state == IEEE80211_STA_ASSOC, ("%s: lsta %p state not " @@ -2463,6 +2595,10 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], #endif } +#ifdef LKPI_80211_HT + /* Stay with the iv_ampdu_rxmax,limit / iv_ampdu_density defaults until later. */ +#endif + ieee80211_ratectl_init(vap); /* Complete setup. */ @@ -3074,6 +3210,9 @@ lkpi_ic_set_channel(struct ieee80211com *ic) hw = LHW_TO_HW(lhw); cfg80211_chandef_create(&hw->conf.chandef, chan, +#ifdef LKPI_80211_HT + (ic->ic_htcaps & IEEE80211_HTC_HT) ? 0 : +#endif NL80211_CHAN_NO_HT); error = lkpi_80211_mo_config(hw, IEEE80211_CONF_CHANGE_CHANNEL); @@ -3362,6 +3501,13 @@ lkpi_80211_txq_tx_one(struct lkpi_sta *lsta, struct mbuf *m) info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO; info->control.vif = vif; /* XXX-BZ info->control.rates */ +#ifdef __notyet__ +#ifdef LKPI_80211_HT + info->control.rts_cts_rate_idx= + info->control.use_rts= /* RTS */ + info->control.use_cts_prot= /* RTS/CTS*/ +#endif +#endif lsta = lkpi_find_lsta_by_ni(lvif, ni); if (lsta != NULL) { @@ -3468,6 +3614,291 @@ lkpi_ic_transmit(struct ieee80211com *ic, struct mbuf *m) return (lkpi_ic_raw_xmit(ni, m, NULL)); } +#ifdef LKPI_80211_HT +static int +lkpi_ic_recv_action(struct ieee80211_node *ni, const struct ieee80211_frame *wh, + const uint8_t *frm, const uint8_t *efrm) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + + ic = ni->ni_ic; + lhw = ic->ic_softc; + + IMPROVE_HT(); + + return (lhw->ic_recv_action(ni, wh, frm, efrm)); +} + +static int +lkpi_ic_send_action(struct ieee80211_node *ni, int category, int action, void *sa) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + + ic = ni->ni_ic; + lhw = ic->ic_softc; + + IMPROVE_HT(); + + return (lhw->ic_send_action(ni, category, action, sa)); +} + + +static int +lkpi_ic_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + + ic = ni->ni_ic; + lhw = ic->ic_softc; + + IMPROVE_HT(); + + return (lhw->ic_ampdu_enable(ni, tap)); +} + +static int +lkpi_ic_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, + int dialogtoken, int baparamset, int batimeout) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + + ic = ni->ni_ic; + lhw = ic->ic_softc; + + IMPROVE_HT(); + + return (lhw->ic_addba_request(ni, tap, dialogtoken, baparamset, batimeout)); +} + +static int +lkpi_ic_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, + int status, int baparamset, int batimeout) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + + ic = ni->ni_ic; + lhw = ic->ic_softc; + + IMPROVE_HT(); + + return (lhw->ic_addba_response(ni, tap, status, baparamset, batimeout)); +} + +static void +lkpi_ic_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + + ic = ni->ni_ic; + lhw = ic->ic_softc; + + IMPROVE_HT(); + + lhw->ic_addba_stop(ni, tap); +} + +static void +lkpi_ic_addba_response_timeout(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + + ic = ni->ni_ic; + lhw = ic->ic_softc; + + IMPROVE_HT(); + + lhw->ic_addba_response_timeout(ni, tap); +} + +static void +lkpi_ic_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, + int status) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + + ic = ni->ni_ic; + lhw = ic->ic_softc; + + IMPROVE_HT(); + + lhw->ic_bar_response(ni, tap, status); +} + +static int +lkpi_ic_ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap, + int baparamset, int batimeout, int baseqctl) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + struct ieee80211_hw *hw; + struct ieee80211vap *vap; + struct lkpi_vif *lvif; + struct ieee80211_vif *vif; + struct lkpi_sta *lsta; + struct ieee80211_sta *sta; + struct ieee80211_ampdu_params params; + int error; + + ic = ni->ni_ic; + lhw = ic->ic_softc; + hw = LHW_TO_HW(lhw); + vap = ni->ni_vap; + lvif = VAP_TO_LVIF(vap); + vif = LVIF_TO_VIF(lvif); + lsta = ni->ni_drv_data; + sta = LSTA_TO_STA(lsta); + + params.sta = sta; + params.action = IEEE80211_AMPDU_RX_START; + params.buf_size = _IEEE80211_MASKSHIFT(le16toh(baparamset), IEEE80211_BAPS_BUFSIZ); + if (params.buf_size == 0) + params.buf_size = IEEE80211_MAX_AMPDU_BUF_HT; + else + params.buf_size = min(params.buf_size, IEEE80211_MAX_AMPDU_BUF_HT); + if (params.buf_size > hw->max_rx_aggregation_subframes) + params.buf_size = hw->max_rx_aggregation_subframes; + params.timeout = le16toh(batimeout); + params.ssn = _IEEE80211_MASKSHIFT(le16toh(baseqctl), IEEE80211_BASEQ_START); + params.tid = _IEEE80211_MASKSHIFT(le16toh(baparamset), IEEE80211_BAPS_TID); + params.amsdu = false; + + IMPROVE_HT("Do we need to distinguish based on SUPPORTS_REORDERING_BUFFER?"); + + /* This may call kalloc. Make sure we can sleep. */ + error = lkpi_80211_mo_ampdu_action(hw, vif, ¶ms); + if (error != 0) { + ic_printf(ic, "%s: mo_ampdu_action returned %d. ni %p rap %p\n", + __func__, error, ni, rap); + return (error); + } + IMPROVE_HT("net80211 is missing the error check on return and assumes success"); + + error = lhw->ic_ampdu_rx_start(ni, rap, baparamset, batimeout, baseqctl); + return (error); +} + +static void +lkpi_ic_ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + struct ieee80211_hw *hw; + struct ieee80211vap *vap; + struct lkpi_vif *lvif; + struct ieee80211_vif *vif; + struct lkpi_sta *lsta; + struct ieee80211_sta *sta; + struct ieee80211_ampdu_params params; + int error; + uint8_t tid; + + ic = ni->ni_ic; + lhw = ic->ic_softc; + + /* + * We should not (cannot) call into mac80211 ops with AMPDU_RX_STOP if + * we did not START. Some drivers pass it down to firmware which will + * simply barf and net80211 calls ieee80211_ht_node_cleanup() from + * ieee80211_ht_node_init() amongst others which will iterate over all + * tid and call ic_ampdu_rx_stop() unconditionally. + * XXX net80211 should probably be more "gentle" in these cases and + * track some state itself. + */ + if ((rap->rxa_flags & IEEE80211_AGGR_RUNNING) == 0) + goto net80211_only; + + hw = LHW_TO_HW(lhw); + vap = ni->ni_vap; + lvif = VAP_TO_LVIF(vap); + vif = LVIF_TO_VIF(lvif); + lsta = ni->ni_drv_data; + sta = LSTA_TO_STA(lsta); + + IMPROVE_HT("This really should be passed from ht_recv_action_ba_delba."); + for (tid = 0; tid < WME_NUM_TID; tid++) { + if (&ni->ni_rx_ampdu[tid] == rap) + break; + } + + params.sta = sta; + params.action = IEEE80211_AMPDU_RX_STOP; + params.buf_size = 0; + params.timeout = 0; + params.ssn = 0; + params.tid = tid; + params.amsdu = false; + + error = lkpi_80211_mo_ampdu_action(hw, vif, ¶ms); + if (error != 0) + ic_printf(ic, "%s: mo_ampdu_action returned %d. ni %p rap %p\n", + __func__, error, ni, rap); + +net80211_only: + lhw->ic_ampdu_rx_stop(ni, rap); +} +#endif + +static void +lkpi_ic_getradiocaps_ht(struct ieee80211com *ic, struct ieee80211_hw *hw, + uint8_t *bands, int *chan_flags, enum nl80211_band band) +{ +#ifdef LKPI_80211_HT + struct ieee80211_sta_ht_cap *ht_cap; + + ht_cap = &hw->wiphy->bands[band]->ht_cap; + if (!ht_cap->ht_supported) + return; + + switch (band) { + case NL80211_BAND_2GHZ: + setbit(bands, IEEE80211_MODE_11NG); + break; + case NL80211_BAND_5GHZ: + setbit(bands, IEEE80211_MODE_11NA); + break; + default: + IMPROVE("Unsupported band %d", band); + return; + } + + ic->ic_htcaps = IEEE80211_HTC_HT; /* HT operation */ + + /* + * Rather than manually checking each flag and + * translating IEEE80211_HT_CAP_ to IEEE80211_HTCAP_, + * simply copy the 16bits. + */ + ic->ic_htcaps |= ht_cap->cap; + + /* Then deal with the other flags. */ + if (ieee80211_hw_check(hw, AMPDU_AGGREGATION)) + ic->ic_htcaps |= IEEE80211_HTC_AMPDU; +#ifdef __notyet__ + if (ieee80211_hw_check(hw, TX_AMSDU)) + ic->ic_htcaps |= IEEE80211_HTC_AMSDU; + if (ieee80211_hw_check(hw, SUPPORTS_AMSDU_IN_AMPDU)) + ic->ic_htcaps |= (IEEE80211_HTC_RX_AMSDU_AMPDU | + IEEE80211_HTC_TX_AMSDU_AMPDU); +#endif + + IMPROVE("PS, ampdu_*, ht_cap.mcs.tx_params, ..."); + ic->ic_htcaps |= IEEE80211_HTCAP_SMPS_OFF; + + /* Only add HT40 channels if supported. */ + if ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) != 0 && + chan_flags != NULL) + *chan_flags |= NET80211_CBW_FLAG_HT40; +#endif +} + static void lkpi_ic_getradiocaps(struct ieee80211com *ic, int maxchan, int *n, struct ieee80211_channel *c) @@ -3491,13 +3922,12 @@ lkpi_ic_getradiocaps(struct ieee80211com *ic, int maxchan, chan_flags = 0; setbit(bands, IEEE80211_MODE_11B); /* XXX-BZ unclear how to check for 11g. */ + + IMPROVE("the bitrates may have flags?"); setbit(bands, IEEE80211_MODE_11G); -#ifdef __notyet__ - if (hw->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.ht_supported) { - setbit(bands, IEEE80211_MODE_11NG); - chan_flags |= NET80211_CBW_FLAG_HT40; - } -#endif + + lkpi_ic_getradiocaps_ht(ic, hw, bands, &chan_flags, + NL80211_BAND_2GHZ); channels = hw->wiphy->bands[NL80211_BAND_2GHZ]->channels; for (i = 0; i < nchans && *n < maxchan; i++) { @@ -3547,11 +3977,11 @@ lkpi_ic_getradiocaps(struct ieee80211com *ic, int maxchan, memset(bands, 0, sizeof(bands)); chan_flags = 0; setbit(bands, IEEE80211_MODE_11A); -#ifdef __not_yet__ - if (hw->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.ht_supported) { - setbit(bands, IEEE80211_MODE_11NA); - chan_flags |= NET80211_CBW_FLAG_HT40; - } + + lkpi_ic_getradiocaps_ht(ic, hw, bands, &chan_flags, + NL80211_BAND_5GHZ); + +#ifdef LKPI_80211_VHT if (hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.vht_supported){ ic->ic_flags_ext |= IEEE80211_FEXT_VHT; @@ -3792,18 +4222,6 @@ linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw) lhw->scan_flags |= LKPI_LHW_SCAN_HW; } -#ifdef __notyet__ - ic->ic_htcaps = IEEE80211_HTC_HT /* HT operation */ - | IEEE80211_HTC_AMPDU /* A-MPDU tx/rx */ - | IEEE80211_HTC_AMSDU /* A-MSDU tx/rx */ - | IEEE80211_HTCAP_MAXAMSDU_3839 - /* max A-MSDU length */ - | IEEE80211_HTCAP_SMPS_OFF; /* SM power save off */ - ic->ic_htcaps |= IEEE80211_HTCAP_SHORTGI20; - ic->ic_htcaps |= IEEE80211_HTCAP_CHWIDTH40 | IEEE80211_HTCAP_SHORTGI40; - ic->ic_htcaps |= IEEE80211_HTCAP_TXSTBC; -#endif - /* * The wiphy variables report bitmasks of avail antennas. * (*get_antenna) get the current bitmask sets which can be @@ -3862,6 +4280,33 @@ linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw) lhw->ic_node_free = ic->ic_node_free; ic->ic_node_free = lkpi_ic_node_free; +#ifdef LKPI_80211_HT + lhw->ic_recv_action = ic->ic_recv_action; + ic->ic_recv_action = lkpi_ic_recv_action; + lhw->ic_send_action = ic->ic_send_action; + ic->ic_send_action = lkpi_ic_send_action; + + lhw->ic_ampdu_enable = ic->ic_ampdu_enable; + ic->ic_ampdu_enable = lkpi_ic_ampdu_enable; + + lhw->ic_addba_request = ic->ic_addba_request; + ic->ic_addba_request = lkpi_ic_addba_request; + lhw->ic_addba_response = ic->ic_addba_response; + ic->ic_addba_response = lkpi_ic_addba_response; + lhw->ic_addba_stop = ic->ic_addba_stop; + ic->ic_addba_stop = lkpi_ic_addba_stop; + lhw->ic_addba_response_timeout = ic->ic_addba_response_timeout; + ic->ic_addba_response_timeout = lkpi_ic_addba_response_timeout; + + lhw->ic_bar_response = ic->ic_bar_response; + ic->ic_bar_response = lkpi_ic_bar_response; + + lhw->ic_ampdu_rx_start = ic->ic_ampdu_rx_start; + ic->ic_ampdu_rx_start = lkpi_ic_ampdu_rx_start; + lhw->ic_ampdu_rx_stop = ic->ic_ampdu_rx_stop; + ic->ic_ampdu_rx_stop = lkpi_ic_ampdu_rx_stop; +#endif + lkpi_radiotap_attach(lhw); /* @@ -3893,6 +4338,9 @@ linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw) continue; cfg80211_chandef_create(&hw->conf.chandef, &channels[i], +#ifdef LKPI_80211_HT + (ic->ic_htcaps & IEEE80211_HTC_HT) ? 0 : +#endif NL80211_CHAN_NO_HT); break; } @@ -3910,7 +4358,6 @@ linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw) /* * The maximum supported bitrates on any band + size for * DSSS Parameter Set give our per-band IE size. - * XXX-BZ FIXME add HT VHT ... later * SSID is the responsibility of the driver and goes on the side. * The user specified bits coming from the vap go into the * "common ies" fields. @@ -3928,6 +4375,15 @@ linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw) lhw->scan_ie_len += 2 + 1; } +#if defined(LKPI_80211_HT) + if ((ic->ic_htcaps & IEEE80211_HTC_HT) != 0) + lhw->scan_ie_len += sizeof(struct ieee80211_ie_htcap); +#endif +#if defined(LKPI_80211_VHT) + if ((ic->ic_flags_ext & IEEE80211_FEXT_VHT) != 0) + lhw->scan_ie_len += 2 + sizeof(struct ieee80211_vht_cap); +#endif + /* Reduce the max_scan_ie_len "left" by the amount we consume already. */ if (hw->wiphy->max_scan_ie_len > 0) { if (lhw->scan_ie_len > hw->wiphy->max_scan_ie_len) @@ -4326,8 +4782,9 @@ no_trace_beacons: * net80211 should take care of the other information (sync_tsf, * sync_dtim_count) as otherwise we need to parse the beacon. */ - } skip_device_ts: + ; + } if (vap != NULL && vap->iv_state > IEEE80211_S_INIT && ieee80211_radiotap_active_vap(vap)) { diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h index 74dc3c9f9dee..ef1f841e4f22 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.h +++ b/sys/compat/linuxkpi/common/src/linux_80211.h @@ -62,11 +62,20 @@ #define D80211_TRACEX_DUMP (D80211_TRACE_TX_DUMP|D80211_TRACE_RX_DUMP) #define D80211_TRACE_STA 0x00010000 #define D80211_TRACE_MO 0x00100000 +#define D80211_TRACE_MODE 0x0f000000 +#define D80211_TRACE_MODE_HT 0x01000000 +#define D80211_TRACE_MODE_VHT 0x02000000 +#define D80211_TRACE_MODE_HE 0x04000000 +#define D80211_TRACE_MODE_EHT 0x08000000 #define IMPROVE_TXQ(...) \ if (linuxkpi_debug_80211 & D80211_IMPROVE_TXQ) \ printf("%s:%d: XXX LKPI80211 IMPROVE_TXQ\n", __func__, __LINE__) +#define IMPROVE_HT(...) \ + if (linuxkpi_debug_80211 & D80211_TRACE_MODE_HT) \ + printf("%s:%d: XXX LKPI80211 IMPROVE_HT\n", __func__, __LINE__) + struct lkpi_radiotap_tx_hdr { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; @@ -190,6 +199,29 @@ struct lkpi_hw { /* name it mac80211_sc? */ void (*ic_node_cleanup)(struct ieee80211_node *); void (*ic_node_free)(struct ieee80211_node *); + /* HT and later functions. */ + int (*ic_recv_action)(struct ieee80211_node *, + const struct ieee80211_frame *, + const uint8_t *, const uint8_t *); + int (*ic_send_action)(struct ieee80211_node *, + int, int, void *); + int (*ic_ampdu_enable)(struct ieee80211_node *, + struct ieee80211_tx_ampdu *); + int (*ic_addba_request)(struct ieee80211_node *, + struct ieee80211_tx_ampdu *, int, int, int); + int (*ic_addba_response)(struct ieee80211_node *, + struct ieee80211_tx_ampdu *, int, int, int); + void (*ic_addba_stop)(struct ieee80211_node *, + struct ieee80211_tx_ampdu *); + void (*ic_addba_response_timeout)(struct ieee80211_node *, + struct ieee80211_tx_ampdu *); + void (*ic_bar_response)(struct ieee80211_node *, + struct ieee80211_tx_ampdu *, int); + int (*ic_ampdu_rx_start)(struct ieee80211_node *, + struct ieee80211_rx_ampdu *, int, int, int); + void (*ic_ampdu_rx_stop)(struct ieee80211_node *, + struct ieee80211_rx_ampdu *); + #define LKPI_MAC80211_DRV_STARTED 0x00000001 uint32_t sc_flags; #define LKPI_LHW_SCAN_RUNNING 0x00000001 @@ -312,5 +344,8 @@ void lkpi_80211_mo_sta_pre_rcu_remove(struct ieee80211_hw *, int lkpi_80211_mo_set_key(struct ieee80211_hw *, enum set_key_cmd, struct ieee80211_vif *, struct ieee80211_sta *, struct ieee80211_key_conf *); +int lkpi_80211_mo_ampdu_action(struct ieee80211_hw *, struct ieee80211_vif *, + struct ieee80211_ampdu_params *); + #endif /* _LKPI_SRC_LINUX_80211_H */ diff --git a/sys/compat/linuxkpi/common/src/linux_80211_macops.c b/sys/compat/linuxkpi/common/src/linux_80211_macops.c index fab0d2ccb813..8cc885c037e3 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211_macops.c +++ b/sys/compat/linuxkpi/common/src/linux_80211_macops.c @@ -695,3 +695,25 @@ lkpi_80211_mo_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, out: return (error); } + +int +lkpi_80211_mo_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params) +{ + struct lkpi_hw *lhw; + int error; + + lhw = HW_TO_LHW(hw); + if (lhw->ops->ampdu_action == NULL) { + error = EOPNOTSUPP; + goto out; + } + + LKPI_80211_TRACE_MO("hw %p vif %p params %p { %p, %d, %u, %u, %u, %u, %d }", + hw, vif, params, params->sta, params->action, params->buf_size, + params->timeout, params->ssn, params->tid, params->amsdu); + error = lhw->ops->ampdu_action(hw, vif, params); + +out: + return (error); +}