Commit df709a18 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:

====================
Please pull this batch of fixes intended for the 3.12 stream!

For the mac80211 bits, Johannes says:

"Jouni fixes a remain-on-channel vs. scan bug, and Felix fixes client TX
probing on VLANs."

And also:

"This time I have two fixes from Emmanuel for RF-kill issues, and fixed
two issues reported by Evan Huus and Thomas Lindroth respectively."

On top of those...

Avinash Patil adds a couple of mwifiex fixes to properly inform cfg80211
about some different types of disconnects, avoiding WARNINGs.

Mark Cave-Ayland corrects a pointer arithmetic problem in rtlwifi,
avoiding incorrect automatic gain calculations.

Solomon Peachy sends a cw1200 fix for locking around calls to
cw1200_irq_handler, addressing "lost interrupt" problems.

Please let me know if there are problems!
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ce97fef4 39c253ed
...@@ -237,7 +237,9 @@ static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id) ...@@ -237,7 +237,9 @@ static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id)
struct hwbus_priv *self = dev_id; struct hwbus_priv *self = dev_id;
if (self->core) { if (self->core) {
cw1200_spi_lock(self);
cw1200_irq_handler(self->core); cw1200_irq_handler(self->core);
cw1200_spi_unlock(self);
return IRQ_HANDLED; return IRQ_HANDLED;
} else { } else {
return IRQ_NONE; return IRQ_NONE;
......
...@@ -1422,13 +1422,19 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) ...@@ -1422,13 +1422,19 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac)
*/ */
int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
{ {
int ret = 0;
if (!priv->media_connected) if (!priv->media_connected)
return 0; return 0;
switch (priv->bss_mode) { switch (priv->bss_mode) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
return mwifiex_deauthenticate_infra(priv, mac); ret = mwifiex_deauthenticate_infra(priv, mac);
if (ret)
cfg80211_disconnected(priv->netdev, 0, NULL, 0,
GFP_KERNEL);
break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
return mwifiex_send_cmd_sync(priv, return mwifiex_send_cmd_sync(priv,
HostCmd_CMD_802_11_AD_HOC_STOP, HostCmd_CMD_802_11_AD_HOC_STOP,
...@@ -1440,7 +1446,7 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) ...@@ -1440,7 +1446,7 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
break; break;
} }
return 0; return ret;
} }
EXPORT_SYMBOL_GPL(mwifiex_deauthenticate); EXPORT_SYMBOL_GPL(mwifiex_deauthenticate);
......
...@@ -118,7 +118,8 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) ...@@ -118,7 +118,8 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
dev_dbg(adapter->dev, dev_dbg(adapter->dev,
"info: successfully disconnected from %pM: reason code %d\n", "info: successfully disconnected from %pM: reason code %d\n",
priv->cfg_bssid, reason_code); priv->cfg_bssid, reason_code);
if (priv->bss_mode == NL80211_IFTYPE_STATION) { if (priv->bss_mode == NL80211_IFTYPE_STATION ||
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); GFP_KERNEL);
} }
......
...@@ -343,7 +343,8 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, ...@@ -343,7 +343,8 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
(bool)GET_RX_DESC_PAGGR(pdesc)); (bool)GET_RX_DESC_PAGGR(pdesc));
rx_status->mactime = GET_RX_DESC_TSFL(pdesc); rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
if (phystatus) { if (phystatus) {
p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE); p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
stats->rx_bufshift);
rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc, rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc,
p_drvinfo); p_drvinfo);
} }
......
...@@ -3518,7 +3518,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, ...@@ -3518,7 +3518,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
return -EINVAL; return -EINVAL;
} }
band = chanctx_conf->def.chan->band; band = chanctx_conf->def.chan->band;
sta = sta_info_get(sdata, peer); sta = sta_info_get_bss(sdata, peer);
if (sta) { if (sta) {
qos = test_sta_flag(sta, WLAN_STA_WME); qos = test_sta_flag(sta, WLAN_STA_WME);
} else { } else {
......
...@@ -893,6 +893,8 @@ struct tpt_led_trigger { ...@@ -893,6 +893,8 @@ struct tpt_led_trigger {
* that the scan completed. * that the scan completed.
* @SCAN_ABORTED: Set for our scan work function when the driver reported * @SCAN_ABORTED: Set for our scan work function when the driver reported
* a scan complete for an aborted scan. * a scan complete for an aborted scan.
* @SCAN_HW_CANCELLED: Set for our scan work function when the scan is being
* cancelled.
*/ */
enum { enum {
SCAN_SW_SCANNING, SCAN_SW_SCANNING,
...@@ -900,6 +902,7 @@ enum { ...@@ -900,6 +902,7 @@ enum {
SCAN_ONCHANNEL_SCANNING, SCAN_ONCHANNEL_SCANNING,
SCAN_COMPLETED, SCAN_COMPLETED,
SCAN_ABORTED, SCAN_ABORTED,
SCAN_HW_CANCELLED,
}; };
/** /**
......
...@@ -394,6 +394,8 @@ void ieee80211_sw_roc_work(struct work_struct *work) ...@@ -394,6 +394,8 @@ void ieee80211_sw_roc_work(struct work_struct *work)
if (started) if (started)
ieee80211_start_next_roc(local); ieee80211_start_next_roc(local);
else if (list_empty(&local->roc_list))
ieee80211_run_deferred_scan(local);
} }
out_unlock: out_unlock:
......
...@@ -238,6 +238,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) ...@@ -238,6 +238,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
enum ieee80211_band band; enum ieee80211_band band;
int i, ielen, n_chans; int i, ielen, n_chans;
if (test_bit(SCAN_HW_CANCELLED, &local->scanning))
return false;
do { do {
if (local->hw_scan_band == IEEE80211_NUM_BANDS) if (local->hw_scan_band == IEEE80211_NUM_BANDS)
return false; return false;
...@@ -940,7 +943,23 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) ...@@ -940,7 +943,23 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
if (!local->scan_req) if (!local->scan_req)
goto out; goto out;
/*
* We have a scan running and the driver already reported completion,
* but the worker hasn't run yet or is stuck on the mutex - mark it as
* cancelled.
*/
if (test_bit(SCAN_HW_SCANNING, &local->scanning) &&
test_bit(SCAN_COMPLETED, &local->scanning)) {
set_bit(SCAN_HW_CANCELLED, &local->scanning);
goto out;
}
if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
/*
* Make sure that __ieee80211_scan_completed doesn't trigger a
* scan on another band.
*/
set_bit(SCAN_HW_CANCELLED, &local->scanning);
if (local->ops->cancel_hw_scan) if (local->ops->cancel_hw_scan)
drv_cancel_hw_scan(local, drv_cancel_hw_scan(local,
rcu_dereference_protected(local->scan_sdata, rcu_dereference_protected(local->scan_sdata,
......
...@@ -180,6 +180,9 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) ...@@ -180,6 +180,9 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
struct ieee80211_local *local = sta->local; struct ieee80211_local *local = sta->local;
struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_sub_if_data *sdata = sta->sdata;
if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
sta->last_rx = jiffies;
if (ieee80211_is_data_qos(mgmt->frame_control)) { if (ieee80211_is_data_qos(mgmt->frame_control)) {
struct ieee80211_hdr *hdr = (void *) skb->data; struct ieee80211_hdr *hdr = (void *) skb->data;
u8 *qc = ieee80211_get_qos_ctl(hdr); u8 *qc = ieee80211_get_qos_ctl(hdr);
......
...@@ -1120,7 +1120,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, ...@@ -1120,7 +1120,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
tx->sta = rcu_dereference(sdata->u.vlan.sta); tx->sta = rcu_dereference(sdata->u.vlan.sta);
if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
return TX_DROP; return TX_DROP;
} else if (info->flags & IEEE80211_TX_CTL_INJECTED || } else if (info->flags & (IEEE80211_TX_CTL_INJECTED |
IEEE80211_TX_INTFL_NL80211_FRAME_TX) ||
tx->sdata->control_port_protocol == tx->skb->protocol) { tx->sdata->control_port_protocol == tx->skb->protocol) {
tx->sta = sta_info_get_bss(sdata, hdr->addr1); tx->sta = sta_info_get_bss(sdata, hdr->addr1);
} }
......
...@@ -2238,6 +2238,10 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, ...@@ -2238,6 +2238,10 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
} }
rate = cfg80211_calculate_bitrate(&ri); rate = cfg80211_calculate_bitrate(&ri);
if (WARN_ONCE(!rate,
"Invalid bitrate: flags=0x%x, idx=%d, vht_nss=%d\n",
status->flag, status->rate_idx, status->vht_nss))
return 0;
/* rewind from end of MPDU */ /* rewind from end of MPDU */
if (status->flag & RX_FLAG_MACTIME_END) if (status->flag & RX_FLAG_MACTIME_END)
......
...@@ -958,8 +958,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -958,8 +958,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
case NETDEV_PRE_UP: case NETDEV_PRE_UP:
if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
return notifier_from_errno(-EOPNOTSUPP); return notifier_from_errno(-EOPNOTSUPP);
if (rfkill_blocked(rdev->rfkill))
return notifier_from_errno(-ERFKILL);
ret = cfg80211_can_add_interface(rdev, wdev->iftype); ret = cfg80211_can_add_interface(rdev, wdev->iftype);
if (ret) if (ret)
return notifier_from_errno(ret); return notifier_from_errno(ret);
......
...@@ -411,6 +411,9 @@ static inline int ...@@ -411,6 +411,9 @@ static inline int
cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
enum nl80211_iftype iftype) enum nl80211_iftype iftype)
{ {
if (rfkill_blocked(rdev->rfkill))
return -ERFKILL;
return cfg80211_can_change_interface(rdev, NULL, iftype); return cfg80211_can_change_interface(rdev, NULL, iftype);
} }
......
...@@ -97,6 +97,10 @@ int ieee80211_radiotap_iterator_init( ...@@ -97,6 +97,10 @@ int ieee80211_radiotap_iterator_init(
struct ieee80211_radiotap_header *radiotap_header, struct ieee80211_radiotap_header *radiotap_header,
int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns) int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns)
{ {
/* check the radiotap header can actually be present */
if (max_length < sizeof(struct ieee80211_radiotap_header))
return -EINVAL;
/* Linux only supports version 0 radiotap format */ /* Linux only supports version 0 radiotap format */
if (radiotap_header->it_version) if (radiotap_header->it_version)
return -EINVAL; return -EINVAL;
...@@ -131,7 +135,8 @@ int ieee80211_radiotap_iterator_init( ...@@ -131,7 +135,8 @@ int ieee80211_radiotap_iterator_init(
*/ */
if ((unsigned long)iterator->_arg - if ((unsigned long)iterator->_arg -
(unsigned long)iterator->_rtheader > (unsigned long)iterator->_rtheader +
sizeof(uint32_t) >
(unsigned long)iterator->_max_length) (unsigned long)iterator->_max_length)
return -EINVAL; return -EINVAL;
} }
......
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