Author: adrian
Date: Wed May 18 05:56:25 2016
New Revision: 300114
URL: https://svnweb.freebsd.org/changeset/base/300114

Log:
  [bwn] add initial 5xx firmware API support
  
  * Add the new TX/RX frame formats;
  * Use the right TX/RX format based on the frame info;
  * Disable the 5xx firmware check, since now it should
    somewhat work (but note, we don't yet use it unless
    you manually add ucode11/initvals11 from the 5.x driver
    to bwn-kmod-firmware;
  
  * Misc: update some comments/debugging now I know what's
    actually going on.
  
  Tested:
  
  * BCM4321MC, STA mode, both 4xx and 666 firmware, DMA mode
  
  TODO:
  
  * The newer firmware ends up logging "warn: firmware state (0)";
    not sure yet what's going on there.  But, yes, it still works.
    I'm committing this via a BCM4321MC, 11a station, firmware
    rev 666.
  
  Obtained from:        Linux b43 (TX/RX descriptor format for 5xx)

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   Wed May 18 04:35:58 2016        (r300113)
+++ head/sys/dev/bwn/if_bwn.c   Wed May 18 05:56:25 2016        (r300114)
@@ -1216,14 +1216,12 @@ bwn_attach_core(struct bwn_mac *mac)
        }
 
        /*
-        * XXX turns off PHY A because it's not supported.
-        * Implement PHY-A support so we can use it for PHY-G
-        * dual-band support.
+        * XXX The PHY-G support doesn't do 5GHz operation.
         */
        if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
            mac->mac_phy.type != BWN_PHYTYPE_N) {
                device_printf(sc->sc_dev,
-                   "%s: forcing 2GHz only; missing PHY-A support\n",
+                   "%s: forcing 2GHz only; no dual-band support for PHY\n",
                    __func__);
                have_a = 0;
                have_bg = 1;
@@ -3791,6 +3789,8 @@ bwn_psctl(struct bwn_mac *mac, uint32_t 
                        DELAY(10);
                }
        }
+       DPRINTF(mac->mac_sc, BWN_DEBUG_RESET, "%s: ucstat=%d\n", __func__,
+           ucstat);
 }
 
 static int
@@ -4186,12 +4186,14 @@ bwn_fw_loaducode(struct bwn_mac *mac)
         * So, complain this is the case and exit out, rather
         * than attaching and then failing.
         */
+#if 0
        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;
        }
+#endif
 
        mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
            BWN_SHARED_UCODE_PATCH);
@@ -5351,7 +5353,17 @@ bwn_dma_rxeof(struct bwn_dma_ring *dr, i
                       len, dr->dr_rx_bufsize, cnt);
                return;
        }
-       macstat = le32toh(rxhdr->mac_status);
+
+       switch (mac->mac_fw.fw_hdr_format) {
+       case BWN_FW_HDR_351:
+       case BWN_FW_HDR_410:
+               macstat = le32toh(rxhdr->ps4.r351.mac_status);
+               break;
+       case BWN_FW_HDR_598:
+               macstat = le32toh(rxhdr->ps4.r598.mac_status);
+               break;
+       }
+
        if (macstat & BWN_RX_MAC_FCSERR) {
                if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
                        device_printf(sc->sc_dev, "RX drop\n");
@@ -5452,7 +5464,16 @@ ready:
                goto error;
        }
 
-       macstat = le32toh(rxhdr.mac_status);
+       switch (mac->mac_fw.fw_hdr_format) {
+       case BWN_FW_HDR_351:
+       case BWN_FW_HDR_410:
+               macstat = le32toh(rxhdr.ps4.r351.mac_status);
+               break;
+       case BWN_FW_HDR_598:
+               macstat = le32toh(rxhdr.ps4.r598.mac_status);
+               break;
+       }
+
        if (macstat & BWN_RX_MAC_FCSERR) {
                if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
                        device_printf(sc->sc_dev, "%s: FCS error", __func__);
@@ -5706,11 +5727,25 @@ bwn_rxeof(struct bwn_mac *mac, struct mb
        BWN_ASSERT_LOCKED(sc);
 
        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);
+       /*
+        * XXX Note: phy_status3 doesn't exist for HT-PHY; it's only
+        * used for LP-PHY.
+        */
+       phystat3 = le16toh(rxhdr->ps3.lp.phy_status3);
+
+       switch (mac->mac_fw.fw_hdr_format) {
+       case BWN_FW_HDR_351:
+       case BWN_FW_HDR_410:
+               macstat = le32toh(rxhdr->ps4.r351.mac_status);
+               chanstat = le16toh(rxhdr->ps4.r351.channel);
+               break;
+       case BWN_FW_HDR_598:
+               macstat = le32toh(rxhdr->ps4.r598.mac_status);
+               chanstat = le16toh(rxhdr->ps4.r598.channel);
+               break;
+       }
+
 
        phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
 
@@ -6181,10 +6216,22 @@ bwn_set_txhdr(struct bwn_mac *mac, struc
                    m->m_pkthdr.len, rate, isshort);
 
        /* XXX TX encryption */
-       bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
-           (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
-           (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
-           m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
+
+       switch (mac->mac_fw.fw_hdr_format) {
+       case BWN_FW_HDR_351:
+               bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->body.r351.plcp),
+                   m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
+               break;
+       case BWN_FW_HDR_410:
+               bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->body.r410.plcp),
+                   m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
+               break;
+       case BWN_FW_HDR_598:
+               bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->body.r598.plcp),
+                   m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
+               break;
+       }
+
        bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
            m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
 
