Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 May 2016 07:04:39 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r299110 - head/sys/dev/bwn
Message-ID:  <201605050704.u4574dRG010095@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Thu May  5 07:04:38 2016
New Revision: 299110
URL: https://svnweb.freebsd.org/changeset/base/299110

Log:
  [bwn] implement firmware tx/rx versioning and fix RSSI calculation.
  
  Different versions of firmware have different requirments for TX/RX
  packet layouts (and other things, of course.)  Currently the driver
  checks between 3xx and 4xx firmware by using the BWN_ISOLDFMT() macro,
  which doesn't take into account the 5xx firmware (which I think I need
  for the HT and N series PHY chips.  I'll know when I do the port.)
  BWN_HDRSIZE() also needs to learn about the 5xx series firmware
  as well.
  
  So:
  
  * add a firmware version enum
  * populate it based on the firmware version we read at load time
  * don't finish loading if the firmware is the 5xx firmware; any
    code using BWN_ISOLDFMT or BWN_HDRSIZE needs updating (most notably
    the TX and RX bits.)
  
  Then, for RX RSSI:
  
  * write down and reimplement the b43 rssi calculation method;
  * use it for the correct PHYs (which are all the ones we support);
  * do the RSSI calculation before radiotap, not after.
  
  Tested:
  
  * Broadcom BCM4312, STA mode
  
  Obtained from:	Linux b43 (careful writing and reimplementing; lots of integer math..)

Modified:
  head/sys/dev/bwn/if_bwn.c
  head/sys/dev/bwn/if_bwnvar.h

Modified: head/sys/dev/bwn/if_bwn.c
==============================================================================
--- head/sys/dev/bwn/if_bwn.c	Thu May  5 06:58:30 2016	(r299109)
+++ head/sys/dev/bwn/if_bwn.c	Thu May  5 07:04:38 2016	(r299110)
@@ -3987,6 +3987,33 @@ bwn_fw_loaducode(struct bwn_mac *mac)
 		error = EOPNOTSUPP;
 		goto error;
 	}
+
+	/*
+	 * Determine firmware header version; needed for TX/RX packet
+	 * handling.
+	 */
+	if (mac->mac_fw.rev >= 598)
+		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_598;
+	else if (mac->mac_fw.rev >= 410)
+		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_410;
+	else
+		mac->mac_fw.fw_hdr_format = BWN_FW_HDR_351;
+
+	/*
+	 * We don't support rev 598 or later; that requires
+	 * another round of changes to the TX/RX descriptor
+	 * and status layout.
+	 *
+	 * So, complain this is the case and exit out, rather
+	 * than attaching and then failing.
+	 */
+	if (mac->mac_fw.fw_hdr_format == BWN_FW_HDR_598) {
+		device_printf(sc->sc_dev,
+		    "firmware is too new (>=598); not supported\n");
+		error = EOPNOTSUPP;
+		goto error;
+	}
+
 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
 	    BWN_SHARED_UCODE_PATCH);
 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
@@ -5401,6 +5428,63 @@ bwn_hwrate2ieeerate(int rate)
 	}
 }
 
