{
u16 auth_alg, auth_transaction, status_code;
+ lockdep_assert_held(&sdata->u.ibss.mtx);
+
if (len < 24 + 6)
return;
u32 bss_change;
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+ lockdep_assert_held(&ifibss->mtx);
+
/* Reset own TSF to allow time synchronization work. */
drv_reset_tsf(local);
memcpy(skb_put(skb, ifibss->ie_len),
ifibss->ie, ifibss->ie_len);
+ if (local->hw.queues >= 4) {
+ pos = skb_put(skb, 9);
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = 7; /* len */
+ *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
+ *pos++ = 0x50;
+ *pos++ = 0xf2;
+ *pos++ = 2; /* WME */
+ *pos++ = 0; /* WME info */
+ *pos++ = 1; /* WME ver */
+ *pos++ = 0; /* U-APSD no in use */
+ }
+
rcu_assign_pointer(ifibss->presp, skb);
sdata->vif.bss_conf.beacon_int = beacon_int;
int i, j;
u16 beacon_int = cbss->beacon_interval;
+ lockdep_assert_held(&sdata->u.ibss.mtx);
+
if (beacon_int < 10)
beacon_int = 10;
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
return;
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC && elems->supp_rates &&
+ if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
memcmp(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) {
- supp_rates = ieee80211_sta_get_rates(local, elems, band);
rcu_read_lock();
-
sta = sta_info_get(sdata, mgmt->sa);
- if (sta) {
- u32 prev_rates;
- prev_rates = sta->sta.supp_rates[band];
- /* make sure mandatory rates are always added */
- sta->sta.supp_rates[band] = supp_rates |
- ieee80211_mandatory_rates(local, band);
+ if (elems->supp_rates) {
+ supp_rates = ieee80211_sta_get_rates(local, elems,
+ band);
+ if (sta) {
+ u32 prev_rates;
+
+ prev_rates = sta->sta.supp_rates[band];
+ /* make sure mandatory rates are always added */
+ sta->sta.supp_rates[band] = supp_rates |
+ ieee80211_mandatory_rates(local, band);
- if (sta->sta.supp_rates[band] != prev_rates) {
+ if (sta->sta.supp_rates[band] != prev_rates) {
#ifdef CONFIG_MAC80211_IBSS_DEBUG
- printk(KERN_DEBUG "%s: updated supp_rates set "
- "for %pM based on beacon/probe_response "
- "(0x%x -> 0x%x)\n",
- sdata->name, sta->sta.addr,
- prev_rates, sta->sta.supp_rates[band]);
+ printk(KERN_DEBUG
+ "%s: updated supp_rates set "
+ "for %pM based on beacon"
+ "/probe_resp (0x%x -> 0x%x)\n",
+ sdata->name, sta->sta.addr,
+ prev_rates,
+ sta->sta.supp_rates[band]);
#endif
- rate_control_rate_init(sta);
- }
- rcu_read_unlock();
- } else {
- rcu_read_unlock();
- ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
- supp_rates, GFP_KERNEL);
+ rate_control_rate_init(sta);
+ }
+ } else
+ sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
+ mgmt->sa, supp_rates,
+ GFP_ATOMIC);
}
+
+ if (sta && elems->wmm_info)
+ set_sta_flags(sta, WLAN_STA_WME);
+
+ rcu_read_unlock();
}
bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
return NULL;
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n",
- wiphy_name(local->hw.wiphy), addr, sdata->name);
+ wiphy_debug(local->hw.wiphy, "Adding new IBSS station %pM (dev=%s)\n",
+ addr, sdata->name);
#endif
sta = sta_info_alloc(sdata, addr, gfp);
int active = 0;
struct sta_info *sta;
+ lockdep_assert_held(&sdata->u.ibss.mtx);
+
rcu_read_lock();
list_for_each_entry_rcu(sta, &local->sta_list, list) {
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+ lockdep_assert_held(&ifibss->mtx);
+
mod_timer(&ifibss->timer,
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
u16 capability;
int i;
+ lockdep_assert_held(&ifibss->mtx);
+
if (ifibss->fixed_bssid) {
memcpy(bssid, ifibss->bssid, ETH_ALEN);
} else {
int active_ibss;
u16 capability;
+ lockdep_assert_held(&ifibss->mtx);
+
active_ibss = ieee80211_sta_active_ibss(sdata);
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
struct ieee80211_mgmt *resp;
u8 *pos, *end;
+ lockdep_assert_held(&ifibss->mtx);
+
if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
len < 24 + 2 || !ifibss->presp)
return;
mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control);
+ mutex_lock(&sdata->u.ibss.mtx);
+
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_PROBE_REQ:
ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len);
ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len);
break;
}
+
+ mutex_unlock(&sdata->u.ibss.mtx);
}
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request))
- return;
+ mutex_lock(&ifibss->mtx);
+
+ /*
+ * Work could be scheduled after scan or similar
+ * when we aren't even joined (or trying) with a
+ * network.
+ */
+ if (!ifibss->ssid_len)
+ goto out;
switch (ifibss->state) {
case IEEE80211_IBSS_MLME_SEARCH:
WARN_ON(1);
break;
}
-}
-static void ieee80211_queue_ibss_work(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- struct ieee80211_local *local = sdata->local;
-
- set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
- ieee80211_queue_work(&local->hw, &sdata->work);
+ out:
+ mutex_unlock(&ifibss->mtx);
}
static void ieee80211_ibss_timer(unsigned long data)
return;
}
- ieee80211_queue_ibss_work(sdata);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
#ifdef CONFIG_PM
setup_timer(&ifibss->timer, ieee80211_ibss_timer,
(unsigned long) sdata);
+ mutex_init(&ifibss->mtx);
}
/* scan finished notification */
continue;
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
continue;
- if (!sdata->u.ibss.ssid_len)
- continue;
sdata->u.ibss.last_scan_completed = jiffies;
- ieee80211_queue_ibss_work(sdata);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
mutex_unlock(&local->iflist_mtx);
}
{
struct sk_buff *skb;
+ skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
+ 36 /* bitrates */ +
+ 34 /* SSID */ +
+ 3 /* DS params */ +
+ 4 /* IBSS params */ +
+ params->ie_len);
+ if (!skb)
+ return -ENOMEM;
+
+ mutex_lock(&sdata->u.ibss.mtx);
+
if (params->bssid) {
memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
sdata->u.ibss.fixed_bssid = true;
sdata->u.ibss.ie_len = params->ie_len;
}
- skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
- 36 /* bitrates */ +
- 34 /* SSID */ +
- 3 /* DS params */ +
- 4 /* IBSS params */ +
- params->ie_len);
- if (!skb)
- return -ENOMEM;
-
sdata->u.ibss.skb = skb;
sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
sdata->u.ibss.ibss_join_req = jiffies;
memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
-
- /*
- * The ssid_len setting below is used to see whether
- * we are active, and we need all other settings
- * before that may get visible.
- */
- mb();
-
sdata->u.ibss.ssid_len = params->ssid_len;
+ mutex_unlock(&sdata->u.ibss.mtx);
+
+ mutex_lock(&sdata->local->mtx);
ieee80211_recalc_idle(sdata->local);
+ mutex_unlock(&sdata->local->mtx);
- set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
return 0;
struct ieee80211_local *local = sdata->local;
struct cfg80211_bss *cbss;
u16 capability;
- int active_ibss = 0;
+ int active_ibss;
+
+ mutex_lock(&sdata->u.ibss.mtx);
active_ibss = ieee80211_sta_active_ibss(sdata);
}
}
- del_timer_sync(&sdata->u.ibss.timer);
- clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
- cancel_work_sync(&sdata->work);
- clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
-
sta_info_flush(sdata->local, sdata);
/* remove beacon */
memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
sdata->u.ibss.ssid_len = 0;
+ del_timer_sync(&sdata->u.ibss.timer);
+
+ mutex_unlock(&sdata->u.ibss.mtx);
+
+ mutex_lock(&local->mtx);
ieee80211_recalc_idle(sdata->local);
+ mutex_unlock(&local->mtx);
return 0;
}