Commit d8037314 authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-next-for-davem-2015-05-29' of...

Merge tag 'mac80211-next-for-davem-2015-05-29' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says:

====================
As we get closer to the merge window, here are a few
more things for -next:
 * disconnect TDLS stations on CSA to avoid issues
 * fix a memory leak introduced in a recent commit
 * switch rfkill and cfg80211 to PM ops
 * in an unlikely scenario, prevent a bookkeeping
   value to get corrupted leading to dropped packets
 * fix a crash in VLAN assignment
 * switch rfkill-gpio to more modern gpiod API
 * send disconnected event to userspace with proper
   local/remote indication
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a9ab2184 f7959e9c
...@@ -889,7 +889,7 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, ...@@ -889,7 +889,7 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
GFP_KERNEL); GFP_KERNEL);
} else if (vif->sme_state == SME_CONNECTED) { } else if (vif->sme_state == SME_CONNECTED) {
cfg80211_disconnected(vif->ndev, proto_reason, cfg80211_disconnected(vif->ndev, proto_reason,
NULL, 0, GFP_KERNEL); NULL, 0, false, GFP_KERNEL);
} }
vif->sme_state = SME_DISCONNECTED; vif->sme_state = SME_DISCONNECTED;
...@@ -3467,7 +3467,7 @@ void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) ...@@ -3467,7 +3467,7 @@ void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
GFP_KERNEL); GFP_KERNEL);
break; break;
case SME_CONNECTED: case SME_CONNECTED:
cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL); cfg80211_disconnected(vif->ndev, 0, NULL, 0, true, GFP_KERNEL);
break; break;
} }
......
...@@ -224,7 +224,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, ...@@ -224,7 +224,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
if (test_bit(wil_status_fwconnected, wil->status)) { if (test_bit(wil_status_fwconnected, wil->status)) {
clear_bit(wil_status_fwconnected, wil->status); clear_bit(wil_status_fwconnected, wil->status);
cfg80211_disconnected(ndev, reason_code, cfg80211_disconnected(ndev, reason_code,
NULL, 0, GFP_KERNEL); NULL, 0, false, GFP_KERNEL);
} else if (test_bit(wil_status_fwconnecting, wil->status)) { } else if (test_bit(wil_status_fwconnecting, wil->status)) {
cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE, WLAN_STATUS_UNSPECIFIED_FAILURE,
......
...@@ -1296,7 +1296,7 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason) ...@@ -1296,7 +1296,7 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
} }
clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0, cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0,
GFP_KERNEL); true, GFP_KERNEL);
} }
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
...@@ -1962,7 +1962,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, ...@@ -1962,7 +1962,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state); clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
cfg80211_disconnected(ndev, reason_code, NULL, 0, GFP_KERNEL); cfg80211_disconnected(ndev, reason_code, NULL, 0, true, GFP_KERNEL);
memcpy(&scbval.ea, &profile->bssid, ETH_ALEN); memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);
scbval.val = cpu_to_le32(reason_code); scbval.val = cpu_to_le32(reason_code);
......
...@@ -835,14 +835,13 @@ static int lbs_cfg_scan(struct wiphy *wiphy, ...@@ -835,14 +835,13 @@ static int lbs_cfg_scan(struct wiphy *wiphy,
* Events * Events
*/ */
void lbs_send_disconnect_notification(struct lbs_private *priv) void lbs_send_disconnect_notification(struct lbs_private *priv,
bool locally_generated)
{ {
lbs_deb_enter(LBS_DEB_CFG80211); lbs_deb_enter(LBS_DEB_CFG80211);
cfg80211_disconnected(priv->dev, cfg80211_disconnected(priv->dev, 0, NULL, 0, locally_generated,
0, GFP_KERNEL);
NULL, 0,
GFP_KERNEL);
lbs_deb_leave(LBS_DEB_CFG80211); lbs_deb_leave(LBS_DEB_CFG80211);
} }
...@@ -1458,7 +1457,7 @@ int lbs_disconnect(struct lbs_private *priv, u16 reason) ...@@ -1458,7 +1457,7 @@ int lbs_disconnect(struct lbs_private *priv, u16 reason)
cfg80211_disconnected(priv->dev, cfg80211_disconnected(priv->dev,
reason, reason,
NULL, 0, NULL, 0, true,
GFP_KERNEL); GFP_KERNEL);
priv->connect_status = LBS_DISCONNECTED; priv->connect_status = LBS_DISCONNECTED;
...@@ -2031,7 +2030,7 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev) ...@@ -2031,7 +2030,7 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd); ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
/* TODO: consider doing this at MACREG_INT_CODE_ADHOC_BCN_LOST time */ /* TODO: consider doing this at MACREG_INT_CODE_ADHOC_BCN_LOST time */
lbs_mac_event_disconnected(priv); lbs_mac_event_disconnected(priv, true);
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret; return ret;
......
...@@ -10,7 +10,8 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev); ...@@ -10,7 +10,8 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev);
int lbs_cfg_register(struct lbs_private *priv); int lbs_cfg_register(struct lbs_private *priv);
void lbs_cfg_free(struct lbs_private *priv); void lbs_cfg_free(struct lbs_private *priv);
void lbs_send_disconnect_notification(struct lbs_private *priv); void lbs_send_disconnect_notification(struct lbs_private *priv,
bool locally_generated);
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
void lbs_scan_done(struct lbs_private *priv); void lbs_scan_done(struct lbs_private *priv);
......
...@@ -68,7 +68,8 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); ...@@ -68,7 +68,8 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
/* From cmdresp.c */ /* From cmdresp.c */
void lbs_mac_event_disconnected(struct lbs_private *priv); void lbs_mac_event_disconnected(struct lbs_private *priv,
bool locally_generated);
......
...@@ -19,10 +19,13 @@ ...@@ -19,10 +19,13 @@
* reset link state etc. * reset link state etc.
* *
* @priv: A pointer to struct lbs_private structure * @priv: A pointer to struct lbs_private structure
* @locally_generated: indicates disconnect was requested locally
* (usually by userspace)
* *
* returns: n/a * returns: n/a
*/ */
void lbs_mac_event_disconnected(struct lbs_private *priv) void lbs_mac_event_disconnected(struct lbs_private *priv,
bool locally_generated)
{ {
if (priv->connect_status != LBS_CONNECTED) if (priv->connect_status != LBS_CONNECTED)
return; return;
...@@ -36,7 +39,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv) ...@@ -36,7 +39,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
msleep_interruptible(1000); msleep_interruptible(1000);
if (priv->wdev->iftype == NL80211_IFTYPE_STATION) if (priv->wdev->iftype == NL80211_IFTYPE_STATION)
lbs_send_disconnect_notification(priv); lbs_send_disconnect_notification(priv, locally_generated);
/* report disconnect to upper layer */ /* report disconnect to upper layer */
netif_stop_queue(priv->dev); netif_stop_queue(priv->dev);
...@@ -229,17 +232,17 @@ int lbs_process_event(struct lbs_private *priv, u32 event) ...@@ -229,17 +232,17 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
case MACREG_INT_CODE_DEAUTHENTICATED: case MACREG_INT_CODE_DEAUTHENTICATED:
lbs_deb_cmd("EVENT: deauthenticated\n"); lbs_deb_cmd("EVENT: deauthenticated\n");
lbs_mac_event_disconnected(priv); lbs_mac_event_disconnected(priv, false);
break; break;
case MACREG_INT_CODE_DISASSOCIATED: case MACREG_INT_CODE_DISASSOCIATED:
lbs_deb_cmd("EVENT: disassociated\n"); lbs_deb_cmd("EVENT: disassociated\n");
lbs_mac_event_disconnected(priv); lbs_mac_event_disconnected(priv, false);
break; break;
case MACREG_INT_CODE_LINK_LOST_NO_SCAN: case MACREG_INT_CODE_LINK_LOST_NO_SCAN:
lbs_deb_cmd("EVENT: link lost\n"); lbs_deb_cmd("EVENT: link lost\n");
lbs_mac_event_disconnected(priv); lbs_mac_event_disconnected(priv, true);
break; break;
case MACREG_INT_CODE_PS_SLEEP: case MACREG_INT_CODE_PS_SLEEP:
......
...@@ -1431,7 +1431,7 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) ...@@ -1431,7 +1431,7 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
ret = mwifiex_deauthenticate_infra(priv, mac); ret = mwifiex_deauthenticate_infra(priv, mac);
if (ret) if (ret)
cfg80211_disconnected(priv->netdev, 0, NULL, 0, cfg80211_disconnected(priv->netdev, 0, NULL, 0,
GFP_KERNEL); true, GFP_KERNEL);
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP, return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP,
......
...@@ -133,7 +133,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) ...@@ -133,7 +133,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
if (priv->bss_mode == NL80211_IFTYPE_STATION || if (priv->bss_mode == NL80211_IFTYPE_STATION ||
priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) { priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
cfg80211_disconnected(priv->netdev, reason_code, NULL, 0, cfg80211_disconnected(priv->netdev, reason_code, NULL, 0,
GFP_KERNEL); false, GFP_KERNEL);
} }
eth_zero_addr(priv->cfg_bssid); eth_zero_addr(priv->cfg_bssid);
......
...@@ -2861,7 +2861,7 @@ static void rndis_wlan_do_link_down_work(struct usbnet *usbdev) ...@@ -2861,7 +2861,7 @@ static void rndis_wlan_do_link_down_work(struct usbnet *usbdev)
deauthenticate(usbdev); deauthenticate(usbdev);
cfg80211_disconnected(usbdev->net, 0, NULL, 0, GFP_KERNEL); cfg80211_disconnected(usbdev->net, 0, NULL, 0, true, GFP_KERNEL);
} }
netif_carrier_off(usbdev->net); netif_carrier_off(usbdev->net);
......
...@@ -379,7 +379,7 @@ void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter) ...@@ -379,7 +379,7 @@ void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter)
GFP_ATOMIC); GFP_ATOMIC);
} else { } else {
cfg80211_disconnected(padapter->pnetdev, 0, NULL, cfg80211_disconnected(padapter->pnetdev, 0, NULL,
0, GFP_ATOMIC); 0, false, GFP_ATOMIC);
} }
} }
} }
......
...@@ -722,7 +722,7 @@ void prism2_connect_result(wlandevice_t *wlandev, u8 failed) ...@@ -722,7 +722,7 @@ void prism2_connect_result(wlandevice_t *wlandev, u8 failed)
void prism2_disconnected(wlandevice_t *wlandev) void prism2_disconnected(wlandevice_t *wlandev)
{ {
cfg80211_disconnected(wlandev->netdev, 0, NULL, cfg80211_disconnected(wlandev->netdev, 0, NULL,
0, GFP_KERNEL); 0, false, GFP_KERNEL);
} }
void prism2_roamed(wlandevice_t *wlandev) void prism2_roamed(wlandevice_t *wlandev)
......
...@@ -4575,13 +4575,15 @@ void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss, ...@@ -4575,13 +4575,15 @@ void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss,
* @ie: information elements of the deauth/disassoc frame (may be %NULL) * @ie: information elements of the deauth/disassoc frame (may be %NULL)
* @ie_len: length of IEs * @ie_len: length of IEs
* @reason: reason code for the disconnection, set it to 0 if unknown * @reason: reason code for the disconnection, set it to 0 if unknown
* @locally_generated: disconnection was requested locally
* @gfp: allocation flags * @gfp: allocation flags
* *
* After it calls this function, the driver should enter an idle state * After it calls this function, the driver should enter an idle state
* and not try to connect to any AP any more. * and not try to connect to any AP any more.
*/ */
void cfg80211_disconnected(struct net_device *dev, u16 reason, void cfg80211_disconnected(struct net_device *dev, u16 reason,
const u8 *ie, size_t ie_len, gfp_t gfp); const u8 *ie, size_t ie_len,
bool locally_generated, gfp_t gfp);
/** /**
* cfg80211_ready_on_channel - notification of remain_on_channel start * cfg80211_ready_on_channel - notification of remain_on_channel start
......
...@@ -1728,8 +1728,7 @@ struct ieee80211_tx_control { ...@@ -1728,8 +1728,7 @@ struct ieee80211_tx_control {
* @sta: station table entry, %NULL for per-vif queue * @sta: station table entry, %NULL for per-vif queue
* @tid: the TID for this queue (unused for per-vif queue) * @tid: the TID for this queue (unused for per-vif queue)
* @ac: the AC for this queue * @ac: the AC for this queue
* @drv_priv: data area for driver use, will always be aligned to * @drv_priv: driver private area, sized by hw->txq_data_size
* sizeof(void *).
* *
* The driver can obtain packets from this queue by calling * The driver can obtain packets from this queue by calling
* ieee80211_tx_dequeue(). * ieee80211_tx_dequeue().
......
...@@ -1411,6 +1411,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, ...@@ -1411,6 +1411,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
} }
sta->sdata = vlansdata; sta->sdata = vlansdata;
ieee80211_check_fast_xmit(sta);
if (sta->sta_state == IEEE80211_STA_AUTHORIZED && if (sta->sta_state == IEEE80211_STA_AUTHORIZED &&
prev_4addr != new_4addr) { prev_4addr != new_4addr) {
......
...@@ -246,6 +246,7 @@ static void ieee80211_restart_work(struct work_struct *work) ...@@ -246,6 +246,7 @@ static void ieee80211_restart_work(struct work_struct *work)
{ {
struct ieee80211_local *local = struct ieee80211_local *local =
container_of(work, struct ieee80211_local, restart_work); container_of(work, struct ieee80211_local, restart_work);
struct ieee80211_sub_if_data *sdata;
/* wait for scan work complete */ /* wait for scan work complete */
flush_workqueue(local->workqueue); flush_workqueue(local->workqueue);
...@@ -254,6 +255,8 @@ static void ieee80211_restart_work(struct work_struct *work) ...@@ -254,6 +255,8 @@ static void ieee80211_restart_work(struct work_struct *work)
"%s called with hardware scan in progress\n", __func__); "%s called with hardware scan in progress\n", __func__);
rtnl_lock(); rtnl_lock();
list_for_each_entry(sdata, &local->interfaces, list)
flush_delayed_work(&sdata->dec_tailroom_needed_wk);
ieee80211_scan_cancel(local); ieee80211_scan_cancel(local);
ieee80211_reconfig(local); ieee80211_reconfig(local);
rtnl_unlock(); rtnl_unlock();
...@@ -770,8 +773,10 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) ...@@ -770,8 +773,10 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
for (r = 0; r < local->hw.n_cipher_schemes; r++) { for (r = 0; r < local->hw.n_cipher_schemes; r++) {
suites[w++] = cs[r].cipher; suites[w++] = cs[r].cipher;
if (WARN_ON(cs[r].pn_len > IEEE80211_MAX_PN_LEN)) if (WARN_ON(cs[r].pn_len > IEEE80211_MAX_PN_LEN)) {
kfree(suites);
return -EINVAL; return -EINVAL;
}
} }
} }
......
...@@ -1098,6 +1098,24 @@ static void ieee80211_chswitch_timer(unsigned long data) ...@@ -1098,6 +1098,24 @@ static void ieee80211_chswitch_timer(unsigned long data)
ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work); ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
} }
static void ieee80211_teardown_tdls_peers(struct ieee80211_sub_if_data *sdata)
{
struct sta_info *sta;
u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
rcu_read_lock();
list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
if (!sta->sta.tdls || sta->sdata != sdata || !sta->uploaded ||
!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
continue;
ieee80211_tdls_oper_request(&sdata->vif, sta->sta.addr,
NL80211_TDLS_TEARDOWN, reason,
GFP_ATOMIC);
}
rcu_read_unlock();
}
static void static void
ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
u64 timestamp, u32 device_timestamp, u64 timestamp, u32 device_timestamp,
...@@ -1161,6 +1179,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, ...@@ -1161,6 +1179,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
return; return;
} }
/*
* Drop all TDLS peers - either we disconnect or move to a different
* channel from this point on. There's no telling what our peer will do.
* The TDLS WIDER_BW scenario is also problematic, as peers might now
* have an incompatible wider chandef.
*/
ieee80211_teardown_tdls_peers(sdata);
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
mutex_lock(&local->chanctx_mtx); mutex_lock(&local->chanctx_mtx);
conf = rcu_dereference_protected(sdata->vif.chanctx_conf, conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
......
...@@ -1183,6 +1183,12 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, ...@@ -1183,6 +1183,12 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
switch (oper) { switch (oper) {
case NL80211_TDLS_ENABLE_LINK: case NL80211_TDLS_ENABLE_LINK:
if (sdata->vif.csa_active) {
tdls_dbg(sdata, "TDLS: disallow link during CSA\n");
ret = -EBUSY;
break;
}
rcu_read_lock(); rcu_read_lock();
sta = sta_info_get(sdata, peer); sta = sta_info_get(sdata, peer);
if (!sta) { if (!sta) {
......
...@@ -794,7 +794,8 @@ void rfkill_resume_polling(struct rfkill *rfkill) ...@@ -794,7 +794,8 @@ void rfkill_resume_polling(struct rfkill *rfkill)
} }
EXPORT_SYMBOL(rfkill_resume_polling); EXPORT_SYMBOL(rfkill_resume_polling);
static int rfkill_suspend(struct device *dev, pm_message_t state) #ifdef CONFIG_PM_SLEEP
static int rfkill_suspend(struct device *dev)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
...@@ -818,13 +819,18 @@ static int rfkill_resume(struct device *dev) ...@@ -818,13 +819,18 @@ static int rfkill_resume(struct device *dev)
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(rfkill_pm_ops, rfkill_suspend, rfkill_resume);
#define RFKILL_PM_OPS (&rfkill_pm_ops)
#else
#define RFKILL_PM_OPS NULL
#endif
static struct class rfkill_class = { static struct class rfkill_class = {
.name = "rfkill", .name = "rfkill",
.dev_release = rfkill_release, .dev_release = rfkill_release,
.dev_groups = rfkill_dev_groups, .dev_groups = rfkill_dev_groups,
.dev_uevent = rfkill_dev_uevent, .dev_uevent = rfkill_dev_uevent,
.suspend = rfkill_suspend, .pm = RFKILL_PM_OPS,
.resume = rfkill_resume,
}; };
bool rfkill_blocked(struct rfkill *rfkill) bool rfkill_blocked(struct rfkill *rfkill)
......
...@@ -112,21 +112,17 @@ static int rfkill_gpio_probe(struct platform_device *pdev) ...@@ -112,21 +112,17 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
rfkill->clk = devm_clk_get(&pdev->dev, NULL); rfkill->clk = devm_clk_get(&pdev->dev, NULL);
gpio = devm_gpiod_get(&pdev->dev, "reset"); gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
if (!IS_ERR(gpio)) { if (IS_ERR(gpio))
ret = gpiod_direction_output(gpio, 0); return PTR_ERR(gpio);
if (ret)
return ret;
rfkill->reset_gpio = gpio;
}
gpio = devm_gpiod_get(&pdev->dev, "shutdown"); rfkill->reset_gpio = gpio;
if (!IS_ERR(gpio)) {
ret = gpiod_direction_output(gpio, 0); gpio = devm_gpiod_get_optional(&pdev->dev, "shutdown", GPIOD_OUT_LOW);
if (ret) if (IS_ERR(gpio))
return ret; return PTR_ERR(gpio);
rfkill->shutdown_gpio = gpio;
} rfkill->shutdown_gpio = gpio;
/* Make sure at-least one of the GPIO is defined and that /* Make sure at-least one of the GPIO is defined and that
* a name is specified for this instance * a name is specified for this instance
......
...@@ -222,6 +222,7 @@ struct cfg80211_event { ...@@ -222,6 +222,7 @@ struct cfg80211_event {
const u8 *ie; const u8 *ie;
size_t ie_len; size_t ie_len;
u16 reason; u16 reason;
bool locally_generated;
} dc; } dc;
struct { struct {
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
......
...@@ -938,7 +938,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, ...@@ -938,7 +938,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
} }
void cfg80211_disconnected(struct net_device *dev, u16 reason, void cfg80211_disconnected(struct net_device *dev, u16 reason,
const u8 *ie, size_t ie_len, gfp_t gfp) const u8 *ie, size_t ie_len,
bool locally_generated, gfp_t gfp)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
...@@ -954,6 +955,7 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason, ...@@ -954,6 +955,7 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
ev->dc.ie_len = ie_len; ev->dc.ie_len = ie_len;
memcpy((void *)ev->dc.ie, ie, ie_len); memcpy((void *)ev->dc.ie, ie, ie_len);
ev->dc.reason = reason; ev->dc.reason = reason;
ev->dc.locally_generated = locally_generated;
spin_lock_irqsave(&wdev->event_lock, flags); spin_lock_irqsave(&wdev->event_lock, flags);
list_add_tail(&ev->list, &wdev->event_list); list_add_tail(&ev->list, &wdev->event_list);
......
...@@ -86,7 +86,7 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) ...@@ -86,7 +86,7 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) static void cfg80211_leave_all(struct cfg80211_registered_device *rdev)
{ {
struct wireless_dev *wdev; struct wireless_dev *wdev;
...@@ -95,7 +95,7 @@ static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) ...@@ -95,7 +95,7 @@ static void cfg80211_leave_all(struct cfg80211_registered_device *rdev)
cfg80211_leave(rdev, wdev); cfg80211_leave(rdev, wdev);
} }
static int wiphy_suspend(struct device *dev, pm_message_t state) static int wiphy_suspend(struct device *dev)
{ {
struct cfg80211_registered_device *rdev = dev_to_rdev(dev); struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
int ret = 0; int ret = 0;
...@@ -136,6 +136,11 @@ static int wiphy_resume(struct device *dev) ...@@ -136,6 +136,11 @@ static int wiphy_resume(struct device *dev)
return ret; return ret;
} }
static SIMPLE_DEV_PM_OPS(wiphy_pm_ops, wiphy_suspend, wiphy_resume);
#define WIPHY_PM_OPS (&wiphy_pm_ops)
#else
#define WIPHY_PM_OPS NULL
#endif #endif
static const void *wiphy_namespace(struct device *d) static const void *wiphy_namespace(struct device *d)
...@@ -151,10 +156,7 @@ struct class ieee80211_class = { ...@@ -151,10 +156,7 @@ struct class ieee80211_class = {
.dev_release = wiphy_dev_release, .dev_release = wiphy_dev_release,
.dev_groups = ieee80211_groups, .dev_groups = ieee80211_groups,
.dev_uevent = wiphy_uevent, .dev_uevent = wiphy_uevent,
#ifdef CONFIG_PM .pm = WIPHY_PM_OPS,
.suspend = wiphy_suspend,
.resume = wiphy_resume,
#endif
.ns_type = &net_ns_type_operations, .ns_type = &net_ns_type_operations,
.namespace = wiphy_namespace, .namespace = wiphy_namespace,
}; };
......
...@@ -887,7 +887,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) ...@@ -887,7 +887,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
case EVENT_DISCONNECTED: case EVENT_DISCONNECTED:
__cfg80211_disconnected(wdev->netdev, __cfg80211_disconnected(wdev->netdev,
ev->dc.ie, ev->dc.ie_len, ev->dc.ie, ev->dc.ie_len,
ev->dc.reason, true); ev->dc.reason,
!ev->dc.locally_generated);
break; break;
case EVENT_IBSS_JOINED: case EVENT_IBSS_JOINED:
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
...@@ -944,7 +945,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, ...@@ -944,7 +945,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
ntype == NL80211_IFTYPE_P2P_CLIENT)) ntype == NL80211_IFTYPE_P2P_CLIENT))
return -EBUSY; return -EBUSY;
if (ntype != otype && netif_running(dev)) { if (ntype != otype) {
dev->ieee80211_ptr->use_4addr = false; dev->ieee80211_ptr->use_4addr = false;
dev->ieee80211_ptr->mesh_id_up_len = 0; dev->ieee80211_ptr->mesh_id_up_len = 0;
wdev_lock(dev->ieee80211_ptr); wdev_lock(dev->ieee80211_ptr);
......
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