+/*
+ * Post process the RX provided RSSI.
+ *
+ * Valid for A, B, G, LP PHYs.
+ */
+static int8_t
+bwn_rx_rssi_calc(struct bwn_mac *mac, int8_t in_rssi,
+    int ofdm, int adjust_2053, int adjust_2050)
+{
+	struct bwn_phy *phy = &mac->mac_phy;
+	struct bwn_phy_g *gphy = &phy->phy_g;
+	int tmp;
+
+	switch (phy->rf_ver) {
+	case 0x2050:
+		if (ofdm) {
+			tmp = in_rssi;
+			if (tmp > 127)
+				tmp -= 256;
+			tmp = tmp * 73 / 64;
+			if (adjust_2050)
+				tmp += 25;
+			else
+				tmp -= 3;
+		} else {
+			if (siba_sprom_get_bf_lo(mac->mac_sc->sc_dev)
+			    & BWN_BFL_RSSI) {
+				if (in_rssi > 63)
+					in_rssi = 63;
+				tmp = gphy->pg_nrssi_lt[in_rssi];
+				tmp = (31 - tmp) * -131 / 128 - 57;
+			} else {
+				tmp = in_rssi;
+				tmp = (31 - tmp) * -149 / 128 - 68;
+			}
+			if (phy->type == BWN_PHYTYPE_G && adjust_2050)
+				tmp += 25;
+		}
+		break;
+	case 0x2060:
+		if (in_rssi > 127)
+			tmp = in_rssi - 256;
+		else
+			tmp = in_rssi;
+		break;
+	default:
+		tmp = in_rssi;
+		tmp = (tmp - 11) * 103 / 64;
+		if (adjust_2053)
+			tmp -= 109;
+		else
+			tmp -= 83;
+	}
+
+	return (tmp);
+}
+
 static void
 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
 {
@@ -5420,8 +5504,11 @@ bwn_rxeof(struct bwn_mac *mac, struct mb
 
 	phystat0 = le16toh(rxhdr->phy_status0);
 	phystat3 = le16toh(rxhdr->phy_status3);
+
+	/* XXX Note: mactime, macstat, chanstat need fixing for fw 598 */
 	macstat = le32toh(rxhdr->mac_status);
 	chanstat = le16toh(rxhdr->channel);
+
 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
 
 	if (macstat & BWN_RX_MAC_FCSERR)
@@ -5452,8 +5539,6 @@ bwn_rxeof(struct bwn_mac *mac, struct mb
 		    BWN_ISOLDFMT(mac),
 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
 
-	/* XXX calculating RSSI & noise & antenna */
-
 	if (phystat0 & BWN_RX_PHYST0_OFDM)
 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
 		    phytype == BWN_PHYTYPE_A);
@@ -5465,14 +5550,29 @@ bwn_rxeof(struct bwn_mac *mac, struct mb
 	}
 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
 
+	/* rssi/noise */
+	switch (phytype) {
+	case BWN_PHYTYPE_A:
+	case BWN_PHYTYPE_B:
+	case BWN_PHYTYPE_G:
+	case BWN_PHYTYPE_LP:
+		rssi = bwn_rx_rssi_calc(mac, rxhdr->phy.abg.rssi,
+		    !! (phystat0 & BWN_RX_PHYST0_OFDM),
+		    !! (phystat0 & BWN_RX_PHYST0_GAINCTL),
+		    !! (phystat3 & BWN_RX_PHYST3_TRSTATE));
+		break;
+	default:
+		/* XXX TODO: implement rssi for other PHYs */
+		break;
+	}
+
+	noise = mac->mac_stats.link_noise;
+
 	/* RX radio tap */
 	if (ieee80211_radiotap_active(ic))
 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
 	m_adj(m, -IEEE80211_CRC_LEN);
 
-	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
-	noise = mac->mac_stats.link_noise;
-
 	BWN_UNLOCK(sc);
 
 	ni = ieee80211_find_rxnode(ic, wh);

Modified: head/sys/dev/bwn/if_bwnvar.h
==============================================================================
--- head/sys/dev/bwn/if_bwnvar.h	Thu May  5 06:58:30 2016	(r299109)
+++ head/sys/dev/bwn/if_bwnvar.h	Thu May  5 07:04:38 2016	(r299110)
@@ -751,6 +751,12 @@ struct bwn_fwinitvals {
 	} __packed data;
 } __packed;
 
+enum bwn_fw_hdr_format {
+	BWN_FW_HDR_598,
+	BWN_FW_HDR_410,
+	BWN_FW_HDR_351,
+};
+
 enum bwn_fwtype {
 	BWN_FWTYPE_DEFAULT,
 	BWN_FWTYPE_OPENSOURCE,
@@ -773,6 +779,7 @@ struct bwn_fw {
 	struct bwn_fwfile		pcm;
 	struct bwn_fwfile		initvals;
 	struct bwn_fwfile		initvals_band;
+	enum bwn_fw_hdr_format		fw_hdr_format;
 
 	uint16_t			rev;
 	uint16_t			patch;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605050704.u4574dRG010095>