From: Claudio Jeker Subject: Re: mwx: implement RSSI To: Benjamin Lee McQueen Cc: Tech Date: Sat, 2 May 2026 13:31:47 +0200 On Fri, May 01, 2026 at 05:00:48PM -0500, Benjamin Lee McQueen wrote: > hi tech@, > > attached is a diff that implements RSSI for the MediaTek MT7921 network > card. > > tested on a MT7921. > > -ben > --- sys/dev/pci/if_mwx.c Fri Aug 1 08:37:06 2025 > +++ /usr/src/sys/dev/pci/if_mwx.c Mon Mar 9 18:45:35 2026 > @@ -1019,7 +1019,7 @@ > htole16(ic->ic_channels[rxi.rxi_chan].ic_freq); > tap->wr_chan_flags = > ic->ic_channels[rxi.rxi_chan].ic_flags; > - tap->wr_dbm_antsignal = 0; > + tap->wr_dbm_antsignal = rxi.rxi_rssi; > bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m, > BPF_DIRECTION_IN); > } > @@ -1029,7 +1029,6 @@ > ni = ieee80211_find_rxnode(ic, wh); > > /* send the frame to the 802.11 layer */ > - /* TODO MAYBE rxi.rxi_rssi = rssi; */ > ieee80211_inputm(ifp, m, ni, &rxi, ml); > > /* node is no longer needed */ > @@ -4225,11 +4224,13 @@ > struct ieee80211_rxinfo *rxi) > { > struct ieee80211com *ic = &sc->sc_ic; > - uint32_t *rxd, rxd0, rxd1, rxd2, rxd3, rxd4; > + uint32_t *rxd, *rxv = NULL; > + uint32_t rxd0, rxd1, rxd2, rxd3, rxd4; > // uint32_t mode = 0; > uint16_t hdr_gap /*, seq_ctrl = 0, fc = 0 */; > uint8_t chfnum, remove_pad /*, qos_ctl = 0, amsdu_info */; > int idx, unicast, num_rxd = 6; > + int i; > // bool insert_ccmp_hdr = false; > > if (m->m_len < num_rxd * sizeof(uint32_t)) > @@ -4308,16 +4309,53 @@ > > rxd += 6; > > - if (rxd1 & MT_RXD1_NORMAL_GROUP_4) > + if (rxd1 & MT_RXD1_NORMAL_GROUP_4) { > num_rxd += 4; > - if (rxd1 & MT_RXD1_NORMAL_GROUP_1) > + rxd += 4; > + } > + if (rxd1 & MT_RXD1_NORMAL_GROUP_1) { > num_rxd += 4; > - if (rxd1 & MT_RXD1_NORMAL_GROUP_2) > + rxd += 4; > + } > + if (rxd1 & MT_RXD1_NORMAL_GROUP_2) { > num_rxd += 2; > - if (rxd1 & MT_RXD1_NORMAL_GROUP_3) > + rxd += 2; > + } > + if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { > + uint32_t v0, v1; > + int8_t chain[4], signal; > + > + rxv = rxd; > num_rxd += 2; > - if (rxd1 & MT_RXD1_NORMAL_GROUP_5) > - num_rxd += 18; > + rxd += 2; > + > + v0 = le32toh(rxv[0]); /* XXX not implemented yet */ > + v1 = le32toh(rxv[1]); > + > + if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { > + num_rxd += 18; > + rxd += 6; > + rxv = rxd; > + v1 = le32toh(rxv[0]); > + rxd += 12; > + } > + > + > + chain[0] = rcpi_to_rssi(MT_PRXV_RCPI0, v1); > + chain[1] = rcpi_to_rssi(MT_PRXV_RCPI1, v1); > + chain[2] = rcpi_to_rssi(MT_PRXV_RCPI2, v1); > + chain[3] = rcpi_to_rssi(MT_PRXV_RCPI3, v1); > + > + signal = -128; > + for (i = 0; i < sc->sc_capa.num_streams; i++) { > + if (!(sc->sc_capa.antenna_mask & BIT(i))) > + continue; > + if (chain[i] >= 0) > + continue; > + signal = MAX(signal, chain[i]); > + } > + rxi->rxi_rssi = signal; > + } > > if (m->m_len < num_rxd * sizeof(uint32_t)) > return -1; > --- sys/dev/pci/if_mwxreg.h Wed May 22 02:38:57 2024 > +++ /usr/src/sys/dev/pci/if_mwxreg.h Mon Mar 9 18:40:42 2026 > @@ -16,6 +16,11 @@ > * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > */ > > +/* FROM LINUX */ > +#define BIT(x) (1 << (x)) > +#define FIELD_GET(mask, reg) (((reg) & (mask)) >> (__builtin_ctz(mask))) > +#define GENMASK(h, l) (((~0U) >> (31 - (h))) & (~0U << (l))) > + > /* MCU WFDMA1 */ > #define MT_MCU_WFDMA1_BASE 0x3000 > > @@ -1401,6 +1406,12 @@ > #define PHY_TYPE_BIT_HT (1U << 4) > #define PHY_TYPE_BIT_VHT (1U << 5) > #define PHY_TYPE_BIT_HE (1U << 6) > + > +/* P-RXV DW0 */ > +#define MT_PRXV_RCPI3 GENMASK(31, 24) > +#define MT_PRXV_RCPI2 GENMASK(23, 16) > +#define MT_PRXV_RCPI1 GENMASK(15, 8) > +#define MT_PRXV_RCPI0 GENMASK(7, 0) > > #define rssi_to_rcpi(rssi) (2 * (rssi) + 220) > #define rcpi_to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) Please do not introduce BIT, FIELD_GET and GENMASK and instead replace them similar to how it is done in other places. You normally want a XY_MASK and XY_SHIFT value. I know that I have not converted all values yet in the header but I really don't want those macros. -- :wq Claudio