提交 ab1f5a53 编写于 作者: J John W. Linville
...@@ -275,7 +275,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend, ...@@ -275,7 +275,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
static const struct pci_device_id bcma_pci_bridge_tbl[] = { static const struct pci_device_id bcma_pci_bridge_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, /* 0xa8d8 */
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
...@@ -285,7 +285,8 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = { ...@@ -285,7 +285,8 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, /* 0xA8DB */ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, /* 0xa8db, BCM43217 (sic!) */
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43228) }, /* 0xa8dc */
{ 0, }, { 0, },
}; };
MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
......
...@@ -133,7 +133,7 @@ static bool bcma_is_core_needed_early(u16 core_id) ...@@ -133,7 +133,7 @@ static bool bcma_is_core_needed_early(u16 core_id)
return false; return false;
} }
#ifdef CONFIG_OF #if defined(CONFIG_OF) && defined(CONFIG_OF_ADDRESS)
static struct device_node *bcma_of_find_child_device(struct platform_device *parent, static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
struct bcma_device *core) struct bcma_device *core)
{ {
......
...@@ -80,6 +80,7 @@ struct reg_dmn_pair_mapping { ...@@ -80,6 +80,7 @@ struct reg_dmn_pair_mapping {
struct ath_regulatory { struct ath_regulatory {
char alpha2[2]; char alpha2[2];
enum nl80211_dfs_regions region;
u16 country_code; u16 country_code;
u16 max_power_level; u16 max_power_level;
u16 current_rd; u16 current_rd;
......
...@@ -664,6 +664,19 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) ...@@ -664,6 +664,19 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
ah->enabled_cals |= TX_CL_CAL; ah->enabled_cals |= TX_CL_CAL;
else else
ah->enabled_cals &= ~TX_CL_CAL; ah->enabled_cals &= ~TX_CL_CAL;
if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) {
if (ah->is_clk_25mhz) {
REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae);
} else {
REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1);
REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
REG_WRITE(ah, AR_SLP32_INC, 0x0001e800);
}
udelay(100);
}
} }
static void ar9003_hw_prog_ini(struct ath_hw *ah, static void ar9003_hw_prog_ini(struct ath_hw *ah,
......
...@@ -368,11 +368,11 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, ...@@ -368,11 +368,11 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
{ {
struct ath_regulatory *reg = ath9k_hw_regulatory(ah); struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
if (reg->power_limit != new_txpow) { if (reg->power_limit != new_txpow)
ath9k_hw_set_txpowerlimit(ah, new_txpow, false); ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
/* read back in case value is clamped */
*txpower = reg->max_power_level; /* read back in case value is clamped */
} *txpower = reg->max_power_level;
} }
EXPORT_SYMBOL(ath9k_cmn_update_txpow); EXPORT_SYMBOL(ath9k_cmn_update_txpow);
......
...@@ -455,7 +455,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, ...@@ -455,7 +455,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
"%2d %2x %1x %2x %2x\n", "%2d %2x %1x %2x %2x\n",
i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
(*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
val[2] & (0x7 << (i * 3)) >> (i * 3), (val[2] & (0x7 << (i * 3))) >> (i * 3),
(*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
} }
......
...@@ -870,19 +870,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, ...@@ -870,19 +870,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
udelay(RTC_PLL_SETTLE_DELAY); udelay(RTC_PLL_SETTLE_DELAY);
REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
if (ah->is_clk_25mhz) {
REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae);
} else {
REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1);
REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
REG_WRITE(ah, AR_SLP32_INC, 0x0001e800);
}
udelay(100);
}
} }
static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
......
...@@ -764,6 +764,32 @@ static const struct ieee80211_iface_combination if_comb[] = { ...@@ -764,6 +764,32 @@ static const struct ieee80211_iface_combination if_comb[] = {
#endif #endif
}; };
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
static void ath9k_set_mcc_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
if (!ath9k_is_chanctx_enabled())
return;
hw->flags |= IEEE80211_HW_QUEUE_CONTROL;
hw->queues = ATH9K_NUM_TX_QUEUES;
hw->offchannel_tx_hw_queue = hw->queues - 1;
hw->wiphy->interface_modes &= ~ BIT(NL80211_IFTYPE_WDS);
hw->wiphy->iface_combinations = if_comb_multi;
hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_multi);
hw->wiphy->max_scan_ssids = 255;
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
hw->wiphy->max_remain_on_channel_duration = 10000;
hw->chanctx_data_size = sizeof(void *);
hw->extra_beacon_tailroom =
sizeof(struct ieee80211_p2p_noa_attr) + 9;
ath_dbg(common, CHAN_CTX, "Use channel contexts\n");
}
#endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */
static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
{ {
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
...@@ -776,7 +802,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -776,7 +802,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_SPECTRUM_MGMT |
IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_SUPPORTS_RC_TABLE | IEEE80211_HW_SUPPORTS_RC_TABLE |
IEEE80211_HW_QUEUE_CONTROL |
IEEE80211_HW_SUPPORTS_HT_CCK_RATES; IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
if (ath9k_ps_enable) if (ath9k_ps_enable)
...@@ -811,24 +836,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -811,24 +836,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
} }
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
if (ath9k_is_chanctx_enabled()) {
hw->wiphy->interface_modes &= ~ BIT(NL80211_IFTYPE_WDS);
hw->wiphy->iface_combinations = if_comb_multi;
hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_multi);
hw->wiphy->max_scan_ssids = 255;
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
hw->wiphy->max_remain_on_channel_duration = 10000;
hw->chanctx_data_size = sizeof(void *);
hw->extra_beacon_tailroom =
sizeof(struct ieee80211_p2p_noa_attr) + 9;
ath_dbg(common, CHAN_CTX, "Use channel contexts\n");
}
#endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
...@@ -838,12 +845,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -838,12 +845,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
/* allow 4 queues per channel context + hw->queues = 4;
* 1 cab queue + 1 offchannel tx queue
*/
hw->queues = ATH9K_NUM_TX_QUEUES;
/* last queue for offchannel */
hw->offchannel_tx_hw_queue = hw->queues - 1;
hw->max_rates = 4; hw->max_rates = 4;
hw->max_listen_interval = 10; hw->max_listen_interval = 10;
hw->max_rate_tries = 10; hw->max_rate_tries = 10;
...@@ -867,6 +869,9 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -867,6 +869,9 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&common->sbands[IEEE80211_BAND_5GHZ]; &common->sbands[IEEE80211_BAND_5GHZ];
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
ath9k_set_mcc_capab(sc, hw);
#endif
ath9k_init_wow(hw); ath9k_init_wow(hw);
ath9k_cmn_reload_chainmask(ah); ath9k_cmn_reload_chainmask(ah);
......
...@@ -1184,6 +1184,9 @@ static void ath9k_assign_hw_queues(struct ieee80211_hw *hw, ...@@ -1184,6 +1184,9 @@ static void ath9k_assign_hw_queues(struct ieee80211_hw *hw,
{ {
int i; int i;
if (!ath9k_is_chanctx_enabled())
return;
for (i = 0; i < IEEE80211_NUM_ACS; i++) for (i = 0; i < IEEE80211_NUM_ACS; i++)
vif->hw_queue[i] = i; vif->hw_queue[i] = i;
......
...@@ -169,7 +169,10 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, ...@@ -169,7 +169,10 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
if (txq->stopped && if (txq->stopped &&
txq->pending_frames < sc->tx.txq_max_pending[q]) { txq->pending_frames < sc->tx.txq_max_pending[q]) {
ieee80211_wake_queue(sc->hw, info->hw_queue); if (ath9k_is_chanctx_enabled())
ieee80211_wake_queue(sc->hw, info->hw_queue);
else
ieee80211_wake_queue(sc->hw, q);
txq->stopped = false; txq->stopped = false;
} }
} }
...@@ -2247,7 +2250,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -2247,7 +2250,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
fi->txq = q; fi->txq = q;
if (++txq->pending_frames > sc->tx.txq_max_pending[q] && if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
!txq->stopped) { !txq->stopped) {
ieee80211_stop_queue(sc->hw, info->hw_queue); if (ath9k_is_chanctx_enabled())
ieee80211_stop_queue(sc->hw, info->hw_queue);
else
ieee80211_stop_queue(sc->hw, q);
txq->stopped = true; txq->stopped = true;
} }
} }
......
...@@ -515,6 +515,7 @@ void ath_reg_notifier_apply(struct wiphy *wiphy, ...@@ -515,6 +515,7 @@ void ath_reg_notifier_apply(struct wiphy *wiphy,
if (!request) if (!request)
return; return;
reg->region = request->dfs_region;
switch (request->initiator) { switch (request->initiator) {
case NL80211_REGDOM_SET_BY_CORE: case NL80211_REGDOM_SET_BY_CORE:
/* /*
...@@ -779,6 +780,19 @@ u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, ...@@ -779,6 +780,19 @@ u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
return SD_NO_CTL; return SD_NO_CTL;
} }
if (ath_regd_get_eepromRD(reg) == CTRY_DEFAULT) {
switch (reg->region) {
case NL80211_DFS_FCC:
return CTL_FCC;
case NL80211_DFS_ETSI:
return CTL_ETSI;
case NL80211_DFS_JP:
return CTL_MKK;
default:
break;
}
}
switch (band) { switch (band) {
case IEEE80211_BAND_2GHZ: case IEEE80211_BAND_2GHZ:
return reg->regpair->reg_2ghz_ctl; return reg->regpair->reg_2ghz_ctl;
......
...@@ -300,9 +300,7 @@ void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) ...@@ -300,9 +300,7 @@ void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg) void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
{ {
assert_mac_suspended(dev); b43_phy_write(dev, destreg, b43_phy_read(dev, srcreg));
dev->phy.ops->phy_write(dev, destreg,
dev->phy.ops->phy_read(dev, srcreg));
} }
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
......
...@@ -299,6 +299,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, ...@@ -299,6 +299,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
primary_offset = ch->center_freq1 - ch->chan->center_freq; primary_offset = ch->center_freq1 - ch->chan->center_freq;
switch (ch->width) { switch (ch->width) {
case NL80211_CHAN_WIDTH_20: case NL80211_CHAN_WIDTH_20:
case NL80211_CHAN_WIDTH_20_NOHT:
ch_inf.bw = BRCMU_CHAN_BW_20; ch_inf.bw = BRCMU_CHAN_BW_20;
WARN_ON(primary_offset != 0); WARN_ON(primary_offset != 0);
break; break;
...@@ -323,6 +324,10 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, ...@@ -323,6 +324,10 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
ch_inf.sb = BRCMU_CHAN_SB_LU; ch_inf.sb = BRCMU_CHAN_SB_LU;
} }
break; break;
case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_160:
case NL80211_CHAN_WIDTH_5:
case NL80211_CHAN_WIDTH_10:
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
} }
...@@ -333,6 +338,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, ...@@ -333,6 +338,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
case IEEE80211_BAND_5GHZ: case IEEE80211_BAND_5GHZ:
ch_inf.band = BRCMU_CHAN_BAND_5G; ch_inf.band = BRCMU_CHAN_BAND_5G;
break; break;
case IEEE80211_BAND_60GHZ:
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
} }
......
...@@ -670,7 +670,6 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci, ...@@ -670,7 +670,6 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
struct brcmf_sdio_dev *sdiodev) struct brcmf_sdio_dev *sdiodev)
{ {
int i; int i;
uint fw_len, nv_len;
char end; char end;
for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) { for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
...@@ -684,25 +683,25 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci, ...@@ -684,25 +683,25 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
return -ENODEV; return -ENODEV;
} }
fw_len = sizeof(sdiodev->fw_name) - 1;
nv_len = sizeof(sdiodev->nvram_name) - 1;
/* check if firmware path is provided by module parameter */ /* check if firmware path is provided by module parameter */
if (brcmf_firmware_path[0] != '\0') { if (brcmf_firmware_path[0] != '\0') {
strncpy(sdiodev->fw_name, brcmf_firmware_path, fw_len); strlcpy(sdiodev->fw_name, brcmf_firmware_path,
strncpy(sdiodev->nvram_name, brcmf_firmware_path, nv_len); sizeof(sdiodev->fw_name));
fw_len -= strlen(sdiodev->fw_name); strlcpy(sdiodev->nvram_name, brcmf_firmware_path,
nv_len -= strlen(sdiodev->nvram_name); sizeof(sdiodev->nvram_name));
end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1]; end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
if (end != '/') { if (end != '/') {
strncat(sdiodev->fw_name, "/", fw_len); strlcat(sdiodev->fw_name, "/",
strncat(sdiodev->nvram_name, "/", nv_len); sizeof(sdiodev->fw_name));
fw_len--; strlcat(sdiodev->nvram_name, "/",
nv_len--; sizeof(sdiodev->nvram_name));
} }
} }
strncat(sdiodev->fw_name, brcmf_fwname_data[i].bin, fw_len); strlcat(sdiodev->fw_name, brcmf_fwname_data[i].bin,
strncat(sdiodev->nvram_name, brcmf_fwname_data[i].nv, nv_len); sizeof(sdiodev->fw_name));
strlcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv,
sizeof(sdiodev->nvram_name));
return 0; return 0;
} }
......
...@@ -284,7 +284,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -284,7 +284,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (WARN_ON_ONCE(mvm->init_ucode_complete)) if (WARN_ON_ONCE(mvm->init_ucode_complete || mvm->calibrating))
return 0; return 0;
iwl_init_notification_wait(&mvm->notif_wait, iwl_init_notification_wait(&mvm->notif_wait,
...@@ -334,6 +334,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -334,6 +334,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
goto out; goto out;
} }
mvm->calibrating = true;
/* Send TX valid antennas before triggering calibrations */ /* Send TX valid antennas before triggering calibrations */
ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant); ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret) if (ret)
...@@ -358,11 +360,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -358,11 +360,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
MVM_UCODE_CALIB_TIMEOUT); MVM_UCODE_CALIB_TIMEOUT);
if (!ret) if (!ret)
mvm->init_ucode_complete = true; mvm->init_ucode_complete = true;
if (ret && iwl_mvm_is_radio_killed(mvm)) {
IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
ret = 1;
}
goto out; goto out;
error: error:
iwl_remove_notification(&mvm->notif_wait, &calib_wait); iwl_remove_notification(&mvm->notif_wait, &calib_wait);
out: out:
mvm->calibrating = false;
if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) { if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
/* we want to debug INIT and we have no NVM - fake */ /* we want to debug INIT and we have no NVM - fake */
mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) + mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
......
...@@ -825,6 +825,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) ...@@ -825,6 +825,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
mvm->scan_status = IWL_MVM_SCAN_NONE; mvm->scan_status = IWL_MVM_SCAN_NONE;
mvm->ps_disabled = false; mvm->ps_disabled = false;
mvm->calibrating = false;
/* just in case one was running */ /* just in case one was running */
ieee80211_remain_on_channel_expired(mvm->hw); ieee80211_remain_on_channel_expired(mvm->hw);
......
...@@ -548,6 +548,7 @@ struct iwl_mvm { ...@@ -548,6 +548,7 @@ struct iwl_mvm {
enum iwl_ucode_type cur_ucode; enum iwl_ucode_type cur_ucode;
bool ucode_loaded; bool ucode_loaded;
bool init_ucode_complete; bool init_ucode_complete;
bool calibrating;
u32 error_event_table; u32 error_event_table;
u32 log_event_table; u32 log_event_table;
u32 umac_error_event_table; u32 umac_error_event_table;
......
...@@ -427,6 +427,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -427,6 +427,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
} }
mvm->sf_state = SF_UNINIT; mvm->sf_state = SF_UNINIT;
mvm->low_latency_agg_frame_limit = 6; mvm->low_latency_agg_frame_limit = 6;
mvm->cur_ucode = IWL_UCODE_INIT;
mutex_init(&mvm->mutex); mutex_init(&mvm->mutex);
mutex_init(&mvm->d0i3_suspend_mutex); mutex_init(&mvm->d0i3_suspend_mutex);
...@@ -757,6 +758,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) ...@@ -757,6 +758,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
{ {
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
bool calibrating = ACCESS_ONCE(mvm->calibrating);
if (state) if (state)
set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
...@@ -765,7 +767,15 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) ...@@ -765,7 +767,15 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
return state && mvm->cur_ucode != IWL_UCODE_INIT; /* iwl_run_init_mvm_ucode is waiting for results, abort it */
if (calibrating)
iwl_abort_notification_waits(&mvm->notif_wait);
/*
* Stop the device if we run OPERATIONAL firmware or if we are in the
* middle of the calibrations.
*/
return state && (mvm->cur_ucode != IWL_UCODE_INIT || calibrating);
} }
static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
......
...@@ -603,16 +603,6 @@ static int iwl_mvm_cancel_regular_scan(struct iwl_mvm *mvm) ...@@ -603,16 +603,6 @@ static int iwl_mvm_cancel_regular_scan(struct iwl_mvm *mvm)
SCAN_COMPLETE_NOTIFICATION }; SCAN_COMPLETE_NOTIFICATION };
int ret; int ret;
if (mvm->scan_status == IWL_MVM_SCAN_NONE)
return 0;
if (iwl_mvm_is_radio_killed(mvm)) {
ieee80211_scan_completed(mvm->hw, true);
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
mvm->scan_status = IWL_MVM_SCAN_NONE;
return 0;
}
iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort, iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort,
scan_abort_notif, scan_abort_notif,
ARRAY_SIZE(scan_abort_notif), ARRAY_SIZE(scan_abort_notif),
...@@ -1431,6 +1421,16 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm, ...@@ -1431,6 +1421,16 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
int iwl_mvm_cancel_scan(struct iwl_mvm *mvm) int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
{ {
if (mvm->scan_status == IWL_MVM_SCAN_NONE)
return 0;
if (iwl_mvm_is_radio_killed(mvm)) {
ieee80211_scan_completed(mvm->hw, true);
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
mvm->scan_status = IWL_MVM_SCAN_NONE;
return 0;
}
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
return iwl_mvm_scan_offload_stop(mvm, true); return iwl_mvm_scan_offload_stop(mvm, true);
return iwl_mvm_cancel_regular_scan(mvm); return iwl_mvm_cancel_regular_scan(mvm);
......
...@@ -913,7 +913,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) ...@@ -913,7 +913,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
* restart. So don't process again if the device is * restart. So don't process again if the device is
* already dead. * already dead.
*/ */
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) { if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n");
iwl_pcie_tx_stop(trans); iwl_pcie_tx_stop(trans);
iwl_pcie_rx_stop(trans); iwl_pcie_rx_stop(trans);
...@@ -943,7 +944,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) ...@@ -943,7 +944,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
/* clear all status bits */ /* clear all status bits */
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
clear_bit(STATUS_INT_ENABLED, &trans->status); clear_bit(STATUS_INT_ENABLED, &trans->status);
clear_bit(STATUS_DEVICE_ENABLED, &trans->status);
clear_bit(STATUS_TPOWER_PMI, &trans->status); clear_bit(STATUS_TPOWER_PMI, &trans->status);
clear_bit(STATUS_RFKILL, &trans->status); clear_bit(STATUS_RFKILL, &trans->status);
...@@ -1898,8 +1898,7 @@ static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans, ...@@ -1898,8 +1898,7 @@ static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans,
int reg; int reg;
__le32 *val; __le32 *val;
prph_len += sizeof(*data) + sizeof(*prph) + prph_len += sizeof(**data) + sizeof(*prph) + num_bytes_in_chunk;
num_bytes_in_chunk;
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH); (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
(*data)->len = cpu_to_le32(sizeof(*prph) + (*data)->len = cpu_to_le32(sizeof(*prph) +
......
...@@ -2191,7 +2191,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -2191,7 +2191,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
if (err != 0) { if (err != 0) {
printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n", printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n",
err); err);
goto failed_hw; goto failed_bind;
} }
skb_queue_head_init(&data->pending); skb_queue_head_init(&data->pending);
...@@ -2397,6 +2397,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -2397,6 +2397,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
return idx; return idx;
failed_hw: failed_hw:
device_release_driver(data->dev);
failed_bind:
device_unregister(data->dev); device_unregister(data->dev);
failed_drvdata: failed_drvdata:
ieee80211_free_hw(hw); ieee80211_free_hw(hw);
......
...@@ -196,6 +196,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv, ...@@ -196,6 +196,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
del_timer_sync(&tbl->timer_context.timer); del_timer_sync(&tbl->timer_context.timer);
tbl->timer_context.timer_is_set = false;
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
list_del(&tbl->list); list_del(&tbl->list);
...@@ -297,6 +298,7 @@ mwifiex_flush_data(unsigned long context) ...@@ -297,6 +298,7 @@ mwifiex_flush_data(unsigned long context)
(struct reorder_tmr_cnxt *) context; (struct reorder_tmr_cnxt *) context;
int start_win, seq_num; int start_win, seq_num;
ctx->timer_is_set = false;
seq_num = mwifiex_11n_find_last_seq_num(ctx); seq_num = mwifiex_11n_find_last_seq_num(ctx);
if (seq_num < 0) if (seq_num < 0)
...@@ -385,6 +387,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, ...@@ -385,6 +387,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
new_node->timer_context.ptr = new_node; new_node->timer_context.ptr = new_node;
new_node->timer_context.priv = priv; new_node->timer_context.priv = priv;
new_node->timer_context.timer_is_set = false;
init_timer(&new_node->timer_context.timer); init_timer(&new_node->timer_context.timer);
new_node->timer_context.timer.function = mwifiex_flush_data; new_node->timer_context.timer.function = mwifiex_flush_data;
...@@ -399,6 +402,22 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, ...@@ -399,6 +402,22 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
} }
static void
mwifiex_11n_rxreorder_timer_restart(struct mwifiex_rx_reorder_tbl *tbl)
{
u32 min_flush_time;
if (tbl->win_size >= MWIFIEX_BA_WIN_SIZE_32)
min_flush_time = MIN_FLUSH_TIMER_15_MS;
else
min_flush_time = MIN_FLUSH_TIMER_MS;
mod_timer(&tbl->timer_context.timer,
jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size));
tbl->timer_context.timer_is_set = true;
}
/* /*
* This function prepares command for adding a BA request. * This function prepares command for adding a BA request.
* *
...@@ -523,31 +542,31 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, ...@@ -523,31 +542,31 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
u8 *ta, u8 pkt_type, void *payload) u8 *ta, u8 pkt_type, void *payload)
{ {
struct mwifiex_rx_reorder_tbl *tbl; struct mwifiex_rx_reorder_tbl *tbl;
int start_win, end_win, win_size; int prev_start_win, start_win, end_win, win_size;
u16 pkt_index; u16 pkt_index;
bool init_window_shift = false; bool init_window_shift = false;
int ret = 0;
tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
if (!tbl) { if (!tbl) {
if (pkt_type != PKT_TYPE_BAR) if (pkt_type != PKT_TYPE_BAR)
mwifiex_11n_dispatch_pkt(priv, payload); mwifiex_11n_dispatch_pkt(priv, payload);
return 0; return ret;
} }
if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) { if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) {
mwifiex_11n_dispatch_pkt(priv, payload); mwifiex_11n_dispatch_pkt(priv, payload);
return 0; return ret;
} }
start_win = tbl->start_win; start_win = tbl->start_win;
prev_start_win = start_win;
win_size = tbl->win_size; win_size = tbl->win_size;
end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) { if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) {
init_window_shift = true; init_window_shift = true;
tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT; tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT;
} }
mod_timer(&tbl->timer_context.timer,
jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size));
if (tbl->flags & RXREOR_FORCE_NO_DROP) { if (tbl->flags & RXREOR_FORCE_NO_DROP) {
dev_dbg(priv->adapter->dev, dev_dbg(priv->adapter->dev,
...@@ -568,11 +587,14 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, ...@@ -568,11 +587,14 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) { if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
if (seq_num >= ((start_win + TWOPOW11) & if (seq_num >= ((start_win + TWOPOW11) &
(MAX_TID_VALUE - 1)) && (MAX_TID_VALUE - 1)) &&
seq_num < start_win) seq_num < start_win) {
return -1; ret = -1;
goto done;
}
} else if ((seq_num < start_win) || } else if ((seq_num < start_win) ||
(seq_num > (start_win + TWOPOW11))) { (seq_num >= (start_win + TWOPOW11))) {
return -1; ret = -1;
goto done;
} }
} }
...@@ -601,8 +623,10 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, ...@@ -601,8 +623,10 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
else else
pkt_index = (seq_num+MAX_TID_VALUE) - start_win; pkt_index = (seq_num+MAX_TID_VALUE) - start_win;
if (tbl->rx_reorder_ptr[pkt_index]) if (tbl->rx_reorder_ptr[pkt_index]) {
return -1; ret = -1;
goto done;
}
tbl->rx_reorder_ptr[pkt_index] = payload; tbl->rx_reorder_ptr[pkt_index] = payload;
} }
...@@ -613,7 +637,11 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, ...@@ -613,7 +637,11 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
*/ */
mwifiex_11n_scan_and_dispatch(priv, tbl); mwifiex_11n_scan_and_dispatch(priv, tbl);
return 0; done:
if (!tbl->timer_context.timer_is_set ||
prev_start_win != tbl->start_win)
mwifiex_11n_rxreorder_timer_restart(tbl);
return ret;
} }
/* /*
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#define _MWIFIEX_11N_RXREORDER_H_ #define _MWIFIEX_11N_RXREORDER_H_
#define MIN_FLUSH_TIMER_MS 50 #define MIN_FLUSH_TIMER_MS 50
#define MIN_FLUSH_TIMER_15_MS 15
#define MWIFIEX_BA_WIN_SIZE_32 32
#define PKT_TYPE_BAR 0xE7 #define PKT_TYPE_BAR 0xE7
#define MAX_TID_VALUE (2 << 11) #define MAX_TID_VALUE (2 << 11)
......
...@@ -600,6 +600,7 @@ struct reorder_tmr_cnxt { ...@@ -600,6 +600,7 @@ struct reorder_tmr_cnxt {
struct timer_list timer; struct timer_list timer;
struct mwifiex_rx_reorder_tbl *ptr; struct mwifiex_rx_reorder_tbl *ptr;
struct mwifiex_private *priv; struct mwifiex_private *priv;
u8 timer_is_set;
}; };
struct mwifiex_rx_reorder_tbl { struct mwifiex_rx_reorder_tbl {
......
...@@ -1111,6 +1111,7 @@ static struct usb_device_id rt2800usb_device_table[] = { ...@@ -1111,6 +1111,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Ovislink */ /* Ovislink */
{ USB_DEVICE(0x1b75, 0x3071) }, { USB_DEVICE(0x1b75, 0x3071) },
{ USB_DEVICE(0x1b75, 0x3072) }, { USB_DEVICE(0x1b75, 0x3072) },
{ USB_DEVICE(0x1b75, 0xa200) },
/* Para */ /* Para */
{ USB_DEVICE(0x20b8, 0x8888) }, { USB_DEVICE(0x20b8, 0x8888) },
/* Pegatron */ /* Pegatron */
......
...@@ -158,55 +158,29 @@ void rt2x00queue_align_frame(struct sk_buff *skb) ...@@ -158,55 +158,29 @@ void rt2x00queue_align_frame(struct sk_buff *skb)
skb_trim(skb, frame_length); skb_trim(skb, frame_length);
} }
void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) /*
* H/W needs L2 padding between the header and the paylod if header size
* is not 4 bytes aligned.
*/
void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int hdr_len)
{ {
unsigned int payload_length = skb->len - header_length; unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
unsigned int header_align = ALIGN_SIZE(skb, 0);
unsigned int payload_align = ALIGN_SIZE(skb, header_length);
unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0;
/* if (!l2pad)
* Adjust the header alignment if the payload needs to be moved more
* than the header.
*/
if (payload_align > header_align)
header_align += 4;
/* There is nothing to do if no alignment is needed */
if (!header_align)
return; return;
/* Reserve the amount of space needed in front of the frame */ skb_push(skb, l2pad);
skb_push(skb, header_align); memmove(skb->data, skb->data + l2pad, hdr_len);
/*
* Move the header.
*/
memmove(skb->data, skb->data + header_align, header_length);
/* Move the payload, if present and if required */
if (payload_length && payload_align)
memmove(skb->data + header_length + l2pad,
skb->data + header_length + l2pad + payload_align,
payload_length);
/* Trim the skb to the correct size */
skb_trim(skb, header_length + l2pad + payload_length);
} }
void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int hdr_len)
{ {
/* unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
* L2 padding is only present if the skb contains more than just the
* IEEE 802.11 header.
*/
unsigned int l2pad = (skb->len > header_length) ?
L2PAD_SIZE(header_length) : 0;
if (!l2pad) if (!l2pad)
return; return;
memmove(skb->data + l2pad, skb->data, header_length); memmove(skb->data + l2pad, skb->data, hdr_len);
skb_pull(skb, l2pad); skb_pull(skb, l2pad);
} }
......
...@@ -467,7 +467,7 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) ...@@ -467,7 +467,7 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw); rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw);
/* <2> work queue */ /* <2> work queue */
rtlpriv->works.hw = hw; rtlpriv->works.hw = hw;
rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0); rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
(void *)rtl_watchdog_wq_callback); (void *)rtl_watchdog_wq_callback);
INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
......
...@@ -1828,3 +1828,9 @@ const struct ieee80211_ops rtl_ops = { ...@@ -1828,3 +1828,9 @@ const struct ieee80211_ops rtl_ops = {
.flush = rtl_op_flush, .flush = rtl_op_flush,
}; };
EXPORT_SYMBOL_GPL(rtl_ops); EXPORT_SYMBOL_GPL(rtl_ops);
bool rtl_btc_status_false(void)
{
return false;
}
EXPORT_SYMBOL_GPL(rtl_btc_status_false);
...@@ -42,5 +42,6 @@ void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr, ...@@ -42,5 +42,6 @@ void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr,
u32 mask, u32 data); u32 mask, u32 data);
void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data); void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data);
bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb);
bool rtl_btc_status_false(void);
#endif #endif
...@@ -842,7 +842,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) ...@@ -842,7 +842,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
break; break;
} }
/* handle command packet here */ /* handle command packet here */
if (rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) { if (rtlpriv->cfg->ops->rx_command_packet &&
rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
goto end; goto end;
} }
...@@ -1127,9 +1128,14 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) ...@@ -1127,9 +1128,14 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
__skb_queue_tail(&ring->queue, pskb); __skb_queue_tail(&ring->queue, pskb);
rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN, if (rtlpriv->use_new_trx_flow) {
&temp_one); temp_one = 4;
rtlpriv->cfg->ops->set_desc(hw, (u8 *)pbuffer_desc, true,
HW_DESC_OWN, (u8 *)&temp_one);
} else {
rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN,
&temp_one);
}
return; return;
} }
...@@ -1370,9 +1376,9 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw, ...@@ -1370,9 +1376,9 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
ring->desc = NULL; ring->desc = NULL;
if (rtlpriv->use_new_trx_flow) { if (rtlpriv->use_new_trx_flow) {
pci_free_consistent(rtlpci->pdev, pci_free_consistent(rtlpci->pdev,
sizeof(*ring->desc) * ring->entries, sizeof(*ring->buffer_desc) * ring->entries,
ring->buffer_desc, ring->buffer_desc_dma); ring->buffer_desc, ring->buffer_desc_dma);
ring->desc = NULL; ring->buffer_desc = NULL;
} }
} }
...@@ -1543,7 +1549,6 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) ...@@ -1543,7 +1549,6 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
true, true,
HW_DESC_TXBUFF_ADDR), HW_DESC_TXBUFF_ADDR),
skb->len, PCI_DMA_TODEVICE); skb->len, PCI_DMA_TODEVICE);
ring->idx = (ring->idx + 1) % ring->entries;
kfree_skb(skb); kfree_skb(skb);
ring->idx = (ring->idx + 1) % ring->entries; ring->idx = (ring->idx + 1) % ring->entries;
} }
...@@ -1796,7 +1801,8 @@ static int rtl_pci_start(struct ieee80211_hw *hw) ...@@ -1796,7 +1801,8 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
rtl_pci_reset_trx_ring(hw); rtl_pci_reset_trx_ring(hw);
rtlpci->driver_is_goingto_unload = false; rtlpci->driver_is_goingto_unload = false;
if (rtlpriv->cfg->ops->get_btc_status()) { if (rtlpriv->cfg->ops->get_btc_status &&
rtlpriv->cfg->ops->get_btc_status()) {
rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv); rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv);
rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv); rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv);
} }
......
...@@ -656,7 +656,8 @@ static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { ...@@ -656,7 +656,8 @@ static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; };
void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *))
{ {
struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
...@@ -722,7 +723,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) ...@@ -722,7 +723,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
memcpy((u8 *)skb_put(skb, totalpacketlen), memcpy((u8 *)skb_put(skb, totalpacketlen),
&reserved_page_packet, totalpacketlen); &reserved_page_packet, totalpacketlen);
rtstatus = rtl_cmd_send_packet(hw, skb); if (cmd_send_packet)
rtstatus = cmd_send_packet(hw, skb);
else
rtstatus = rtl_cmd_send_packet(hw, skb);
if (rtstatus) if (rtstatus)
b_dlok = true; b_dlok = true;
......
...@@ -109,7 +109,9 @@ void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, ...@@ -109,7 +109,9 @@ void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
u32 cmd_len, u8 *p_cmdbuffer); u32 cmd_len, u8 *p_cmdbuffer);
void rtl92c_firmware_selfreset(struct ieee80211_hw *hw); void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); void rtl92c_set_fw_rsvdpagepkt
(struct ieee80211_hw *hw,
bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *));
void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len); void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len);
void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
......
...@@ -114,6 +114,8 @@ ...@@ -114,6 +114,8 @@
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4)
#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ #define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32)
#define CHIP_VER_B BIT(4) #define CHIP_VER_B BIT(4)
#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3) #define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3)
......
...@@ -459,7 +459,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) ...@@ -459,7 +459,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
tmp_reg422 & (~BIT(6))); tmp_reg422 & (~BIT(6)));
rtl92c_set_fw_rsvdpagepkt(hw, 0); rtl92c_set_fw_rsvdpagepkt(hw, NULL);
_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4));
......
...@@ -244,6 +244,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { ...@@ -244,6 +244,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {
.phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate,
.phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback,
.dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower,
.get_btc_status = rtl_btc_status_false,
}; };
static struct rtl_mod_params rtl92ce_mod_params = { static struct rtl_mod_params rtl92ce_mod_params = {
......
...@@ -728,6 +728,9 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) ...@@ -728,6 +728,9 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name)
case HW_DESC_RXPKT_LEN: case HW_DESC_RXPKT_LEN:
ret = GET_RX_DESC_PKT_LEN(pdesc); ret = GET_RX_DESC_PKT_LEN(pdesc);
break; break;
case HW_DESC_RXBUFF_ADDR:
ret = GET_RX_STATUS_DESC_BUFF_ADDR(pdesc);
break;
default: default:
RT_ASSERT(false, "ERR rxdesc :%d not process\n", RT_ASSERT(false, "ERR rxdesc :%d not process\n",
desc_name); desc_name);
......
...@@ -1592,6 +1592,20 @@ void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) ...@@ -1592,6 +1592,20 @@ void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
} }
} }
bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
{
/* Currently nothing happens here.
* Traffic stops after some seconds in WPA2 802.11n mode.
* Maybe because rtl8192cu chip should be set from here?
* If I understand correctly, the realtek vendor driver sends some urbs
* if its "here".
*
* This is maybe necessary:
* rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb);
*/
return true;
}
void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
{ {
struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_priv *rtlpriv = rtl_priv(hw);
...@@ -1939,7 +1953,8 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) ...@@ -1939,7 +1953,8 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
recover = true; recover = true;
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
tmp_reg422 & (~BIT(6))); tmp_reg422 & (~BIT(6)));
rtl92c_set_fw_rsvdpagepkt(hw, 0); rtl92c_set_fw_rsvdpagepkt(hw,
&usb_cmd_send_packet);
_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0); _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4)); _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
if (recover) if (recover)
......
...@@ -104,7 +104,6 @@ bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid); ...@@ -104,7 +104,6 @@ bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid);
void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
int rtl92c_download_fw(struct ieee80211_hw *hw); int rtl92c_download_fw(struct ieee80211_hw *hw);
void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished);
void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
u8 element_id, u32 cmd_len, u8 *p_cmdbuffer); u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
......
...@@ -101,6 +101,12 @@ static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw) ...@@ -101,6 +101,12 @@ static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw)
} }
} }
/* get bt coexist status */
static bool rtl92cu_get_btc_status(void)
{
return false;
}
static struct rtl_hal_ops rtl8192cu_hal_ops = { static struct rtl_hal_ops rtl8192cu_hal_ops = {
.init_sw_vars = rtl92cu_init_sw_vars, .init_sw_vars = rtl92cu_init_sw_vars,
.deinit_sw_vars = rtl92cu_deinit_sw_vars, .deinit_sw_vars = rtl92cu_deinit_sw_vars,
...@@ -148,6 +154,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = { ...@@ -148,6 +154,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
.phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback, .phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback,
.dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower, .dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower,
.fill_h2c_cmd = rtl92c_fill_h2c_cmd, .fill_h2c_cmd = rtl92c_fill_h2c_cmd,
.get_btc_status = rtl92cu_get_btc_status,
}; };
static struct rtl_mod_params rtl92cu_mod_params = { static struct rtl_mod_params rtl92cu_mod_params = {
......
...@@ -251,6 +251,7 @@ static struct rtl_hal_ops rtl8192de_hal_ops = { ...@@ -251,6 +251,7 @@ static struct rtl_hal_ops rtl8192de_hal_ops = {
.get_rfreg = rtl92d_phy_query_rf_reg, .get_rfreg = rtl92d_phy_query_rf_reg,
.set_rfreg = rtl92d_phy_set_rf_reg, .set_rfreg = rtl92d_phy_set_rf_reg,
.linked_set_reg = rtl92d_linked_set_reg, .linked_set_reg = rtl92d_linked_set_reg,
.get_btc_status = rtl_btc_status_false,
}; };
static struct rtl_mod_params rtl92de_mod_params = { static struct rtl_mod_params rtl92de_mod_params = {
......
...@@ -362,7 +362,7 @@ void rtl92ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) ...@@ -362,7 +362,7 @@ void rtl92ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
} }
break; break;
default: default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
"switch case not process %x\n", variable); "switch case not process %x\n", variable);
break; break;
} }
...@@ -591,7 +591,7 @@ void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) ...@@ -591,7 +591,7 @@ void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
acm_ctrl &= (~ACMHW_BEQEN); acm_ctrl &= (~ACMHW_BEQEN);
break; break;
default: default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
"switch case not process\n"); "switch case not process\n");
break; break;
} }
...@@ -710,7 +710,7 @@ void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) ...@@ -710,7 +710,7 @@ void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
} }
break; break;
default: default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
"switch case not process %x\n", variable); "switch case not process %x\n", variable);
break; break;
} }
...@@ -2424,7 +2424,7 @@ void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index, ...@@ -2424,7 +2424,7 @@ void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index,
enc_algo = CAM_AES; enc_algo = CAM_AES;
break; break;
default: default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
"switch case not process\n"); "switch case not process\n");
enc_algo = CAM_TKIP; enc_algo = CAM_TKIP;
break; break;
......
...@@ -446,6 +446,8 @@ ...@@ -446,6 +446,8 @@
/* DWORD 6 */ /* DWORD 6 */
#define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \ #define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val)
#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32)
#define SE_RX_HAL_IS_CCK_RATE(_pdesc)\ #define SE_RX_HAL_IS_CCK_RATE(_pdesc)\
(GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \ (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \
......
...@@ -1201,6 +1201,9 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw, ...@@ -1201,6 +1201,9 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,
} }
if (type != NL80211_IFTYPE_AP &&
rtlpriv->mac80211.link_state < MAC80211_LINKED)
bt_msr = rtl_read_byte(rtlpriv, MSR) & ~MSR_LINK_MASK;
rtl_write_byte(rtlpriv, (MSR), bt_msr); rtl_write_byte(rtlpriv, (MSR), bt_msr);
temp = rtl_read_dword(rtlpriv, TCR); temp = rtl_read_dword(rtlpriv, TCR);
...@@ -1262,6 +1265,7 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw) ...@@ -1262,6 +1265,7 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw)
rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]); rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]);
/* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */ /* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */
rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F); rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F);
rtlpci->irq_enabled = true;
} }
void rtl92se_disable_interrupt(struct ieee80211_hw *hw) void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
...@@ -1276,8 +1280,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw) ...@@ -1276,8 +1280,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
rtlpci = rtl_pcidev(rtl_pcipriv(hw)); rtlpci = rtl_pcidev(rtl_pcipriv(hw));
rtl_write_dword(rtlpriv, INTA_MASK, 0); rtl_write_dword(rtlpriv, INTA_MASK, 0);
rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
rtlpci->irq_enabled = false;
synchronize_irq(rtlpci->pdev->irq);
} }
static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data)
......
...@@ -399,6 +399,8 @@ static bool _rtl92s_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, ...@@ -399,6 +399,8 @@ static bool _rtl92s_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
case 2: case 2:
currentcmd = &postcommoncmd[*step]; currentcmd = &postcommoncmd[*step];
break; break;
default:
return true;
} }
if (currentcmd->cmdid == CMDID_END) { if (currentcmd->cmdid == CMDID_END) {
......
...@@ -87,11 +87,8 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) ...@@ -87,11 +87,8 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw)
static void rtl92se_fw_cb(const struct firmware *firmware, void *context) static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
{ {
struct ieee80211_hw *hw = context; struct ieee80211_hw *hw = context;
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
struct rt_firmware *pfirmware = NULL; struct rt_firmware *pfirmware = NULL;
int err;
RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
"Firmware callback routine entered!\n"); "Firmware callback routine entered!\n");
...@@ -112,20 +109,6 @@ static void rtl92se_fw_cb(const struct firmware *firmware, void *context) ...@@ -112,20 +109,6 @@ static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
pfirmware->sz_fw_tmpbufferlen = firmware->size; pfirmware->sz_fw_tmpbufferlen = firmware->size;
release_firmware(firmware); release_firmware(firmware);
err = ieee80211_register_hw(hw);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Can't register mac80211 hw\n");
return;
} else {
rtlpriv->mac80211.mac80211_registered = 1;
}
rtlpci->irq_alloc = 1;
set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
/*init rfkill */
rtl_init_rfkill(hw);
} }
static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
...@@ -226,8 +209,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) ...@@ -226,8 +209,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
if (!rtlpriv->rtlhal.pfirmware) if (!rtlpriv->rtlhal.pfirmware)
return 1; return 1;
rtlpriv->max_fw_size = RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE; rtlpriv->max_fw_size = RTL8190_MAX_FIRMWARE_CODE_SIZE*2 +
sizeof(struct fw_hdr);
pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n" pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
"Loading firmware %s\n", rtlpriv->cfg->fw_name); "Loading firmware %s\n", rtlpriv->cfg->fw_name);
/* request fw */ /* request fw */
...@@ -253,6 +236,19 @@ static void rtl92s_deinit_sw_vars(struct ieee80211_hw *hw) ...@@ -253,6 +236,19 @@ static void rtl92s_deinit_sw_vars(struct ieee80211_hw *hw)
} }
} }
static bool rtl92se_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue,
u16 index)
{
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
u8 *entry = (u8 *)(&ring->desc[ring->idx]);
u8 own = (u8)rtl92se_get_desc(entry, true, HW_DESC_OWN);
if (own)
return false;
return true;
}
static struct rtl_hal_ops rtl8192se_hal_ops = { static struct rtl_hal_ops rtl8192se_hal_ops = {
.init_sw_vars = rtl92s_init_sw_vars, .init_sw_vars = rtl92s_init_sw_vars,
.deinit_sw_vars = rtl92s_deinit_sw_vars, .deinit_sw_vars = rtl92s_deinit_sw_vars,
...@@ -286,6 +282,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = { ...@@ -286,6 +282,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = {
.led_control = rtl92se_led_control, .led_control = rtl92se_led_control,
.set_desc = rtl92se_set_desc, .set_desc = rtl92se_set_desc,
.get_desc = rtl92se_get_desc, .get_desc = rtl92se_get_desc,
.is_tx_desc_closed = rtl92se_is_tx_desc_closed,
.tx_polling = rtl92se_tx_polling, .tx_polling = rtl92se_tx_polling,
.enable_hw_sec = rtl92se_enable_hw_security_config, .enable_hw_sec = rtl92se_enable_hw_security_config,
.set_key = rtl92se_set_key, .set_key = rtl92se_set_key,
...@@ -294,6 +291,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = { ...@@ -294,6 +291,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = {
.set_bbreg = rtl92s_phy_set_bb_reg, .set_bbreg = rtl92s_phy_set_bb_reg,
.get_rfreg = rtl92s_phy_query_rf_reg, .get_rfreg = rtl92s_phy_query_rf_reg,
.set_rfreg = rtl92s_phy_set_rf_reg, .set_rfreg = rtl92s_phy_set_rf_reg,
.get_btc_status = rtl_btc_status_false,
}; };
static struct rtl_mod_params rtl92se_mod_params = { static struct rtl_mod_params rtl92se_mod_params = {
...@@ -322,6 +320,8 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = { ...@@ -322,6 +320,8 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = {
.maps[MAC_RCR_ACRC32] = RCR_ACRC32, .maps[MAC_RCR_ACRC32] = RCR_ACRC32,
.maps[MAC_RCR_ACF] = RCR_ACF, .maps[MAC_RCR_ACF] = RCR_ACF,
.maps[MAC_RCR_AAP] = RCR_AAP, .maps[MAC_RCR_AAP] = RCR_AAP,
.maps[MAC_HIMR] = INTA_MASK,
.maps[MAC_HIMRE] = INTA_MASK + 4,
.maps[EFUSE_TEST] = REG_EFUSE_TEST, .maps[EFUSE_TEST] = REG_EFUSE_TEST,
.maps[EFUSE_CTRL] = REG_EFUSE_CTRL, .maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
......
...@@ -640,6 +640,9 @@ u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name) ...@@ -640,6 +640,9 @@ u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name)
case HW_DESC_RXPKT_LEN: case HW_DESC_RXPKT_LEN:
ret = GET_RX_STATUS_DESC_PKT_LEN(desc); ret = GET_RX_STATUS_DESC_PKT_LEN(desc);
break; break;
case HW_DESC_RXBUFF_ADDR:
ret = GET_RX_STATUS_DESC_BUFF_ADDR(desc);
break;
default: default:
RT_ASSERT(false, "ERR rxdesc :%d not process\n", RT_ASSERT(false, "ERR rxdesc :%d not process\n",
desc_name); desc_name);
......
...@@ -1889,15 +1889,18 @@ static void _rtl8821ae_store_tx_power_by_rate(struct ieee80211_hw *hw, ...@@ -1889,15 +1889,18 @@ static void _rtl8821ae_store_tx_power_by_rate(struct ieee80211_hw *hw,
struct rtl_phy *rtlphy = &rtlpriv->phy; struct rtl_phy *rtlphy = &rtlpriv->phy;
u8 rate_section = _rtl8821ae_get_rate_section_index(regaddr); u8 rate_section = _rtl8821ae_get_rate_section_index(regaddr);
if (band != BAND_ON_2_4G && band != BAND_ON_5G) if (band != BAND_ON_2_4G && band != BAND_ON_5G) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n", band); RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n", band);
band = BAND_ON_2_4G;
if (rfpath >= MAX_RF_PATH) }
if (rfpath >= MAX_RF_PATH) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n", rfpath); RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n", rfpath);
rfpath = MAX_RF_PATH - 1;
if (txnum >= MAX_RF_PATH) }
if (txnum >= MAX_RF_PATH) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n", txnum); RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n", txnum);
txnum = MAX_RF_PATH - 1;
}
rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = data; rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][RateSection %d] = 0x%x\n", "TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][RateSection %d] = 0x%x\n",
......
...@@ -1117,7 +1117,18 @@ int rtl_usb_probe(struct usb_interface *intf, ...@@ -1117,7 +1117,18 @@ int rtl_usb_probe(struct usb_interface *intf,
} }
rtlpriv->cfg->ops->init_sw_leds(hw); rtlpriv->cfg->ops->init_sw_leds(hw);
err = ieee80211_register_hw(hw);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Can't register mac80211 hw.\n");
err = -ENODEV;
goto error_out;
}
rtlpriv->mac80211.mac80211_registered = 1;
set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
return 0; return 0;
error_out: error_out:
rtl_deinit_core(hw); rtl_deinit_core(hw);
_rtl_usb_io_handler_release(hw); _rtl_usb_io_handler_release(hw);
......
...@@ -53,6 +53,9 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, ...@@ -53,6 +53,9 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
__aligned(__alignof__(struct aead_request)); __aligned(__alignof__(struct aead_request));
struct aead_request *aead_req = (void *) aead_req_data; struct aead_request *aead_req = (void *) aead_req_data;
if (data_len == 0)
return -EINVAL;
memset(aead_req, 0, sizeof(aead_req_data)); memset(aead_req, 0, sizeof(aead_req_data));
sg_init_one(&pt, data, data_len); sg_init_one(&pt, data, data_len);
......
...@@ -805,7 +805,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, ...@@ -805,7 +805,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
memset(&csa_ie, 0, sizeof(csa_ie)); memset(&csa_ie, 0, sizeof(csa_ie));
err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, err = ieee80211_parse_ch_switch_ie(sdata, elems,
ifibss->chandef.chan->band, ifibss->chandef.chan->band,
sta_flags, ifibss->bssid, &csa_ie); sta_flags, ifibss->bssid, &csa_ie);
/* can't switch to destination channel, fail */ /* can't switch to destination channel, fail */
......
...@@ -1705,7 +1705,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, ...@@ -1705,7 +1705,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
* ieee80211_parse_ch_switch_ie - parses channel switch IEs * ieee80211_parse_ch_switch_ie - parses channel switch IEs
* @sdata: the sdata of the interface which has received the frame * @sdata: the sdata of the interface which has received the frame
* @elems: parsed 802.11 elements received with the frame * @elems: parsed 802.11 elements received with the frame
* @beacon: indicates if the frame was a beacon or probe response
* @current_band: indicates the current band * @current_band: indicates the current band
* @sta_flags: contains information about own capabilities and restrictions * @sta_flags: contains information about own capabilities and restrictions
* to decide which channel switch announcements can be accepted. Only the * to decide which channel switch announcements can be accepted. Only the
...@@ -1719,7 +1718,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, ...@@ -1719,7 +1718,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
* Return: 0 on success, <0 on error and >0 if there is nothing to parse. * Return: 0 on success, <0 on error and >0 if there is nothing to parse.
*/ */
int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems, bool beacon, struct ieee802_11_elems *elems,
enum ieee80211_band current_band, enum ieee80211_band current_band,
u32 sta_flags, u8 *bssid, u32 sta_flags, u8 *bssid,
struct ieee80211_csa_ie *csa_ie); struct ieee80211_csa_ie *csa_ie);
......
...@@ -777,10 +777,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ...@@ -777,10 +777,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
int i, flushed; int i, flushed;
struct ps_data *ps; struct ps_data *ps;
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
bool cancel_scan;
clear_bit(SDATA_STATE_RUNNING, &sdata->state); clear_bit(SDATA_STATE_RUNNING, &sdata->state);
if (rcu_access_pointer(local->scan_sdata) == sdata) cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
if (cancel_scan)
ieee80211_scan_cancel(local); ieee80211_scan_cancel(local);
/* /*
...@@ -911,6 +913,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ...@@ -911,6 +913,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
list_del(&sdata->u.vlan.list); list_del(&sdata->u.vlan.list);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL); RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
/* see comment in the default case below */
ieee80211_free_keys(sdata, true);
/* no need to tell driver */ /* no need to tell driver */
break; break;
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
...@@ -936,17 +940,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ...@@ -936,17 +940,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
/* /*
* When we get here, the interface is marked down. * When we get here, the interface is marked down.
* Free the remaining keys, if there are any * Free the remaining keys, if there are any
* (shouldn't be, except maybe in WDS mode?) * (which can happen in AP mode if userspace sets
* keys before the interface is operating, and maybe
* also in WDS mode)
* *
* Force the key freeing to always synchronize_net() * Force the key freeing to always synchronize_net()
* to wait for the RX path in case it is using this * to wait for the RX path in case it is using this
* interface enqueuing frames * at this very time on * interface enqueuing frames at this very time on
* another CPU. * another CPU.
*/ */
ieee80211_free_keys(sdata, true); ieee80211_free_keys(sdata, true);
/* fall through */
case NL80211_IFTYPE_AP:
skb_queue_purge(&sdata->skb_queue); skb_queue_purge(&sdata->skb_queue);
} }
...@@ -1004,6 +1007,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ...@@ -1004,6 +1007,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_ps(local, -1); ieee80211_recalc_ps(local, -1);
if (cancel_scan)
flush_delayed_work(&local->scan_work);
if (local->open_count == 0) { if (local->open_count == 0) {
ieee80211_stop_device(local); ieee80211_stop_device(local);
......
...@@ -874,7 +874,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, ...@@ -874,7 +874,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
memset(&csa_ie, 0, sizeof(csa_ie)); memset(&csa_ie, 0, sizeof(csa_ie));
err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band, err = ieee80211_parse_ch_switch_ie(sdata, elems, band,
sta_flags, sdata->vif.addr, sta_flags, sdata->vif.addr,
&csa_ie); &csa_ie);
if (err < 0) if (err < 0)
......
...@@ -1117,7 +1117,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, ...@@ -1117,7 +1117,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
current_band = cbss->channel->band; current_band = cbss->channel->band;
memset(&csa_ie, 0, sizeof(csa_ie)); memset(&csa_ie, 0, sizeof(csa_ie));
res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
ifmgd->flags, ifmgd->flags,
ifmgd->associated->bssid, &csa_ie); ifmgd->associated->bssid, &csa_ie);
if (res < 0) if (res < 0)
...@@ -1216,7 +1216,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, ...@@ -1216,7 +1216,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work); ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
else else
mod_timer(&ifmgd->chswitch_timer, mod_timer(&ifmgd->chswitch_timer,
TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval)); TU_TO_EXP_TIME((csa_ie.count - 1) *
cbss->beacon_interval));
} }
static bool static bool
......
...@@ -1685,11 +1685,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) ...@@ -1685,11 +1685,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
sc = le16_to_cpu(hdr->seq_ctrl); sc = le16_to_cpu(hdr->seq_ctrl);
frag = sc & IEEE80211_SCTL_FRAG; frag = sc & IEEE80211_SCTL_FRAG;
if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
is_multicast_ether_addr(hdr->addr1))) { goto out;
/* not fragmented */
if (is_multicast_ether_addr(hdr->addr1)) {
rx->local->dot11MulticastReceivedFrameCount++;
goto out; goto out;
} }
I802_DEBUG_INC(rx->local->rx_handlers_fragments); I802_DEBUG_INC(rx->local->rx_handlers_fragments);
if (skb_linearize(rx->skb)) if (skb_linearize(rx->skb))
...@@ -1782,10 +1785,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) ...@@ -1782,10 +1785,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
out: out:
if (rx->sta) if (rx->sta)
rx->sta->rx_packets++; rx->sta->rx_packets++;
if (is_multicast_ether_addr(hdr->addr1)) ieee80211_led_rx(rx->local);
rx->local->dot11MulticastReceivedFrameCount++;
else
ieee80211_led_rx(rx->local);
return RX_CONTINUE; return RX_CONTINUE;
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include "wme.h" #include "wme.h"
int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems, bool beacon, struct ieee802_11_elems *elems,
enum ieee80211_band current_band, enum ieee80211_band current_band,
u32 sta_flags, u8 *bssid, u32 sta_flags, u8 *bssid,
struct ieee80211_csa_ie *csa_ie) struct ieee80211_csa_ie *csa_ie)
...@@ -91,19 +91,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, ...@@ -91,19 +91,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
return -EINVAL; return -EINVAL;
} }
if (!beacon && sec_chan_offs) { if (sec_chan_offs) {
secondary_channel_offset = sec_chan_offs->sec_chan_offs; secondary_channel_offset = sec_chan_offs->sec_chan_offs;
} else if (beacon && ht_oper) {
secondary_channel_offset =
ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
} else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) { } else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) {
/* If it's not a beacon, HT is enabled and the IE not present, /* If the secondary channel offset IE is not present,
* it's 20 MHz, 802.11-2012 8.5.2.6: * we can't know what's the post-CSA offset, so the
* This element [the Secondary Channel Offset Element] is * best we can do is use 20MHz.
* present when switching to a 40 MHz channel. It may be */
* present when switching to a 20 MHz channel (in which
* case the secondary channel offset is set to SCN).
*/
secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册