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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to