Index | Thread | Search

From:
Benjamin Lee McQueen <mcq@disroot.org>
Subject:
Re: mwx: implement RSSI
To:
Claudio <claudio@openbsd.org>
Cc:
Tech <tech@openbsd.org>
Date:
Wed, 06 May 2026 21:57:36 -0500

Download raw body.

Thread
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)