Index: sbin/ifconfig/ifieee80211.c =================================================================== --- sbin/ifconfig/ifieee80211.c +++ sbin/ifconfig/ifieee80211.c @@ -1787,6 +1787,21 @@ set80211(s, IEEE80211_IOC_STBC, stbc, 0, NULL); } +static void +set80211ldpc(const char *val, int d, int s, const struct afswtch *rafp) +{ + int ldpc; + + if (get80211val(s, IEEE80211_IOC_LDPC, &ldpc) < 0) + errx(-1, "cannot set LDPC setting"); + if (d < 0) { + d = -d; + ldpc &= ~d; + } else + ldpc |= d; + set80211(s, IEEE80211_IOC_LDPC, ldpc, 0, NULL); +} + static DECL_CMD_FUNC(set80211ampdulimit, val, d) { @@ -5030,6 +5045,23 @@ break; } } + if (get80211val(s, IEEE80211_IOC_LDPC, &val) != -1) { + switch (val) { + case 0: + LINE_CHECK("-ldpc"); + break; + case 1: + LINE_CHECK("ldpctx -ldpcrx"); + break; + case 2: + LINE_CHECK("-ldpctx ldpcrx"); + break; + case 3: + if (verbose) + LINE_CHECK("ldpc"); + break; + } + } } if (IEEE80211_IS_CHAN_VHT(c) || verbose) { @@ -5603,6 +5635,12 @@ DEF_CMD("-stbctx", -1, set80211stbc), DEF_CMD("stbc", 3, set80211stbc), /* NB: tx+rx */ DEF_CMD("-stbc", -3, set80211stbc), + DEF_CMD("ldpcrx", 2, set80211ldpc), + DEF_CMD("-ldpcrx", -2, set80211ldpc), + DEF_CMD("ldpctx", 1, set80211ldpc), + DEF_CMD("-ldpctx", -1, set80211ldpc), + DEF_CMD("ldpc", 3, set80211ldpc), /* NB: tx+rx */ + DEF_CMD("-ldpc", -3, set80211ldpc), DEF_CMD("puren", 1, set80211puren), DEF_CMD("-puren", 0, set80211puren), DEF_CMD("doth", 1, set80211doth), Index: sys/net80211/_ieee80211.h =================================================================== --- sys/net80211/_ieee80211.h +++ sys/net80211/_ieee80211.h @@ -517,9 +517,10 @@ #define IEEE80211_HTC_RXMCS32 0x00400000 /* CAPABILITY: MCS32 support */ #define IEEE80211_HTC_TXUNEQUAL 0x00800000 /* CAPABILITY: TX unequal MCS */ #define IEEE80211_HTC_TXMCS32 0x01000000 /* CAPABILITY: MCS32 support */ +#define IEEE80211_HTC_TXLDPC 0x02000000 /* CAPABILITY: TX using LDPC */ #define IEEE80211_C_HTCAP_BITS \ "\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \ - "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS" + "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS\32TXLDPC" #endif /* _NET80211__IEEE80211_H_ */ Index: sys/net80211/ieee80211.h =================================================================== --- sys/net80211/ieee80211.h +++ sys/net80211/ieee80211.h @@ -617,7 +617,7 @@ } __packed; /* HT capability flags (ht_cap) */ -#define IEEE80211_HTCAP_LDPC 0x0001 /* LDPC supported */ +#define IEEE80211_HTCAP_LDPC 0x0001 /* LDPC rx supported */ #define IEEE80211_HTCAP_CHWIDTH40 0x0002 /* 20/40 supported */ #define IEEE80211_HTCAP_SMPS 0x000c /* SM Power Save mode */ #define IEEE80211_HTCAP_SMPS_OFF 0x000c /* disabled */ Index: sys/net80211/ieee80211_ht.c =================================================================== --- sys/net80211/ieee80211_ht.c +++ sys/net80211/ieee80211_ht.c @@ -298,6 +298,11 @@ vap->iv_flags_ht |= IEEE80211_FHT_STBC_TX; if (vap->iv_htcaps & IEEE80211_HTCAP_RXSTBC) vap->iv_flags_ht |= IEEE80211_FHT_STBC_RX; + + if (vap->iv_htcaps & IEEE80211_HTCAP_LDPC) + vap->iv_flags_ht |= IEEE80211_FHT_LDPC_RX; + if (vap->iv_htcaps & IEEE80211_HTC_TXLDPC) + vap->iv_flags_ht |= IEEE80211_FHT_LDPC_TX; } /* NB: disable default legacy WDS, too many issues right now */ if (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY) @@ -1650,6 +1655,20 @@ } /* + * Update LDPC state according to received htcap + * and local settings. + */ +static __inline void +htcap_update_ldpc(struct ieee80211_node *ni) +{ + struct ieee80211vap *vap = ni->ni_vap; + + if ((ni->ni_htcap & IEEE80211_HTCAP_LDPC) && + (vap->iv_flags_ht & IEEE80211_FHT_LDPC_TX)) + ni->ni_flags |= IEEE80211_NODE_LDPC; +} + +/* * Parse and update HT-related state extracted from * the HT cap and info ie's. * @@ -1669,6 +1688,7 @@ if (vap->iv_htcaps & IEEE80211_HTCAP_SMPS) htcap_update_mimo_ps(ni); htcap_update_shortgi(ni); + htcap_update_ldpc(ni); if (htinfoie[0] == IEEE80211_ELEMID_VENDOR) htinfoie += 4; @@ -1821,6 +1841,7 @@ if (vap->iv_htcaps & IEEE80211_HTCAP_SMPS) htcap_update_mimo_ps(ni); htcap_update_shortgi(ni); + htcap_update_ldpc(ni); } /* @@ -3027,7 +3048,9 @@ if ((vap->iv_flags_ht & IEEE80211_FHT_STBC_RX) == 0) caps &= ~IEEE80211_HTCAP_RXSTBC; - /* XXX TODO: adjust LDPC based on receive capabilities */ + /* adjust LDPC based on receive capabilites */ + if ((vap->iv_flags_ht & IEEE80211_FHT_LDPC_RX) == 0) + caps &= ~IEEE80211_HTCAP_LDPC; ADDSHORT(frm, caps); Index: sys/net80211/ieee80211_ioctl.c =================================================================== --- sys/net80211/ieee80211_ioctl.c +++ sys/net80211/ieee80211_ioctl.c @@ -1136,6 +1136,13 @@ if (vap->iv_flags_ht & IEEE80211_FHT_STBC_RX) ireq->i_val |= 2; break; + case IEEE80211_IOC_LDPC: + ireq->i_val = 0; + if (vap->iv_flags_ht & IEEE80211_FHT_LDPC_TX) + ireq->i_val |= 1; + if (vap->iv_flags_ht & IEEE80211_FHT_LDPC_RX) + ireq->i_val |= 2; + break; /* VHT */ case IEEE80211_IOC_VHTCONF: @@ -3372,6 +3379,31 @@ if (isvapht(vap)) error = ERESTART; break; + case IEEE80211_IOC_LDPC: + /* Check if we can do LDPC TX/RX before changing the setting */ + if ((ireq->i_val & 1) && + (vap->iv_htcaps & IEEE80211_HTCAP_LDPC) == 0) + return EOPNOTSUPP; + if ((ireq->i_val & 2) && + (vap->iv_htcaps & IEEE80211_HTC_TXLDPC) == 0) + return EOPNOTSUPP; + + /* TX */ + if (ireq->i_val & 1) + vap->iv_flags_ht |= IEEE80211_FHT_LDPC_TX; + else + vap->iv_flags_ht &= ~IEEE80211_FHT_LDPC_TX; + + /* RX */ + if (ireq->i_val & 2) + vap->iv_flags_ht |= IEEE80211_FHT_LDPC_RX; + else + vap->iv_flags_ht &= ~IEEE80211_FHT_LDPC_TX; + + /* NB: reset only if we're operating on an 11n channel */ + if (isvapht(vap)) + error = ERESTART; + break; /* VHT */ case IEEE80211_IOC_VHTCONF: Index: sys/net80211/ieee80211_node.h =================================================================== --- sys/net80211/ieee80211_node.h +++ sys/net80211/ieee80211_node.h @@ -143,6 +143,7 @@ #define IEEE80211_NODE_AMSDU_RX 0x040000 /* AMSDU rx enabled */ #define IEEE80211_NODE_AMSDU_TX 0x080000 /* AMSDU tx enabled */ #define IEEE80211_NODE_VHT 0x100000 /* VHT enabled */ +#define IEEE80211_NODE_LDPC 0x200000 /* LDPC enabled */ uint16_t ni_associd; /* association ID */ uint16_t ni_vlan; /* vlan tag */ uint16_t ni_txpower; /* current transmit power */ Index: sys/net80211/ieee80211_var.h =================================================================== --- sys/net80211/ieee80211_var.h +++ sys/net80211/ieee80211_var.h @@ -641,6 +641,8 @@ /* ic_flags_ht/iv_flags_ht */ #define IEEE80211_FHT_NONHT_PR 0x00000001 /* STATUS: non-HT sta present */ +#define IEEE80211_FHT_LDPC_TX 0x00010000 /* CONF: LDPC tx enabled */ +#define IEEE80211_FHT_LDPC_RX 0x00020000 /* CONF: LDPC rx enabled */ #define IEEE80211_FHT_GF 0x00040000 /* CONF: Greenfield enabled */ #define IEEE80211_FHT_HT 0x00080000 /* CONF: HT supported */ #define IEEE80211_FHT_AMPDU_TX 0x00100000 /* CONF: A-MPDU tx supported */