@@ -6243,9 +6290,22 @@ bwn_set_txhdr(struct bwn_mac *mac, struc
                    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
 
                if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
-                       cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
-                           (txhdr->body.old.rts_frame) :
-                           (txhdr->body.new.rts_frame));
+
+                       switch (mac->mac_fw.fw_hdr_format) {
+                       case BWN_FW_HDR_351:
+                               cts = (struct ieee80211_frame_cts *)
+                                   txhdr->body.r351.rts_frame;
+                               break;
+                       case BWN_FW_HDR_410:
+                               cts = (struct ieee80211_frame_cts *)
+                                   txhdr->body.r410.rts_frame;
+                               break;
+                       case BWN_FW_HDR_598:
+                               cts = (struct ieee80211_frame_cts *)
+                                   txhdr->body.r598.rts_frame;
+                               break;
+                       }
+
                        mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
                            protdur);
                        KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
@@ -6255,9 +6315,21 @@ bwn_set_txhdr(struct bwn_mac *mac, struc
                        macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
                        len = sizeof(struct ieee80211_frame_cts);
                } else {
-                       rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
-                           (txhdr->body.old.rts_frame) :
-                           (txhdr->body.new.rts_frame));
+                       switch (mac->mac_fw.fw_hdr_format) {
+                       case BWN_FW_HDR_351:
+                               rts = (struct ieee80211_frame_rts *)
+                                   txhdr->body.r351.rts_frame;
+                               break;
+                       case BWN_FW_HDR_410:
+                               rts = (struct ieee80211_frame_rts *)
+                                   txhdr->body.r410.rts_frame;
+                               break;
+                       case BWN_FW_HDR_598:
+                               rts = (struct ieee80211_frame_rts *)
+                                   txhdr->body.r598.rts_frame;
+                               break;
+                       }
+
                        /* XXX rate/rate_fb is the hardware rate */
                        protdur += ieee80211_ack_duration(ic->ic_rt, rate,
                            isshort);
@@ -6271,15 +6343,40 @@ bwn_set_txhdr(struct bwn_mac *mac, struc
                        len = sizeof(struct ieee80211_frame_rts);
                }
                len += IEEE80211_CRC_LEN;
-               bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
-                   &txhdr->body.old.rts_plcp :
-                   &txhdr->body.new.rts_plcp), len, rts_rate);
+
+               switch (mac->mac_fw.fw_hdr_format) {
+               case BWN_FW_HDR_351:
+                       bwn_plcp_genhdr((struct bwn_plcp4 *)
+                           &txhdr->body.r351.rts_plcp, len, rts_rate);
+                       break;
+               case BWN_FW_HDR_410:
+                       bwn_plcp_genhdr((struct bwn_plcp4 *)
+                           &txhdr->body.r410.rts_plcp, len, rts_rate);
+                       break;
+               case BWN_FW_HDR_598:
+                       bwn_plcp_genhdr((struct bwn_plcp4 *)
+                           &txhdr->body.r598.rts_plcp, len, rts_rate);
+                       break;
+               }
+
                bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
                    rts_rate_fb);
 
