[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)
This commit is contained in:
parent
596f2a146d
commit
4b1c046953
@ -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 flags)
|
||||
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, int *slot)
|
||||
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 @@ bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
|
||||
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 mbuf *m, const void *_rxhdr)
|
||||
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, struct ieee80211_node *ni,
|
||||
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, struct ieee80211_node *ni,
|
||||
+ 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, struct ieee80211_node *ni,
|
||||
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, struct ieee80211_node *ni,
|
||||
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, struct ieee80211_node *ni,
|
||||
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, struct mbuf *m,
|
||||
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, struct mbuf *m,
|
||||
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;
|
||||
|
@ -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,8 +784,8 @@ 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;
|
||||
@ -777,7 +796,22 @@ struct bwn_txhdr {
|
||||
uint8_t rts_frame[16];
|
||||
uint8_t pad1[2];
|
||||
struct bwn_plcp6 plcp;
|
||||
} __packed new;
|
||||
} __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 r598;
|
||||
} __packed body;
|
||||
} __packed;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user