mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Andreas Wendleder <gonsolo@gmail.com>
To: linux-wireless@vger.kernel.org
Cc: Johannes Berg <johannes@sipsolutions.net>,
	b43-dev@lists.infradead.org, Michael Buesch <m@bues.ch>,
	Alessio Ferri <alessio.ferri@mythread.it>,
	kvalo@kernel.org, julian.calaby@gmail.com, jpeisach@ubuntu.com,
	rosenp@gmail.com, linux-kernel@vger.kernel.org
Subject: [PATCH RFC wireless-next 3/3] wifi: b43: address match table, templates and beacons for the AC microcode
Date: Thu, 12 Nov 2026 18:56:24 +0100	[thread overview]
Message-ID: <20261112175624.40547-4-gonsolo@gmail.com> (raw)
In-Reply-To: <20261112175624.40547-1-gonsolo@gmail.com>

The microcode of revisions 784 and above lays out several things
differently:

 - the address match table is in the RCMTA object memory, 8 bytes per
   entry (MAC[0..3], then MAC[4..5] and the attributes); the vendor driver
   uses entry 63 for its own address and 62 for the BSSID,
 - the templates in template RAM: 0x30 holds BSSID, MAC, BSSID, 0x48 the
   MAC, plus the default null frame at 0x2c and a header at 0,
 - the ACK/CTS PHY control word and the antenna selection use the AC
   PhyTxControlWord_0 format,
 - the two beacon template slots are at 0x200 and 0x480, and the beacon's
   PHY TX control words are at SHM 0xcc, 0xce and 0xd0 instead of the
   legacy BEACPHYCTL word.
Signed-off-by: Andreas Wendleder <gonsolo@gmail.com>
---
 drivers/net/wireless/broadcom/b43/main.c | 141 ++++++++++++++++++++---
 1 file changed, 126 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index 205d429..da7e420 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -662,6 +662,26 @@ void b43_macfilter_set(struct b43_wldev *dev, u16 offset, const u8 *mac)
 	if (!mac)
 		mac = zero_addr;
 
+	if (b43_ucode_is_ac(dev)) {
+		/*
+		 * rev 40+ ucode: address match table (AMT) in RCMTA object
+		 * memory, 8 bytes per entry: MAC[0..3], MAC[4..5] | attr << 16.
+		 * the vendor driver uses entry 63 for its own MAC and 62 for
+		 * the BSSID.
+		 */
+		bool self = offset == B43_MACFILTER_SELF;
+		u16 idx = self ? 0x3f : 0x3e;
+		u16 attr = is_zero_ether_addr(mac) ? 0 :
+						     (self ? 0x8008 : 0x8006);
+
+		b43_shm_write32(dev, B43_SHM_RCMTA, idx * 2,
+				mac[0] | (mac[1] << 8) | (mac[2] << 16) |
+				((u32)mac[3] << 24));
+		b43_shm_write32(dev, B43_SHM_RCMTA, idx * 2 + 1,
+				mac[4] | (mac[5] << 8) | ((u32)attr << 16));
+		return;
+	}
+
 	offset |= 0x0020;
 	b43_write16(dev, B43_MMIO_MACFILTER_CONTROL, offset);
 
@@ -689,6 +709,39 @@ static void b43_write_mac_bssid_templates(struct b43_wldev *dev)
 
 	b43_macfilter_set(dev, B43_MACFILTER_BSSID, bssid);
 
