Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Conflicts: drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
This commit is contained in:
Коммит
ec094144cd
|
@ -519,7 +519,7 @@ static const u32 ar9580_1p0_mac_core[][2] = {
|
|||
{0x00008258, 0x00000000},
|
||||
{0x0000825c, 0x40000000},
|
||||
{0x00008260, 0x00080922},
|
||||
{0x00008264, 0x9bc00010},
|
||||
{0x00008264, 0x9d400010},
|
||||
{0x00008268, 0xffffffff},
|
||||
{0x0000826c, 0x0000ffff},
|
||||
{0x00008270, 0x00000000},
|
||||
|
|
|
@ -145,14 +145,14 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
|
|||
struct channel_detector *cd;
|
||||
struct ath_common *common = ath9k_hw_common(dpd->ah);
|
||||
|
||||
cd = kmalloc(sizeof(*cd), GFP_KERNEL);
|
||||
cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
|
||||
if (cd == NULL)
|
||||
goto fail;
|
||||
|
||||
INIT_LIST_HEAD(&cd->head);
|
||||
cd->freq = freq;
|
||||
sz = sizeof(cd->detectors) * dpd->num_radar_types;
|
||||
cd->detectors = kzalloc(sz, GFP_KERNEL);
|
||||
cd->detectors = kzalloc(sz, GFP_ATOMIC);
|
||||
if (cd->detectors == NULL)
|
||||
goto fail;
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ static bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts)
|
|||
{
|
||||
struct pulse_elem *p = pool_get_pulse_elem();
|
||||
if (p == NULL) {
|
||||
p = kmalloc(sizeof(*p), GFP_KERNEL);
|
||||
p = kmalloc(sizeof(*p), GFP_ATOMIC);
|
||||
if (p == NULL) {
|
||||
DFS_POOL_STAT_INC(pulse_alloc_error);
|
||||
return false;
|
||||
|
@ -277,7 +277,7 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde,
|
|||
ps.deadline_ts = ps.first_ts + ps.dur;
|
||||
new_ps = pool_get_pseq_elem();
|
||||
if (new_ps == NULL) {
|
||||
new_ps = kmalloc(sizeof(*new_ps), GFP_KERNEL);
|
||||
new_ps = kmalloc(sizeof(*new_ps), GFP_ATOMIC);
|
||||
if (new_ps == NULL) {
|
||||
DFS_POOL_STAT_INC(pseq_alloc_error);
|
||||
return false;
|
||||
|
|
|
@ -796,7 +796,7 @@ static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
|
|||
* required version.
|
||||
*/
|
||||
if (priv->fw_version_major != MAJOR_VERSION_REQ ||
|
||||
priv->fw_version_minor != MINOR_VERSION_REQ) {
|
||||
priv->fw_version_minor < MINOR_VERSION_REQ) {
|
||||
dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
|
||||
MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -5109,7 +5109,8 @@ static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
|
|||
#endif
|
||||
#ifdef CONFIG_B43_SSB
|
||||
case B43_BUS_SSB:
|
||||
/* FIXME */
|
||||
ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,
|
||||
avoid);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -4086,10 +4086,6 @@ static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
|
|||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
|
@ -4152,8 +4148,7 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
|
|||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
BIT(NL80211_IFTYPE_P2P_GO);
|
||||
wiphy->iface_combinations = brcmf_iface_combos;
|
||||
wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
|
||||
wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
|
||||
|
|
|
@ -276,6 +276,130 @@ static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function frees the WL per-device resources.
|
||||
*
|
||||
* This function frees resources owned by the WL device pointed to
|
||||
* by the wl parameter.
|
||||
*
|
||||
* precondition: can both be called locked and unlocked
|
||||
*
|
||||
*/
|
||||
static void brcms_free(struct brcms_info *wl)
|
||||
{
|
||||
struct brcms_timer *t, *next;
|
||||
|
||||
/* free ucode data */
|
||||
if (wl->fw.fw_cnt)
|
||||
brcms_ucode_data_free(&wl->ucode);
|
||||
if (wl->irq)
|
||||
free_irq(wl->irq, wl);
|
||||
|
||||
/* kill dpc */
|
||||
tasklet_kill(&wl->tasklet);
|
||||
|
||||
if (wl->pub) {
|
||||
brcms_debugfs_detach(wl->pub);
|
||||
brcms_c_module_unregister(wl->pub, "linux", wl);
|
||||
}
|
||||
|
||||
/* free common resources */
|
||||
if (wl->wlc) {
|
||||
brcms_c_detach(wl->wlc);
|
||||
wl->wlc = NULL;
|
||||
wl->pub = NULL;
|
||||
}
|
||||
|
||||
/* virtual interface deletion is deferred so we cannot spinwait */
|
||||
|
||||
/* wait for all pending callbacks to complete */
|
||||
while (atomic_read(&wl->callbacks) > 0)
|
||||
schedule();
|
||||
|
||||
/* free timers */
|
||||
for (t = wl->timers; t; t = next) {
|
||||
next = t->next;
|
||||
#ifdef DEBUG
|
||||
kfree(t->name);
|
||||
#endif
|
||||
kfree(t);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* called from both kernel as from this kernel module (error flow on attach)
|
||||
* precondition: perimeter lock is not acquired.
|
||||
*/
|
||||
static void brcms_remove(struct bcma_device *pdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
|
||||
struct brcms_info *wl = hw->priv;
|
||||
|
||||
if (wl->wlc) {
|
||||
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
|
||||
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
|
||||
ieee80211_unregister_hw(hw);
|
||||
}
|
||||
|
||||
brcms_free(wl);
|
||||
|
||||
bcma_set_drvdata(pdev, NULL);
|
||||
ieee80211_free_hw(hw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Precondition: Since this function is called in brcms_pci_probe() context,
|
||||
* no locking is required.
|
||||
*/
|
||||
static void brcms_release_fw(struct brcms_info *wl)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_FW_IMAGES; i++) {
|
||||
release_firmware(wl->fw.fw_bin[i]);
|
||||
release_firmware(wl->fw.fw_hdr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Precondition: Since this function is called in brcms_pci_probe() context,
|
||||
* no locking is required.
|
||||
*/
|
||||
static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
|
||||
{
|
||||
int status;
|
||||
struct device *device = &pdev->dev;
|
||||
char fw_name[100];
|
||||
int i;
|
||||
|
||||
memset(&wl->fw, 0, sizeof(struct brcms_firmware));
|
||||
for (i = 0; i < MAX_FW_IMAGES; i++) {
|
||||
if (brcms_firmwares[i] == NULL)
|
||||
break;
|
||||
sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
|
||||
UCODE_LOADER_API_VER);
|
||||
status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
|
||||
if (status) {
|
||||
wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
|
||||
KBUILD_MODNAME, fw_name);
|
||||
return status;
|
||||
}
|
||||
sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
|
||||
UCODE_LOADER_API_VER);
|
||||
status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
|
||||
if (status) {
|
||||
wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
|
||||
KBUILD_MODNAME, fw_name);
|
||||
return status;
|
||||
}
|
||||
wl->fw.hdr_num_entries[i] =
|
||||
wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
|
||||
}
|
||||
wl->fw.fw_cnt = i;
|
||||
status = brcms_ucode_data_init(wl, &wl->ucode);
|
||||
brcms_release_fw(wl);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void brcms_ops_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_control *control,
|
||||
struct sk_buff *skb)
|
||||
|
@ -308,6 +432,14 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
|
|||
if (!blocked)
|
||||
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
|
||||
|
||||
if (!wl->ucode.bcm43xx_bomminor) {
|
||||
err = brcms_request_fw(wl, wl->wlc->hw->d11core);
|
||||
if (err) {
|
||||
brcms_remove(wl->wlc->hw->d11core);
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_bh(&wl->lock);
|
||||
/* avoid acknowledging frames before a non-monitor device is added */
|
||||
wl->mute_tx = true;
|
||||
|
@ -856,129 +988,6 @@ void brcms_dpc(unsigned long data)
|
|||
wake_up(&wl->tx_flush_wq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Precondition: Since this function is called in brcms_pci_probe() context,
|
||||
* no locking is required.
|
||||
*/
|
||||
static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
|
||||
{
|
||||
int status;
|
||||
struct device *device = &pdev->dev;
|
||||
char fw_name[100];
|
||||
int i;
|
||||
|
||||
memset(&wl->fw, 0, sizeof(struct brcms_firmware));
|
||||
for (i = 0; i < MAX_FW_IMAGES; i++) {
|
||||
if (brcms_firmwares[i] == NULL)
|
||||
break;
|
||||
sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
|
||||
UCODE_LOADER_API_VER);
|
||||
status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
|
||||
if (status) {
|
||||
wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
|
||||
KBUILD_MODNAME, fw_name);
|
||||
return status;
|
||||
}
|
||||
sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
|
||||
UCODE_LOADER_API_VER);
|
||||
status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
|
||||
if (status) {
|
||||
wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
|
||||
KBUILD_MODNAME, fw_name);
|
||||
return status;
|
||||
}
|
||||
wl->fw.hdr_num_entries[i] =
|
||||
wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
|
||||
}
|
||||
wl->fw.fw_cnt = i;
|
||||
return brcms_ucode_data_init(wl, &wl->ucode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Precondition: Since this function is called in brcms_pci_probe() context,
|
||||
* no locking is required.
|
||||
*/
|
||||
static void brcms_release_fw(struct brcms_info *wl)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_FW_IMAGES; i++) {
|
||||
release_firmware(wl->fw.fw_bin[i]);
|
||||
release_firmware(wl->fw.fw_hdr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function frees the WL per-device resources.
|
||||
*
|
||||
* This function frees resources owned by the WL device pointed to
|
||||
* by the wl parameter.
|
||||
*
|
||||
* precondition: can both be called locked and unlocked
|
||||
*
|
||||
*/
|
||||
static void brcms_free(struct brcms_info *wl)
|
||||
{
|
||||
struct brcms_timer *t, *next;
|
||||
|
||||
/* free ucode data */
|
||||
if (wl->fw.fw_cnt)
|
||||
brcms_ucode_data_free(&wl->ucode);
|
||||
if (wl->irq)
|
||||
free_irq(wl->irq, wl);
|
||||
|
||||
/* kill dpc */
|
||||
tasklet_kill(&wl->tasklet);
|
||||
|
||||
if (wl->pub) {
|
||||
brcms_debugfs_detach(wl->pub);
|
||||
brcms_c_module_unregister(wl->pub, "linux", wl);
|
||||
}
|
||||
|
||||
/* free common resources */
|
||||
if (wl->wlc) {
|
||||
brcms_c_detach(wl->wlc);
|
||||
wl->wlc = NULL;
|
||||
wl->pub = NULL;
|
||||
}
|
||||
|
||||
/* virtual interface deletion is deferred so we cannot spinwait */
|
||||
|
||||
/* wait for all pending callbacks to complete */
|
||||
while (atomic_read(&wl->callbacks) > 0)
|
||||
schedule();
|
||||
|
||||
/* free timers */
|
||||
for (t = wl->timers; t; t = next) {
|
||||
next = t->next;
|
||||
#ifdef DEBUG
|
||||
kfree(t->name);
|
||||
#endif
|
||||
kfree(t);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* called from both kernel as from this kernel module (error flow on attach)
|
||||
* precondition: perimeter lock is not acquired.
|
||||
*/
|
||||
static void brcms_remove(struct bcma_device *pdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
|
||||
struct brcms_info *wl = hw->priv;
|
||||
|
||||
if (wl->wlc) {
|
||||
brcms_led_unregister(wl);
|
||||
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
|
||||
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
|
||||
ieee80211_unregister_hw(hw);
|
||||
}
|
||||
|
||||
brcms_free(wl);
|
||||
|
||||
bcma_set_drvdata(pdev, NULL);
|
||||
ieee80211_free_hw(hw);
|
||||
}
|
||||
|
||||
static irqreturn_t brcms_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct brcms_info *wl;
|
||||
|
@ -1120,18 +1129,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
|
|||
spin_lock_init(&wl->lock);
|
||||
spin_lock_init(&wl->isr_lock);
|
||||
|
||||
/* prepare ucode */
|
||||
if (brcms_request_fw(wl, pdev) < 0) {
|
||||
wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
|
||||
"%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
|
||||
brcms_release_fw(wl);
|
||||
brcms_remove(pdev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* common load-time initialization */
|
||||
wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err);
|
||||
brcms_release_fw(wl);
|
||||
if (!wl->wlc) {
|
||||
wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
|
||||
KBUILD_MODNAME, err);
|
||||
|
|
|
@ -670,3 +670,32 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid)
|
||||
{
|
||||
u32 pmu_ctl = 0;
|
||||
|
||||
switch (cc->dev->bus->chip_id) {
|
||||
case 0x4322:
|
||||
ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100070);
|
||||
ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x1014140a);
|
||||
ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888854);
|
||||
if (spuravoid == 1)
|
||||
ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05201828);
|
||||
else
|
||||
ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05001828);
|
||||
pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
|
||||
break;
|
||||
case 43222:
|
||||
/* TODO: BCM43222 requires updating PLLs too */
|
||||
return;
|
||||
default:
|
||||
ssb_printk(KERN_ERR PFX
|
||||
"Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
|
||||
cc->dev->bus->chip_id);
|
||||
return;
|
||||
}
|
||||
|
||||
chipco_set32(cc, SSB_CHIPCO_PMU_CTL, pmu_ctl);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate);
|
||||
|
|
|
@ -219,6 +219,7 @@
|
|||
#define SSB_CHIPCO_PMU_CTL 0x0600 /* PMU control */
|
||||
#define SSB_CHIPCO_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */
|
||||
#define SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT 16
|
||||
#define SSB_CHIPCO_PMU_CTL_PLL_UPD 0x00000400
|
||||
#define SSB_CHIPCO_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */
|
||||
#define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
|
||||
#define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */
|
||||
|
@ -667,5 +668,6 @@ enum ssb_pmu_ldo_volt_id {
|
|||
void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
|
||||
enum ssb_pmu_ldo_volt_id id, u32 voltage);
|
||||
void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on);
|
||||
void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid);
|
||||
|
||||
#endif /* LINUX_SSB_CHIPCO_H_ */
|
||||
|
|
|
@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
|
|||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
|
||||
}
|
||||
|
||||
u32 ieee80211_idle_off(struct ieee80211_local *local)
|
||||
static u32 __ieee80211_idle_off(struct ieee80211_local *local)
|
||||
{
|
||||
if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
|
||||
return 0;
|
||||
|
@ -87,7 +87,7 @@ u32 ieee80211_idle_off(struct ieee80211_local *local)
|
|||
return IEEE80211_CONF_CHANGE_IDLE;
|
||||
}
|
||||
|
||||
static u32 ieee80211_idle_on(struct ieee80211_local *local)
|
||||
static u32 __ieee80211_idle_on(struct ieee80211_local *local)
|
||||
{
|
||||
if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
|
||||
return 0;
|
||||
|
@ -98,16 +98,18 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local)
|
|||
return IEEE80211_CONF_CHANGE_IDLE;
|
||||
}
|
||||
|
||||
void ieee80211_recalc_idle(struct ieee80211_local *local)
|
||||
static u32 __ieee80211_recalc_idle(struct ieee80211_local *local,
|
||||
bool force_active)
|
||||
{
|
||||
bool working = false, scanning, active;
|
||||
unsigned int led_trig_start = 0, led_trig_stop = 0;
|
||||
struct ieee80211_roc_work *roc;
|
||||
u32 change;
|
||||
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
active = !list_empty(&local->chanctx_list) || local->monitors;
|
||||
active = force_active ||
|
||||
!list_empty(&local->chanctx_list) ||
|
||||
local->monitors;
|
||||
|
||||
if (!local->ops->remain_on_channel) {
|
||||
list_for_each_entry(roc, &local->roc_list, list) {
|
||||
|
@ -132,9 +134,18 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
|
|||
ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
|
||||
|
||||
if (working || scanning || active)
|
||||
change = ieee80211_idle_off(local);
|
||||
else
|
||||
change = ieee80211_idle_on(local);
|
||||
return __ieee80211_idle_off(local);
|
||||
return __ieee80211_idle_on(local);
|
||||
}
|
||||
|
||||
u32 ieee80211_idle_off(struct ieee80211_local *local)
|
||||
{
|
||||
return __ieee80211_recalc_idle(local, true);
|
||||
}
|
||||
|
||||
void ieee80211_recalc_idle(struct ieee80211_local *local)
|
||||
{
|
||||
u32 change = __ieee80211_recalc_idle(local, false);
|
||||
if (change)
|
||||
ieee80211_hw_config(local, change);
|
||||
}
|
||||
|
|
|
@ -4022,8 +4022,16 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
|
|||
/* prep auth_data so we don't go into idle on disassoc */
|
||||
ifmgd->auth_data = auth_data;
|
||||
|
||||
if (ifmgd->associated)
|
||||
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
|
||||
if (ifmgd->associated) {
|
||||
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
||||
|
||||
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
|
||||
WLAN_REASON_UNSPECIFIED,
|
||||
false, frame_buf);
|
||||
|
||||
__cfg80211_send_deauth(sdata->dev, frame_buf,
|
||||
sizeof(frame_buf));
|
||||
}
|
||||
|
||||
sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
|
||||
|
||||
|
@ -4083,8 +4091,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
mutex_lock(&ifmgd->mtx);
|
||||
|
||||
if (ifmgd->associated)
|
||||
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
|
||||
if (ifmgd->associated) {
|
||||
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
||||
|
||||
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
|
||||
WLAN_REASON_UNSPECIFIED,
|
||||
false, frame_buf);
|
||||
|
||||
__cfg80211_send_deauth(sdata->dev, frame_buf,
|
||||
sizeof(frame_buf));
|
||||
}
|
||||
|
||||
if (ifmgd->auth_data && !ifmgd->auth_data->done) {
|
||||
err = -EBUSY;
|
||||
|
|
Загрузка…
Ссылка в новой задаче