Commit 6a4cd3fd authored by David S. Miller's avatar David S. Miller

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless

John W. Linville says:

====================
A few stragglers hoping for 3.9, somewhat delayed due to my travels...

On the mac80211 bits, Johannes says:

"Sadly, I have another pull request -- the idle handling fix broke LED
handling in some cases."

and:

"Yet one more!

This fixes a fairly important/annoying bug -- when roaming between
multiple APs of the same network, the system could get stuck thinking it
was connected to the old one while it really wasn't."

On top of that...

Arend sends a brcmfmac patch that removes advertising a feature that
isn't actually fully supported, and a brcmsmac patch that rearranges
code to request firmware at IFF_UP to play more nicely with being
built into the kernel.

Felix gives us a minor ath9k_htc fix to support the newly released
open source firmware, and an ath9k_hw initvals fix to improve device
stability.

Rafał Miłecki provides a fix for an ssb regression that caused a
serious performance problem with b43.

Zefir Kurtisi offers an ath9k fix to change some kmalloc flags to
allow the DFS detector to be called in softirq context.

Please let me know if there are problems.  If these don't make 3.9,
I'll just pull them into wireless-next -- just let me know if you
want to do it that way!
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 12fb3dd9 5a22483e
...@@ -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},
......
...@@ -143,14 +143,14 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq) ...@@ -143,14 +143,14 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
u32 sz, i; u32 sz, i;
struct channel_detector *cd; struct channel_detector *cd;
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;
......
...@@ -218,7 +218,7 @@ static bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts) ...@@ -218,7 +218,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;
...@@ -299,7 +299,7 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde, ...@@ -299,7 +299,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;
......
...@@ -5165,7 +5165,8 @@ static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid) ...@@ -5165,7 +5165,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
} }
......
...@@ -4126,10 +4126,6 @@ static const struct ieee80211_iface_limit brcmf_iface_limits[] = { ...@@ -4126,10 +4126,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) |
...@@ -4187,8 +4183,7 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) ...@@ -4187,8 +4183,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;
......
...@@ -274,6 +274,130 @@ static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br) ...@@ -274,6 +274,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)
...@@ -306,6 +430,14 @@ static int brcms_ops_start(struct ieee80211_hw *hw) ...@@ -306,6 +430,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;
...@@ -793,128 +925,6 @@ void brcms_dpc(unsigned long data) ...@@ -793,128 +925,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) {
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;
...@@ -1047,18 +1057,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) ...@@ -1047,18 +1057,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);
......
...@@ -675,3 +675,32 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) ...@@ -675,3 +675,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);
} }
......
...@@ -3964,8 +3964,16 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, ...@@ -3964,8 +3964,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);
...@@ -4025,8 +4033,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ...@@ -4025,8 +4033,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