+	if (b43_ucode_is_ac(dev)) {
+		/*
+		 * rev 40+ ucode (as wl): template RAM 0x30 = BSSID, MAC, BSSID;
+		 * 0x48 = MAC. Also the vendor driver's default null-frame
+		 * template at 0x2c and the header at 0x0.
+		 */
+		static const u32 hdr0[] = {
+			0x00000094, 0x75749000, 0x00007776,
+			0x00000000, 0xffff0005, 0x0000ffff
+		};
+		static const u32 null2c[] = {
+			0x00e0040a, 0x0048beef, 0xff000005, 0xff02ff01,
+			0x01181000, 0x10000302, 0xf3f2f118, 0x0000ccbb
+		};
+		u8 blk[20] = { 0 };
+		u8 m[8] = { 0 };
+
+		for (i = 0; i < ARRAY_SIZE(hdr0); i++)
+			b43_ram_write(dev, 0x00 + i * 4, hdr0[i]);
+		for (i = 0; i < ARRAY_SIZE(null2c); i++)
+			b43_ram_write(dev, 0x2c + i * 4, null2c[i]);
+		memcpy(blk, bssid, ETH_ALEN);
+		memcpy(blk + 6, mac, ETH_ALEN);
+		memcpy(blk + 12, bssid, ETH_ALEN);
+		for (i = 0; i < sizeof(blk); i += 4)
+			b43_ram_write(dev, 0x30 + i,
+				      get_unaligned_le32(blk + i));
+		memcpy(m, mac, ETH_ALEN);
+		b43_ram_write(dev, 0x48, get_unaligned_le32(m));
+		b43_ram_write(dev, 0x4c, get_unaligned_le32(m + 4));
+		return;
+	}
+
 	memcpy(mac_bssid, mac, ETH_ALEN);
 	memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
 
@@ -1657,19 +1710,56 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
 				  len, ram_offset, shm_size_offset, rate);
 
 	/* Write the PHY TX control parameters. */
-	antenna = B43_ANTENNA_DEFAULT;
-	antenna = b43_antenna_to_phyctl(antenna);
-	ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
-	/* We can't send beacons with short preamble. Would get PHY errors. */
-	ctl &= ~B43_TXH_PHY_SHORTPRMBL;
-	ctl &= ~B43_TXH_PHY_ANT;
-	ctl &= ~B43_TXH_PHY_ENC;
-	ctl |= antenna;
-	if (b43_is_cck_rate(rate))
-		ctl |= B43_TXH_PHY_ENC_CCK;
-	else
-		ctl |= B43_TXH_PHY_ENC_OFDM;
-	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
+	if (b43_ucode_is_ac(dev)) {
+		/*
+		 * rev 40+ ucode (wlc_beacon_phytxctl, core_rev > 0x27): the
+		 * beacon slot's PhyTxControlWord_0/1/2 live at SHM 0xcc/ce/d0,
+		 * not the legacy BEACPHYCTL word (0x54, unused here). Compute
+		 * them the same way as a normal AC TX descriptor rate entry
+		 * (b43_generate_txhdr_ac): CCK/OFDM bit, core mask, PLCP rate
+		 * index; no sub-band (this is 20 MHz single-channel only).
+		 */
+		static const u8 cck[] = { B43_CCK_RATE_1MB, B43_CCK_RATE_2MB,
+					  B43_CCK_RATE_5MB, B43_CCK_RATE_11MB };
+		static const u8 ofdm[] = {
+			B43_OFDM_RATE_6MB,  B43_OFDM_RATE_9MB,
+			B43_OFDM_RATE_12MB, B43_OFDM_RATE_18MB,
+			B43_OFDM_RATE_24MB, B43_OFDM_RATE_36MB,
+			B43_OFDM_RATE_48MB, B43_OFDM_RATE_54MB
+		};
+		bool is_ofdm = b43_is_ofdm_rate(rate);
+		const u8 *tbl = is_ofdm ? ofdm : cck;
+		unsigned int n = is_ofdm ? ARRAY_SIZE(ofdm) : ARRAY_SIZE(cck);
+		unsigned int idx = 0;
+		u16 phy0 = (is_ofdm ? 1 : 0) | 0x0004 | (1 << 6);
+
+		while (idx < n && tbl[idx] != rate)
+			idx++;
+		if (idx == n)
+			idx = 0;
+		b43_shm_write16(dev, B43_SHM_SHARED, 0xcc, phy0);
+		b43_shm_write16(dev, B43_SHM_SHARED, 0xce, 0);
+		b43_shm_write16(dev, B43_SHM_SHARED, 0xd0, idx);
+	} else {
+		antenna = B43_ANTENNA_DEFAULT;
+		antenna = b43_antenna_to_phyctl(antenna);
+		ctl = b43_shm_read16(dev, B43_SHM_SHARED,
+				     B43_SHM_SH_BEACPHYCTL);
+		/*
+		 * We can't send beacons with short preamble. Would get PHY
+		 * errors.
+		 */
+		ctl &= ~B43_TXH_PHY_SHORTPRMBL;
+		ctl &= ~B43_TXH_PHY_ANT;
+		ctl &= ~B43_TXH_PHY_ENC;
+		ctl |= antenna;
+		if (b43_is_cck_rate(rate))
+			ctl |= B43_TXH_PHY_ENC_CCK;
+		else
+			ctl |= B43_TXH_PHY_ENC_OFDM;
+		b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL,
+				ctl);
+	}
 
 	/* Find the position of the TIM and the DTIM_period value
 	 * and write them to SHM. */