-               protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
-                   (&txhdr->body.old.rts_frame) :
-                   (&txhdr->body.new.rts_frame));
+               switch (mac->mac_fw.fw_hdr_format) {
+               case BWN_FW_HDR_351:
+                       protwh = (struct ieee80211_frame *)
+                           &txhdr->body.r351.rts_frame;
+                       break;
+               case BWN_FW_HDR_410:
+                       protwh = (struct ieee80211_frame *)
+                           &txhdr->body.r410.rts_frame;
+                       break;
+               case BWN_FW_HDR_598:
+                       protwh = (struct ieee80211_frame *)
+                           &txhdr->body.r598.rts_frame;
+                       break;
+               }
+
                txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
 
                if (BWN_ISOFDMRATE(rts_rate)) {
@@ -6303,10 +6400,17 @@ bwn_set_txhdr(struct bwn_mac *mac, struc
                txhdr->phyctl_1fb = htole16(bwn_set_txhdr_phyctl1(mac, 
rate_fb));
        }
 
-       if (BWN_ISOLDFMT(mac))
-               txhdr->body.old.cookie = htole16(cookie);
-       else
-               txhdr->body.new.cookie = htole16(cookie);
+       switch (mac->mac_fw.fw_hdr_format) {
+       case BWN_FW_HDR_351:
+               txhdr->body.r351.cookie = htole16(cookie);
+               break;
+       case BWN_FW_HDR_410:
+               txhdr->body.r410.cookie = htole16(cookie);
+               break;
+       case BWN_FW_HDR_598:
+               txhdr->body.r598.cookie = htole16(cookie);
+               break;
+       }
 
        txhdr->macctl = htole32(macctl);
        txhdr->phyctl = htole16(phyctl);
@@ -6739,6 +6843,7 @@ bwn_rx_radiotap(struct bwn_mac *mac, str
        const struct ieee80211_frame_min *wh;
        uint64_t tsf;
        uint16_t low_mactime_now;
+       uint16_t mt;
 
        if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
                sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
@@ -6750,8 +6855,19 @@ bwn_rx_radiotap(struct bwn_mac *mac, str
        bwn_tsf_read(mac, &tsf);
        low_mactime_now = tsf;
        tsf = tsf & ~0xffffULL;
-       tsf += le16toh(rxhdr->mac_time);
-       if (low_mactime_now < le16toh(rxhdr->mac_time))
+
+       switch (mac->mac_fw.fw_hdr_format) {
+       case BWN_FW_HDR_351:
+       case BWN_FW_HDR_410:
+               mt = le16toh(rxhdr->ps4.r351.mac_time);
+               break;
+       case BWN_FW_HDR_598:
+               mt = le16toh(rxhdr->ps4.r598.mac_time);
+               break;
+       }
+
+       tsf += mt;
+       if (low_mactime_now < mt)
                tsf -= 0x10000;
 
        sc->sc_rx_th.wr_tsf = tsf;

Modified: head/sys/dev/bwn/if_bwnvar.h
==============================================================================
--- head/sys/dev/bwn/if_bwnvar.h        Wed May 18 04:35:58 2016        
(r300113)
+++ head/sys/dev/bwn/if_bwnvar.h        Wed May 18 05:56:25 2016        
(r300114)
@@ -271,10 +271,29 @@ struct bwn_rxhdr4 {
                } __packed ht;
                uint16_t                phy_status2;
        } __packed ps2;
-       uint16_t                        phy_status3;
-       uint32_t                        mac_status;
-       uint16_t                        mac_time;
-       uint16_t                        channel;
+       union {
+               struct {
+                       uint16_t        phy_status3;
+               } __packed lp;
+               struct {
+                       int8_t          phy_ht_power1;
+                       int8_t          phy_ht_power2;
+               } __packed ht;
+       } __packed ps3;
+       union {
+               struct {
+                       uint32_t        mac_status;
+                       uint16_t        mac_time;
+                       uint16_t        channel;
+               } __packed r351;
+               struct {
+                       uint16_t        phy_status4;
+                       uint16_t        phy_status5;
+                       uint32_t        mac_status;
+                       uint16_t        mac_time;
+                       uint16_t        channel;
+               } __packed r598;
+       } __packed ps4;
 } __packed;
 
 struct bwn_txstatus {
@@ -765,19 +784,34 @@ struct bwn_txhdr {
                        uint8_t         rts_frame[16];
                        uint8_t         pad1[2];
                        struct bwn_plcp6        plcp;
-               } __packed old;
-               /* format > r410 */
+               } __packed r351;
+               /* format > r410 < r598 */
+               struct {
+                       uint16_t        mimo_antenna;
+                       uint16_t        preload_size;
+                       uint8_t         pad0[2];
+                       uint16_t        cookie;
+                       uint16_t        tx_status;
+                       struct bwn_plcp6        rts_plcp;
+                       uint8_t         rts_frame[16];
+                       uint8_t         pad1[2];
+                       struct bwn_plcp6        plcp;
+               } __packed r410;
                struct {
                        uint16_t        mimo_antenna;
                        uint16_t        preload_size;
                        uint8_t         pad0[2];
                        uint16_t        cookie;
                        uint16_t        tx_status;
+                       uint16_t        max_n_mpdus;
+                       uint16_t        max_a_bytes_mrt;
+                       uint16_t        max_a_bytes_fbr;
+                       uint16_t        min_m_bytes;
                        struct bwn_plcp6        rts_plcp;
                        uint8_t         rts_frame[16];
                        uint8_t         pad1[2];
                        struct bwn_plcp6        plcp;
-               } __packed new;
+               } __packed r598;
        } __packed body;
 } __packed;
 
_______________________________________________
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