Download raw body.
mwx: implement RSSI
On 2026-05-02 06:31, Claudio Jeker wrote:
> 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.
something like this?
Index: if_mwx.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_mwx.c,v
diff -u -r1.7 if_mwx.c
--- if_mwx.c 1 Aug 2025 14:37:06 -0000 1.7
+++ if_mwx.c 7 May 2026 02:51:52 -0000
@@ -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_MASK, MT_PRXV_RCPI0_SHIFT, v1);
+ chain[1] = rcpi_to_rssi(MT_PRXV_RCPI1_MASK, MT_PRXV_RCPI1_SHIFT, v1);
+ chain[2] = rcpi_to_rssi(MT_PRXV_RCPI2_MASK, MT_PRXV_RCPI2_SHIFT, v1);
+ chain[3] = rcpi_to_rssi(MT_PRXV_RCPI3_MASK, MT_PRXV_RCPI3_SHIFT, v1);
+
+ signal = -128;
+ for (i = 0; i < sc->sc_capa.num_streams; i++) {
+ if (!(sc->sc_capa.antenna_mask & (1U << 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;
Index: if_mwxreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_mwxreg.h,v
diff -u -r1.3 if_mwxreg.h
--- if_mwxreg.h 22 May 2024 08:38:57 -0000 1.3
+++ if_mwxreg.h 7 May 2026 02:51:53 -0000
@@ -1402,5 +1402,16 @@
#define PHY_TYPE_BIT_VHT (1U << 5)
#define PHY_TYPE_BIT_HE (1U << 6)
+/* P-RXV DW0 */
+#define MT_PRXV_RCPI0_MASK 0x000000ff
+#define MT_PRXV_RCPI0_SHIFT 0
+#define MT_PRXV_RCPI1_MASK 0x0000ff00
+#define MT_PRXV_RCPI1_SHIFT 8
+#define MT_PRXV_RCPI2_MASK 0x00ff0000
+#define MT_PRXV_RCPI2_SHIFT 16
+#define MT_PRXV_RCPI3_MASK 0xff000000
+#define MT_PRXV_RCPI3_SHIFT 24
+
#define rssi_to_rcpi(rssi) (2 * (rssi) + 220)
-#define rcpi_to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
+#define rcpi_to_rssi(mask, shift, rxv) \
+ (((int)(((rxv) & (mask)) >> (shift)) - 220) / 2)
mwx: implement RSSI