@@ -1726,20 +1816,28 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
 static void b43_upload_beacon0(struct b43_wldev *dev)
 {
 	struct b43_wl *wl = dev->wl;
+	/*
+	 * rev 40+ ucode keeps the two beacon template slots at RAM 0x200 and
+	 * 0x480 (wlc_bmac_write_hw_bcntemplates, core_rev > 0x27), not the
+	 * legacy 0x68/0x468. Length (SHM 0x18/0x1a) and the valid bits (MMIO
+	 * MACCMD, unchanged) are the same on both.
+	 */
+	u16 base = b43_ucode_is_ac(dev) ? 0x200 : B43_SHM_SH_BT_BASE0;
 
 	if (wl->beacon0_uploaded)
 		return;
-	b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE0, B43_SHM_SH_BTL0);
+	b43_write_beacon_template(dev, base, B43_SHM_SH_BTL0);
 	wl->beacon0_uploaded = true;
 }
 
 static void b43_upload_beacon1(struct b43_wldev *dev)
 {
 	struct b43_wl *wl = dev->wl;
+	u16 base = b43_ucode_is_ac(dev) ? 0x480 : B43_SHM_SH_BT_BASE1;
 
 	if (wl->beacon1_uploaded)
 		return;
-	b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE1, B43_SHM_SH_BTL1);
+	b43_write_beacon_template(dev, base, B43_SHM_SH_BTL1);
 	wl->beacon1_uploaded = true;
 }
 
@@ -3237,6 +3335,17 @@ static void b43_set_phytxctl_defaults(struct b43_wldev *dev)
 {
 	u16 ctl = 0;
 
+	if (b43_ucode_is_ac(dev)) {
+		/*
+		 * rev 40+ ucode: AC PhyTxControlWord_0 format (CCK, core 0), as
+		 * the vendor driver sets it. 0x54/0x188 mean something else
+		 * here.
+		 */
+		b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL,
+				0x0040);
+		return;
+	}
+
 	ctl |= B43_TXH_PHY_ENC_CCK;
 	ctl |= B43_TXH_PHY_ANT01AUTO;
 	ctl |= B43_TXH_PHY_TXPWR;
@@ -3252,6 +3361,8 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
 	u16 ant;
 	u16 tmp;
 
+	if (b43_ucode_is_ac(dev))
+		return;
 	ant = b43_antenna_to_phyctl(antenna);
 
 	/* For ACK/CTS */

      parent reply	other threads:[~2026-11-12 17:56 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12 17:56 [PATCH RFC wireless-next 0/3] wifi: b43: core revision 40 and 42 MAC setup (series 2/4) Andreas Wendleder
2026-11-12 17:56 ` [PATCH RFC wireless-next 1/3] wifi: b43: set the DMA burst and prefetch bits of core revisions 40 and 42 Andreas Wendleder
2026-11-12 17:56 ` [PATCH RFC wireless-next 2/3] wifi: b43: MAC core setup for " Andreas Wendleder
2026-11-12 17:56 ` Andreas Wendleder [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261112175624.40547-4-gonsolo@gmail.com \
    --to=gonsolo@gmail.com \
    --cc=alessio.ferri@mythread.it \
    --cc=b43-dev@lists.infradead.org \
    --cc=johannes@sipsolutions.net \
    --cc=jpeisach@ubuntu.com \
    --cc=julian.calaby@gmail.com \
    --cc=kvalo@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=m@bues.ch \
    --cc=rosenp@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®