[iwm] Sync valid_tx_ant and valid_rx_ant mask handling with iwlwifi.

* This fixes the phy_cfg field sent in the iwm_send_phy_cfg_cmd()
  command, which wasn't taking into account the valid_rx_ant and
  valid_tx_ant masks from nvm_data before.

Tested:

* 7260, STA mode, 2G and 5G

Obtained from:	DragonflyBSD commit cbb82693c18fd71b4eb86855b82d03995f352d65
This commit is contained in:
Adrian Chadd 2017-02-06 05:03:41 +00:00
parent 8c03b09087
commit 2a2476b30b
6 changed files with 61 additions and 49 deletions

View File

@ -771,8 +771,14 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
(int) tlv_len);
goto parse_out;
}
sc->sc_fw_phy_config =
sc->sc_fw.phy_config =
le32toh(*(const uint32_t *)tlv_data);
sc->sc_fw.valid_tx_ant = (sc->sc_fw.phy_config &
IWM_FW_PHY_CFG_TX_CHAIN) >>
IWM_FW_PHY_CFG_TX_CHAIN_POS;
sc->sc_fw.valid_rx_ant = (sc->sc_fw.phy_config &
IWM_FW_PHY_CFG_RX_CHAIN) >>
IWM_FW_PHY_CFG_RX_CHAIN_POS;
break;
case IWM_UCODE_TLV_API_CHANGES_SET: {
@ -1401,12 +1407,13 @@ iwm_mvm_nic_config(struct iwm_softc *sc)
{
uint8_t radio_cfg_type, radio_cfg_step, radio_cfg_dash;
uint32_t reg_val = 0;
uint32_t phy_config = iwm_mvm_get_phy_config(sc);
radio_cfg_type = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_TYPE) >>
radio_cfg_type = (phy_config & IWM_FW_PHY_CFG_RADIO_TYPE) >>
IWM_FW_PHY_CFG_RADIO_TYPE_POS;
radio_cfg_step = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_STEP) >>
radio_cfg_step = (phy_config & IWM_FW_PHY_CFG_RADIO_STEP) >>
IWM_FW_PHY_CFG_RADIO_STEP_POS;
radio_cfg_dash = (sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RADIO_DASH) >>
radio_cfg_dash = (phy_config & IWM_FW_PHY_CFG_RADIO_DASH) >>
IWM_FW_PHY_CFG_RADIO_DASH_POS;
/* SKU control */
@ -2696,7 +2703,7 @@ iwm_send_phy_cfg_cmd(struct iwm_softc *sc)
enum iwm_ucode_type ucode_type = sc->sc_uc_current;
/* Set parameters */
phy_cfg_cmd.phy_cfg = htole32(sc->sc_fw_phy_config);
phy_cfg_cmd.phy_cfg = htole32(iwm_mvm_get_phy_config(sc));
phy_cfg_cmd.calib_control.event_trigger =
sc->sc_default_calib[ucode_type].event_trigger;
phy_cfg_cmd.calib_control.flow_trigger =
@ -2783,6 +2790,7 @@ iwm_run_init_mvm_ucode(struct iwm_softc *sc, int justnvm)
if (error != 0)
return error;
#if 0
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
"%s: phy_txant=0x%08x, nvm_valid_tx_ant=0x%02x, valid=0x%02x\n",
__func__,
@ -2790,10 +2798,11 @@ iwm_run_init_mvm_ucode(struct iwm_softc *sc, int justnvm)
>> IWM_FW_PHY_CFG_TX_CHAIN_POS),
sc->nvm_data->valid_tx_ant,
iwm_fw_valid_tx_ant(sc));
#endif
/* Send TX valid antennas before triggering calibrations */
if ((error = iwm_send_tx_ant_cfg(sc, iwm_fw_valid_tx_ant(sc))) != 0) {
error = iwm_send_tx_ant_cfg(sc, iwm_mvm_get_valid_tx_ant(sc));
if (error != 0) {
device_printf(sc->sc_dev,
"failed to send antennas before calibration: %d\n", error);
return error;
@ -4238,11 +4247,11 @@ iwm_setrates(struct iwm_softc *sc, struct iwm_node *in)
#if 0
if (txant == 0)
txant = iwm_fw_valid_tx_ant(sc);
txant = iwm_mvm_get_valid_tx_ant(sc);
nextant = 1<<(ffs(txant)-1);
txant &= ~nextant;
#else
nextant = iwm_fw_valid_tx_ant(sc);
nextant = iwm_mvm_get_valid_tx_ant(sc);
#endif
/*
* Map the rate id into a rate index into
@ -4708,7 +4717,8 @@ iwm_init_hw(struct iwm_softc *sc)
goto error;
}
if ((error = iwm_send_tx_ant_cfg(sc, iwm_fw_valid_tx_ant(sc))) != 0) {
error = iwm_send_tx_ant_cfg(sc, iwm_mvm_get_valid_tx_ant(sc));
if (error != 0) {
device_printf(sc->sc_dev, "antenna config failed\n");
goto error;
}

View File

@ -202,8 +202,8 @@ iwm_mvm_phy_ctxt_cmd_data(struct iwm_softc *sc,
ieee80211_chan2ieee(ic, chan),
chains_static,
chains_dynamic,
iwm_fw_valid_rx_ant(sc),
iwm_fw_valid_tx_ant(sc));
iwm_mvm_get_valid_rx_ant(sc),
iwm_mvm_get_valid_tx_ant(sc));
cmd->ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
@ -217,13 +217,13 @@ iwm_mvm_phy_ctxt_cmd_data(struct iwm_softc *sc,
idle_cnt = chains_static;
active_cnt = chains_dynamic;
cmd->rxchain_info = htole32(iwm_fw_valid_rx_ant(sc) <<
cmd->rxchain_info = htole32(iwm_mvm_get_valid_rx_ant(sc) <<
IWM_PHY_RX_CHAIN_VALID_POS);
cmd->rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS);
cmd->rxchain_info |= htole32(active_cnt <<
IWM_PHY_RX_CHAIN_MIMO_CNT_POS);
cmd->txchain_info = htole32(iwm_fw_valid_tx_ant(sc));
cmd->txchain_info = htole32(iwm_mvm_get_valid_tx_ant(sc));
}
/*

View File

@ -172,7 +172,7 @@ iwm_mvm_scan_rx_chain(struct iwm_softc *sc)
uint16_t rx_chain;
uint8_t rx_ant;
rx_ant = iwm_fw_valid_rx_ant(sc);
rx_ant = iwm_mvm_get_valid_rx_ant(sc);
rx_chain = rx_ant << IWM_PHY_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_SEL_POS;
@ -209,7 +209,7 @@ iwm_mvm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)
for (i = 0, ind = sc->sc_scan_last_antenna;
i < IWM_RATE_MCS_ANT_NUM; i++) {
ind = (ind + 1) % IWM_RATE_MCS_ANT_NUM;
if (iwm_fw_valid_tx_ant(sc) & (1 << ind)) {
if (iwm_mvm_get_valid_tx_ant(sc) & (1 << ind)) {
sc->sc_scan_last_antenna = ind;
break;
}
@ -469,8 +469,8 @@ iwm_mvm_config_umac_scan(struct iwm_softc *sc)
if (scan_config == NULL)
return ENOMEM;
scan_config->tx_chains = htole32(iwm_fw_valid_tx_ant(sc));
scan_config->rx_chains = htole32(iwm_fw_valid_rx_ant(sc));
scan_config->tx_chains = htole32(iwm_mvm_get_valid_tx_ant(sc));
scan_config->rx_chains = htole32(iwm_mvm_get_valid_rx_ant(sc));
scan_config->legacy_rates = htole32(rates |
IWM_SCAN_CONFIG_SUPPORTED_RATE(rates));

View File

@ -428,31 +428,3 @@ iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
sc->sc_wantresp = -1;
wakeup(&sc->sc_wantresp);
}
uint8_t
iwm_fw_valid_tx_ant(struct iwm_softc *sc)
{
uint8_t tx_ant;
tx_ant = ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_TX_CHAIN)
>> IWM_FW_PHY_CFG_TX_CHAIN_POS);
if (sc->nvm_data->valid_tx_ant)
tx_ant &= sc->nvm_data->valid_tx_ant;
return tx_ant;
}
uint8_t
iwm_fw_valid_rx_ant(struct iwm_softc *sc)
{
uint8_t rx_ant;
rx_ant = ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RX_CHAIN)
>> IWM_FW_PHY_CFG_RX_CHAIN_POS);
if (sc->nvm_data->valid_rx_ant)
rx_ant &= sc->nvm_data->valid_rx_ant;
return rx_ant;
}

View File

@ -116,7 +116,34 @@ extern int iwm_mvm_send_cmd_pdu_status(struct iwm_softc *sc, uint8_t id,
uint16_t len, const void *data, uint32_t *status);
extern void iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd);
extern uint8_t iwm_fw_valid_tx_ant(struct iwm_softc *sc);
extern uint8_t iwm_fw_valid_rx_ant(struct iwm_softc *sc);
static inline uint8_t
iwm_mvm_get_valid_tx_ant(struct iwm_softc *sc)
{
return sc->nvm_data && sc->nvm_data->valid_tx_ant ?
sc->sc_fw.valid_tx_ant & sc->nvm_data->valid_tx_ant :
sc->sc_fw.valid_tx_ant;
}
static inline uint8_t
iwm_mvm_get_valid_rx_ant(struct iwm_softc *sc)
{
return sc->nvm_data && sc->nvm_data->valid_rx_ant ?
sc->sc_fw.valid_rx_ant & sc->nvm_data->valid_rx_ant :
sc->sc_fw.valid_rx_ant;
}
static inline uint32_t
iwm_mvm_get_phy_config(struct iwm_softc *sc)
{
uint32_t phy_config = ~(IWM_FW_PHY_CFG_TX_CHAIN |
IWM_FW_PHY_CFG_RX_CHAIN);
uint32_t valid_rx_ant = iwm_mvm_get_valid_rx_ant(sc);
uint32_t valid_tx_ant = iwm_mvm_get_valid_tx_ant(sc);
phy_config |= valid_tx_ant << IWM_FW_PHY_CFG_TX_CHAIN_POS |
valid_rx_ant << IWM_FW_PHY_CFG_RX_CHAIN_POS;
return sc->sc_fw.phy_config & phy_config;
}
#endif /* __IF_IWM_UTIL_H__ */

View File

@ -172,6 +172,10 @@ struct iwm_fw_info {
} fw_sect[IWM_UCODE_SECT_MAX];
int fw_count;
} fw_sects[IWM_UCODE_TYPE_MAX];
uint32_t phy_config;
uint8_t valid_tx_ant;
uint8_t valid_rx_ant;
};
struct iwm_nvm_data {
@ -465,7 +469,6 @@ struct iwm_softc {
bus_size_t sc_fwdmasegsz;
struct iwm_fw_info sc_fw;
int sc_fw_phy_config;
struct iwm_tlv_calib_ctrl sc_default_calib[IWM_UCODE_TYPE_MAX];
const struct iwm_cfg *cfg;