Commit ec094144 authored by John W. Linville's avatar John W. Linville

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless

Conflicts:
	drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
parents c43933e6 f09a8785
...@@ -519,7 +519,7 @@ static const u32 ar9580_1p0_mac_core[][2] = { ...@@ -519,7 +519,7 @@ static const u32 ar9580_1p0_mac_core[][2] = {
{0x00008258, 0x00000000}, {0x00008258, 0x00000000},
{0x0000825c, 0x40000000}, {0x0000825c, 0x40000000},
{0x00008260, 0x00080922}, {0x00008260, 0x00080922},
{0x00008264, 0x9bc00010}, {0x00008264, 0x9d400010},
{0x00008268, 0xffffffff}, {0x00008268, 0xffffffff},
{0x0000826c, 0x0000ffff}, {0x0000826c, 0x0000ffff},
{0x00008270, 0x00000000}, {0x00008270, 0x00000000},
......
...@@ -145,14 +145,14 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq) ...@@ -145,14 +145,14 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
struct channel_detector *cd; struct channel_detector *cd;
struct ath_common *common = ath9k_hw_common(dpd->ah); struct ath_common *common = ath9k_hw_common(dpd->ah);
cd = kmalloc(sizeof(*cd), GFP_KERNEL); cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
if (cd == NULL) if (cd == NULL)
goto fail; goto fail;
INIT_LIST_HEAD(&cd->head); INIT_LIST_HEAD(&cd->head);
cd->freq = freq; cd->freq = freq;
sz = sizeof(cd->detectors) * dpd->num_radar_types; sz = sizeof(cd->detectors) * dpd->num_radar_types;
cd->detectors = kzalloc(sz, GFP_KERNEL); cd->detectors = kzalloc(sz, GFP_ATOMIC);
if (cd->detectors == NULL) if (cd->detectors == NULL)
goto fail; goto fail;
......
...@@ -196,7 +196,7 @@ static bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts) ...@@ -196,7 +196,7 @@ static bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts)
{ {
struct pulse_elem *p = pool_get_pulse_elem(); struct pulse_elem *p = pool_get_pulse_elem();
if (p == NULL) { if (p == NULL) {
p = kmalloc(sizeof(*p), GFP_KERNEL); p = kmalloc(sizeof(*p), GFP_ATOMIC);
if (p == NULL) { if (p == NULL) {
DFS_POOL_STAT_INC(pulse_alloc_error); DFS_POOL_STAT_INC(pulse_alloc_error);
return false; return false;
...@@ -277,7 +277,7 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde, ...@@ -277,7 +277,7 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde,
ps.deadline_ts = ps.first_ts + ps.dur; ps.deadline_ts = ps.first_ts + ps.dur;
new_ps = pool_get_pseq_elem(); new_ps = pool_get_pseq_elem();
if (new_ps == NULL) { if (new_ps == NULL) {
new_ps = kmalloc(sizeof(*new_ps), GFP_KERNEL); new_ps = kmalloc(sizeof(*new_ps), GFP_ATOMIC);
if (new_ps == NULL) { if (new_ps == NULL) {
DFS_POOL_STAT_INC(pseq_alloc_error); DFS_POOL_STAT_INC(pseq_alloc_error);
return false; return false;
......
...@@ -796,7 +796,7 @@ static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) ...@@ -796,7 +796,7 @@ static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
* required version. * required version.
*/ */
if (priv->fw_version_major != MAJOR_VERSION_REQ || 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", dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
MAJOR_VERSION_REQ, MINOR_VERSION_REQ); MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
return -EINVAL; return -EINVAL;
......
...@@ -5109,7 +5109,8 @@ static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid) ...@@ -5109,7 +5109,8 @@ static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
#endif #endif
#ifdef CONFIG_B43_SSB #ifdef CONFIG_B43_SSB
case B43_BUS_SSB: case B43_BUS_SSB:
/* FIXME */ ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,
avoid);
break; break;
#endif #endif
} }
......
...@@ -4086,10 +4086,6 @@ static const struct ieee80211_iface_limit brcmf_iface_limits[] = { ...@@ -4086,10 +4086,6 @@ static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_AP) BIT(NL80211_IFTYPE_AP)
}, },
{
.max = 1,
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
},
{ {
.max = 1, .max = 1,
.types = BIT(NL80211_IFTYPE_P2P_CLIENT) | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
...@@ -4152,8 +4148,7 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) ...@@ -4152,8 +4148,7 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_GO);
BIT(NL80211_IFTYPE_P2P_DEVICE);
wiphy->iface_combinations = brcmf_iface_combos; wiphy->iface_combinations = brcmf_iface_combos;
wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; 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) ...@@ -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, static void brcms_ops_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control, struct ieee80211_tx_control *control,
struct sk_buff *skb) struct sk_buff *skb)
...@@ -308,6 +432,14 @@ static int brcms_ops_start(struct ieee80211_hw *hw) ...@@ -308,6 +432,14 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
if (!blocked) if (!blocked)
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); 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); spin_lock_bh(&wl->lock);
/* avoid acknowledging frames before a non-monitor device is added */ /* avoid acknowledging frames before a non-monitor device is added */
wl->mute_tx = true; wl->mute_tx = true;
...@@ -856,129 +988,6 @@ void brcms_dpc(unsigned long data) ...@@ -856,129 +988,6 @@ void brcms_dpc(unsigned long data)
wake_up(&wl->tx_flush_wq); 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) static irqreturn_t brcms_isr(int irq, void *dev_id)
{ {
struct brcms_info *wl; struct brcms_info *wl;
...@@ -1120,18 +1129,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) ...@@ -1120,18 +1129,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
spin_lock_init(&wl->lock); spin_lock_init(&wl->lock);
spin_lock_init(&wl->isr_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 */ /* common load-time initialization */
wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err); wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err);
brcms_release_fw(wl);
if (!wl->wlc) { if (!wl->wlc) {
wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
KBUILD_MODNAME, err); KBUILD_MODNAME, err);
......
...@@ -670,3 +670,32 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) ...@@ -670,3 +670,32 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc)
return 0; 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 @@ ...@@ -219,6 +219,7 @@
#define SSB_CHIPCO_PMU_CTL 0x0600 /* PMU control */ #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 0xFFFF0000 /* ILP div mask */
#define SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT 16 #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_NOILPONW 0x00000200 /* No ILP on wait */
#define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ #define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
#define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */ #define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */
...@@ -667,5 +668,6 @@ enum ssb_pmu_ldo_volt_id { ...@@ -667,5 +668,6 @@ enum ssb_pmu_ldo_volt_id {
void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc, void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
enum ssb_pmu_ldo_volt_id id, u32 voltage); enum ssb_pmu_ldo_volt_id id, u32 voltage);
void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on); 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_ */ #endif /* LINUX_SSB_CHIPCO_H_ */
...@@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) ...@@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); 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)) if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
return 0; return 0;
...@@ -87,7 +87,7 @@ u32 ieee80211_idle_off(struct ieee80211_local *local) ...@@ -87,7 +87,7 @@ u32 ieee80211_idle_off(struct ieee80211_local *local)
return IEEE80211_CONF_CHANGE_IDLE; 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) if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
return 0; return 0;
...@@ -98,16 +98,18 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) ...@@ -98,16 +98,18 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local)
return IEEE80211_CONF_CHANGE_IDLE; 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; bool working = false, scanning, active;
unsigned int led_trig_start = 0, led_trig_stop = 0; unsigned int led_trig_start = 0, led_trig_stop = 0;
struct ieee80211_roc_work *roc; struct ieee80211_roc_work *roc;
u32 change;
lockdep_assert_held(&local->mtx); 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) { if (!local->ops->remain_on_channel) {
list_for_each_entry(roc, &local->roc_list, list) { list_for_each_entry(roc, &local->roc_list, list) {
...@@ -132,9 +134,18 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) ...@@ -132,9 +134,18 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
if (working || scanning || active) if (working || scanning || active)
change = ieee80211_idle_off(local); return __ieee80211_idle_off(local);
else return __ieee80211_idle_on(local);
change = 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) if (change)
ieee80211_hw_config(local, change); ieee80211_hw_config(local, change);
} }
......
...@@ -4022,8 +4022,16 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, ...@@ -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 */ /* prep auth_data so we don't go into idle on disassoc */
ifmgd->auth_data = auth_data; ifmgd->auth_data = auth_data;
if (ifmgd->associated) if (ifmgd->associated) {
ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 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); sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
...@@ -4083,8 +4091,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ...@@ -4083,8 +4091,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
mutex_lock(&ifmgd->mtx); mutex_lock(&ifmgd->mtx);
if (ifmgd->associated) if (ifmgd->associated) {
ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 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) { if (ifmgd->auth_data && !ifmgd->auth_data->done) {
err = -EBUSY; err = -EBUSY;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment