aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/Makefile1
-rw-r--r--net/mac80211/cfg.c478
-rw-r--r--net/mac80211/ieee80211_i.h89
-rw-r--r--net/mac80211/iface.c23
-rw-r--r--net/mac80211/main.c10
-rw-r--r--net/mac80211/offchannel.c280
-rw-r--r--net/mac80211/scan.c4
-rw-r--r--net/mac80211/status.c28
-rw-r--r--net/mac80211/work.c370
9 files changed, 532 insertions, 751 deletions
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 3e9d931bba35..2b1470bac178 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -9,7 +9,6 @@ mac80211-y := \
9 scan.o offchannel.o \ 9 scan.o offchannel.o \
10 ht.o agg-tx.o agg-rx.o \ 10 ht.o agg-tx.o agg-rx.o \
11 ibss.o \ 11 ibss.o \
12 work.o \
13 iface.o \ 12 iface.o \
14 rate.o \ 13 rate.o \
15 michael.o \ 14 michael.o \
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a16907919709..498c94e34427 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2112,35 +2112,171 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
2112 return 0; 2112 return 0;
2113} 2113}
2114 2114
2115static int ieee80211_remain_on_channel_hw(struct ieee80211_local *local, 2115static int ieee80211_start_roc_work(struct ieee80211_local *local,
2116 struct net_device *dev, 2116 struct ieee80211_sub_if_data *sdata,
2117 struct ieee80211_channel *chan, 2117 struct ieee80211_channel *channel,
2118 enum nl80211_channel_type chantype, 2118 enum nl80211_channel_type channel_type,
2119 unsigned int duration, u64 *cookie) 2119 unsigned int duration, u64 *cookie,
2120{ 2120 struct sk_buff *txskb)
2121{
2122 struct ieee80211_roc_work *roc, *tmp;
2123 bool queued = false;
2121 int ret; 2124 int ret;
2122 u32 random_cookie;
2123 2125
2124 lockdep_assert_held(&local->mtx); 2126 lockdep_assert_held(&local->mtx);
2125 2127
2126 if (local->hw_roc_cookie) 2128 roc = kzalloc(sizeof(*roc), GFP_KERNEL);
2127 return -EBUSY; 2129 if (!roc)
2128 /* must be nonzero */ 2130 return -ENOMEM;
2129 random_cookie = random32() | 1; 2131
2130 2132 roc->chan = channel;
2131 *cookie = random_cookie; 2133 roc->chan_type = channel_type;
2132 local->hw_roc_dev = dev; 2134 roc->duration = duration;
2133 local->hw_roc_cookie = random_cookie; 2135 roc->req_duration = duration;
2134 local->hw_roc_channel = chan; 2136 roc->frame = txskb;
2135 local->hw_roc_channel_type = chantype; 2137 roc->mgmt_tx_cookie = (unsigned long)txskb;
2136 local->hw_roc_duration = duration; 2138 roc->sdata = sdata;
2137 ret = drv_remain_on_channel(local, chan, chantype, duration); 2139 INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
2140 INIT_LIST_HEAD(&roc->dependents);
2141
2142 /* if there's one pending or we're scanning, queue this one */
2143 if (!list_empty(&local->roc_list) || local->scanning)
2144 goto out_check_combine;
2145
2146 /* if not HW assist, just queue & schedule work */
2147 if (!local->ops->remain_on_channel) {
2148 ieee80211_queue_delayed_work(&local->hw, &roc->work, 0);
2149 goto out_queue;
2150 }
2151
2152 /* otherwise actually kick it off here (for error handling) */
2153
2154 /*
2155 * If the duration is zero, then the driver
2156 * wouldn't actually do anything. Set it to
2157 * 10 for now.
2158 *
2159 * TODO: cancel the off-channel operation
2160 * when we get the SKB's TX status and
2161 * the wait time was zero before.
2162 */
2163 if (!duration)
2164 duration = 10;
2165
2166 ret = drv_remain_on_channel(local, channel, channel_type, duration);
2138 if (ret) { 2167 if (ret) {
2139 local->hw_roc_channel = NULL; 2168 kfree(roc);
2140 local->hw_roc_cookie = 0; 2169 return ret;
2141 } 2170 }
2142 2171
2143 return ret; 2172 roc->started = true;
2173 goto out_queue;
2174
2175 out_check_combine:
2176 list_for_each_entry(tmp, &local->roc_list, list) {
2177 if (tmp->chan != channel || tmp->chan_type != channel_type)
2178 continue;
2179
2180 /*
2181 * Extend this ROC if possible:
2182 *
2183 * If it hasn't started yet, just increase the duration
2184 * and add the new one to the list of dependents.
2185 */
2186 if (!tmp->started) {
2187 list_add_tail(&roc->list, &tmp->dependents);
2188 tmp->duration = max(tmp->duration, roc->duration);
2189 queued = true;
2190 break;
2191 }
2192
2193 /* If it has already started, it's more difficult ... */
2194 if (local->ops->remain_on_channel) {
2195 unsigned long j = jiffies;
2196
2197 /*
2198 * In the offloaded ROC case, if it hasn't begun, add
2199 * this new one to the dependent list to be handled
2200 * when the the master one begins. If it has begun,
2201 * check that there's still a minimum time left and
2202 * if so, start this one, transmitting the frame, but
2203 * add it to the list directly after this one with a
2204 * a reduced time so we'll ask the driver to execute
2205 * it right after finishing the previous one, in the
2206 * hope that it'll also be executed right afterwards,
2207 * effectively extending the old one.
2208 * If there's no minimum time left, just add it to the
2209 * normal list.
2210 */
2211 if (!tmp->hw_begun) {
2212 list_add_tail(&roc->list, &tmp->dependents);
2213 queued = true;
2214 break;
2215 }
2216
2217 if (time_before(j + IEEE80211_ROC_MIN_LEFT,
2218 tmp->hw_start_time +
2219 msecs_to_jiffies(tmp->duration))) {
2220 int new_dur;
2221
2222 ieee80211_handle_roc_started(roc);
2223
2224 new_dur = roc->duration -
2225 jiffies_to_msecs(tmp->hw_start_time +
2226 msecs_to_jiffies(
2227 tmp->duration) -
2228 j);
2229
2230 if (new_dur > 0) {
2231 /* add right after tmp */
2232 list_add(&roc->list, &tmp->list);
2233 } else {
2234 list_add_tail(&roc->list,
2235 &tmp->dependents);
2236 }
2237 queued = true;
2238 }
2239 } else if (del_timer_sync(&tmp->work.timer)) {
2240 unsigned long new_end;
2241
2242 /*
2243 * In the software ROC case, cancel the timer, if
2244 * that fails then the finish work is already
2245 * queued/pending and thus we queue the new ROC
2246 * normally, if that succeeds then we can extend
2247 * the timer duration and TX the frame (if any.)
2248 */
2249
2250 list_add_tail(&roc->list, &tmp->dependents);
2251 queued = true;
2252
2253 new_end = jiffies + msecs_to_jiffies(roc->duration);
2254
2255 /* ok, it was started & we canceled timer */
2256 if (time_after(new_end, tmp->work.timer.expires))
2257 mod_timer(&tmp->work.timer, new_end);
2258 else
2259 add_timer(&tmp->work.timer);
2260
2261 ieee80211_handle_roc_started(roc);
2262 }
2263 break;
2264 }
2265
2266 out_queue:
2267 if (!queued)
2268 list_add_tail(&roc->list, &local->roc_list);
2269
2270 /*
2271 * cookie is either the roc (for normal roc)
2272 * or the SKB (for mgmt TX)
2273 */
2274 if (txskb)
2275 *cookie = (unsigned long)txskb;
2276 else
2277 *cookie = (unsigned long)roc;
2278
2279 return 0;
2144} 2280}
2145 2281
2146static int ieee80211_remain_on_channel(struct wiphy *wiphy, 2282static int ieee80211_remain_on_channel(struct wiphy *wiphy,
@@ -2152,84 +2288,76 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy,
2152{ 2288{
2153 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 2289 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2154 struct ieee80211_local *local = sdata->local; 2290 struct ieee80211_local *local = sdata->local;
2291 int ret;
2155 2292
2156 if (local->ops->remain_on_channel) { 2293 mutex_lock(&local->mtx);
2157 int ret; 2294 ret = ieee80211_start_roc_work(local, sdata, chan, channel_type,
2158 2295 duration, cookie, NULL);
2159 mutex_lock(&local->mtx); 2296 mutex_unlock(&local->mtx);
2160 ret = ieee80211_remain_on_channel_hw(local, dev,
2161 chan, channel_type,
2162 duration, cookie);
2163 local->hw_roc_for_tx = false;
2164 mutex_unlock(&local->mtx);
2165
2166 return ret;
2167 }
2168 2297
2169 return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, 2298 return ret;
2170 duration, cookie);
2171} 2299}
2172 2300
2173static int ieee80211_cancel_remain_on_channel_hw(struct ieee80211_local *local, 2301static int ieee80211_cancel_roc(struct ieee80211_local *local,
2174 u64 cookie) 2302 u64 cookie, bool mgmt_tx)
2175{ 2303{
2304 struct ieee80211_roc_work *roc, *tmp, *found = NULL;
2176 int ret; 2305 int ret;
2177 2306
2178 lockdep_assert_held(&local->mtx); 2307 mutex_lock(&local->mtx);
2308 list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
2309 if (!mgmt_tx && (unsigned long)roc != cookie)
2310 continue;
2311 else if (mgmt_tx && roc->mgmt_tx_cookie != cookie)
2312 continue;
2179 2313
2180 if (local->hw_roc_cookie != cookie) 2314 found = roc;
2181 return -ENOENT; 2315 break;
2316 }
2182 2317
2183 ret = drv_cancel_remain_on_channel(local); 2318 if (!found) {
2184 if (ret) 2319 mutex_unlock(&local->mtx);
2185 return ret; 2320 return -ENOENT;
2321 }
2186 2322
2187 local->hw_roc_cookie = 0; 2323 if (local->ops->remain_on_channel) {
2188 local->hw_roc_channel = NULL; 2324 if (found->started) {
2325 ret = drv_cancel_remain_on_channel(local);
2326 if (WARN_ON_ONCE(ret)) {
2327 mutex_unlock(&local->mtx);
2328 return ret;
2329 }
2330 }
2189 2331
2190 return 0; 2332 list_del(&found->list);
2191}
2192 2333
2193static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, 2334 ieee80211_run_deferred_scan(local);
2194 struct net_device *dev, 2335 ieee80211_start_next_roc(local);
2195 u64 cookie) 2336 mutex_unlock(&local->mtx);
2196{
2197 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2198 struct ieee80211_local *local = sdata->local;
2199 2337
2200 if (local->ops->cancel_remain_on_channel) { 2338 ieee80211_roc_notify_destroy(found);
2201 int ret; 2339 } else {
2340 /* work may be pending so use it all the time */
2341 found->abort = true;
2342 ieee80211_queue_delayed_work(&local->hw, &found->work, 0);
2202 2343
2203 mutex_lock(&local->mtx);
2204 ret = ieee80211_cancel_remain_on_channel_hw(local, cookie);
2205 mutex_unlock(&local->mtx); 2344 mutex_unlock(&local->mtx);
2206 2345
2207 return ret; 2346 /* work will clean up etc */
2347 flush_delayed_work(&found->work);
2208 } 2348 }
2209 2349
2210 return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); 2350 return 0;
2211} 2351}
2212 2352
2213static enum work_done_result 2353static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
2214ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) 2354 struct net_device *dev,
2355 u64 cookie)
2215{ 2356{
2216 /* 2357 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2217 * Use the data embedded in the work struct for reporting 2358 struct ieee80211_local *local = sdata->local;
2218 * here so if the driver mangled the SKB before dropping
2219 * it (which is the only way we really should get here)
2220 * then we don't report mangled data.
2221 *
2222 * If there was no wait time, then by the time we get here
2223 * the driver will likely not have reported the status yet,
2224 * so in that case userspace will have to deal with it.
2225 */
2226
2227 if (wk->offchan_tx.wait && !wk->offchan_tx.status)
2228 cfg80211_mgmt_tx_status(wk->sdata->dev,
2229 (unsigned long) wk->offchan_tx.frame,
2230 wk->data, wk->data_len, false, GFP_KERNEL);
2231 2359
2232 return WORK_DONE_DESTROY; 2360 return ieee80211_cancel_roc(local, cookie, false);
2233} 2361}
2234 2362
2235static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, 2363static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
@@ -2243,10 +2371,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2243 struct ieee80211_local *local = sdata->local; 2371 struct ieee80211_local *local = sdata->local;
2244 struct sk_buff *skb; 2372 struct sk_buff *skb;
2245 struct sta_info *sta; 2373 struct sta_info *sta;
2246 struct ieee80211_work *wk;
2247 const struct ieee80211_mgmt *mgmt = (void *)buf; 2374 const struct ieee80211_mgmt *mgmt = (void *)buf;
2375 bool need_offchan = false;
2248 u32 flags; 2376 u32 flags;
2249 bool is_offchan = false, in_hw_roc = false; 2377 int ret;
2250 2378
2251 if (dont_wait_for_ack) 2379 if (dont_wait_for_ack)
2252 flags = IEEE80211_TX_CTL_NO_ACK; 2380 flags = IEEE80211_TX_CTL_NO_ACK;
@@ -2254,34 +2382,28 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2254 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | 2382 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
2255 IEEE80211_TX_CTL_REQ_TX_STATUS; 2383 IEEE80211_TX_CTL_REQ_TX_STATUS;
2256 2384
2257 /* Check that we are on the requested channel for transmission */
2258 if (chan != local->tmp_channel &&
2259 chan != local->oper_channel)
2260 is_offchan = true;
2261 if (channel_type_valid &&
2262 (channel_type != local->tmp_channel_type &&
2263 channel_type != local->_oper_channel_type))
2264 is_offchan = true;
2265
2266 if (chan == local->hw_roc_channel) {
2267 /* TODO: check channel type? */
2268 is_offchan = false;
2269 in_hw_roc = true;
2270 flags |= IEEE80211_TX_CTL_TX_OFFCHAN;
2271 }
2272
2273 if (no_cck) 2385 if (no_cck)
2274 flags |= IEEE80211_TX_CTL_NO_CCK_RATE; 2386 flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
2275 2387
2276 if (is_offchan && !offchan)
2277 return -EBUSY;
2278
2279 switch (sdata->vif.type) { 2388 switch (sdata->vif.type) {
2280 case NL80211_IFTYPE_ADHOC: 2389 case NL80211_IFTYPE_ADHOC:
2390 if (!sdata->vif.bss_conf.ibss_joined)
2391 need_offchan = true;
2392 /* fall through */
2393#ifdef CONFIG_MAC80211_MESH
2394 case NL80211_IFTYPE_MESH_POINT:
2395 if (ieee80211_vif_is_mesh(&sdata->vif) &&
2396 !sdata->u.mesh.mesh_id_len)
2397 need_offchan = true;
2398 /* fall through */
2399#endif
2281 case NL80211_IFTYPE_AP: 2400 case NL80211_IFTYPE_AP:
2282 case NL80211_IFTYPE_AP_VLAN: 2401 case NL80211_IFTYPE_AP_VLAN:
2283 case NL80211_IFTYPE_P2P_GO: 2402 case NL80211_IFTYPE_P2P_GO:
2284 case NL80211_IFTYPE_MESH_POINT: 2403 if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
2404 !ieee80211_vif_is_mesh(&sdata->vif) &&
2405 !rcu_access_pointer(sdata->bss->beacon))
2406 need_offchan = true;
2285 if (!ieee80211_is_action(mgmt->frame_control) || 2407 if (!ieee80211_is_action(mgmt->frame_control) ||
2286 mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) 2408 mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)
2287 break; 2409 break;
@@ -2293,105 +2415,60 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2293 break; 2415 break;
2294 case NL80211_IFTYPE_STATION: 2416 case NL80211_IFTYPE_STATION:
2295 case NL80211_IFTYPE_P2P_CLIENT: 2417 case NL80211_IFTYPE_P2P_CLIENT:
2418 if (!sdata->u.mgd.associated)
2419 need_offchan = true;
2296 break; 2420 break;
2297 default: 2421 default:
2298 return -EOPNOTSUPP; 2422 return -EOPNOTSUPP;
2299 } 2423 }
2300 2424
2425 mutex_lock(&local->mtx);
2426
2427 /* Check if the operating channel is the requested channel */
2428 if (!need_offchan) {
2429 need_offchan = chan != local->oper_channel;
2430 if (channel_type_valid &&
2431 channel_type != local->_oper_channel_type)
2432 need_offchan = true;
2433 }
2434
2435 if (need_offchan && !offchan) {
2436 ret = -EBUSY;
2437 goto out_unlock;
2438 }
2439
2301 skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); 2440 skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
2302 if (!skb) 2441 if (!skb) {
2303 return -ENOMEM; 2442 ret = -ENOMEM;
2443 goto out_unlock;
2444 }
2304 skb_reserve(skb, local->hw.extra_tx_headroom); 2445 skb_reserve(skb, local->hw.extra_tx_headroom);
2305 2446
2306 memcpy(skb_put(skb, len), buf, len); 2447 memcpy(skb_put(skb, len), buf, len);
2307 2448
2308 IEEE80211_SKB_CB(skb)->flags = flags; 2449 IEEE80211_SKB_CB(skb)->flags = flags;
2309 2450
2310 if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL &&
2311 flags & IEEE80211_TX_CTL_TX_OFFCHAN)
2312 IEEE80211_SKB_CB(skb)->hw_queue =
2313 local->hw.offchannel_tx_hw_queue;
2314
2315 skb->dev = sdata->dev; 2451 skb->dev = sdata->dev;
2316 2452
2317 *cookie = (unsigned long) skb; 2453 if (!need_offchan) {
2318
2319 if (is_offchan && local->ops->remain_on_channel) {
2320 unsigned int duration;
2321 int ret;
2322
2323 mutex_lock(&local->mtx);
2324 /*
2325 * If the duration is zero, then the driver
2326 * wouldn't actually do anything. Set it to
2327 * 100 for now.
2328 *
2329 * TODO: cancel the off-channel operation
2330 * when we get the SKB's TX status and
2331 * the wait time was zero before.
2332 */
2333 duration = 100;
2334 if (wait)
2335 duration = wait;
2336 ret = ieee80211_remain_on_channel_hw(local, dev, chan,
2337 channel_type,
2338 duration, cookie);
2339 if (ret) {
2340 kfree_skb(skb);
2341 mutex_unlock(&local->mtx);
2342 return ret;
2343 }
2344
2345 local->hw_roc_for_tx = true;
2346 local->hw_roc_duration = wait;
2347
2348 /*
2349 * queue up frame for transmission after
2350 * ieee80211_ready_on_channel call
2351 */
2352
2353 /* modify cookie to prevent API mismatches */
2354 *cookie ^= 2;
2355 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN;
2356 if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
2357 IEEE80211_SKB_CB(skb)->hw_queue =
2358 local->hw.offchannel_tx_hw_queue;
2359 local->hw_roc_skb = skb;
2360 local->hw_roc_skb_for_status = skb;
2361 mutex_unlock(&local->mtx);
2362
2363 return 0;
2364 }
2365
2366 /*
2367 * Can transmit right away if the channel was the
2368 * right one and there's no wait involved... If a
2369 * wait is involved, we might otherwise not be on
2370 * the right channel for long enough!
2371 */
2372 if (!is_offchan && !wait && (in_hw_roc || !sdata->vif.bss_conf.idle)) {
2373 ieee80211_tx_skb(sdata, skb); 2454 ieee80211_tx_skb(sdata, skb);
2374 return 0; 2455 ret = 0;
2375 } 2456 goto out_unlock;
2376
2377 wk = kzalloc(sizeof(*wk) + len, GFP_KERNEL);
2378 if (!wk) {
2379 kfree_skb(skb);
2380 return -ENOMEM;
2381 } 2457 }
2382 2458
2383 wk->type = IEEE80211_WORK_OFFCHANNEL_TX; 2459 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN;
2384 wk->chan = chan; 2460 if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
2385 wk->chan_type = channel_type; 2461 IEEE80211_SKB_CB(skb)->hw_queue =
2386 wk->sdata = sdata; 2462 local->hw.offchannel_tx_hw_queue;
2387 wk->done = ieee80211_offchan_tx_done;
2388 wk->offchan_tx.frame = skb;
2389 wk->offchan_tx.wait = wait;
2390 wk->data_len = len;
2391 memcpy(wk->data, buf, len);
2392 2463
2393 ieee80211_add_work(wk); 2464 /* This will handle all kinds of coalescing and immediate TX */
2394 return 0; 2465 ret = ieee80211_start_roc_work(local, sdata, chan, channel_type,
2466 wait, cookie, skb);
2467 if (ret)
2468 kfree_skb(skb);
2469 out_unlock:
2470 mutex_unlock(&local->mtx);
2471 return ret;
2395} 2472}
2396 2473
2397static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, 2474static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
@@ -2400,45 +2477,8 @@ static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
2400{ 2477{
2401 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 2478 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2402 struct ieee80211_local *local = sdata->local; 2479 struct ieee80211_local *local = sdata->local;
2403 struct ieee80211_work *wk;
2404 int ret = -ENOENT;
2405 2480
2406 mutex_lock(&local->mtx); 2481 return ieee80211_cancel_roc(local, cookie, true);
2407
2408 if (local->ops->cancel_remain_on_channel) {
2409 cookie ^= 2;
2410 ret = ieee80211_cancel_remain_on_channel_hw(local, cookie);
2411
2412 if (ret == 0) {
2413 kfree_skb(local->hw_roc_skb);
2414 local->hw_roc_skb = NULL;
2415 local->hw_roc_skb_for_status = NULL;
2416 }
2417
2418 mutex_unlock(&local->mtx);
2419
2420 return ret;
2421 }
2422
2423 list_for_each_entry(wk, &local->work_list, list) {
2424 if (wk->sdata != sdata)
2425 continue;
2426
2427 if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX)
2428 continue;
2429
2430 if (cookie != (unsigned long) wk->offchan_tx.frame)
2431 continue;
2432
2433 wk->timeout = jiffies;
2434
2435 ieee80211_queue_work(&local->hw, &local->work_work);
2436 ret = 0;
2437 break;
2438 }
2439 mutex_unlock(&local->mtx);
2440
2441 return ret;
2442} 2482}
2443 2483
2444static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, 2484static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8c026abcb8d9..e6cbf5b68c89 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -317,55 +317,30 @@ struct mesh_preq_queue {
317 u8 flags; 317 u8 flags;
318}; 318};
319 319
320enum ieee80211_work_type { 320#if HZ/100 == 0
321 IEEE80211_WORK_ABORT, 321#define IEEE80211_ROC_MIN_LEFT 1
322 IEEE80211_WORK_REMAIN_ON_CHANNEL, 322#else
323 IEEE80211_WORK_OFFCHANNEL_TX, 323#define IEEE80211_ROC_MIN_LEFT (HZ/100)
324}; 324#endif
325
326/**
327 * enum work_done_result - indicates what to do after work was done
328 *
329 * @WORK_DONE_DESTROY: This work item is no longer needed, destroy.
330 * @WORK_DONE_REQUEUE: This work item was reset to be reused, and
331 * should be requeued.
332 */
333enum work_done_result {
334 WORK_DONE_DESTROY,
335 WORK_DONE_REQUEUE,
336};
337 325
338struct ieee80211_work { 326struct ieee80211_roc_work {
339 struct list_head list; 327 struct list_head list;
328 struct list_head dependents;
340 329
341 struct rcu_head rcu_head; 330 struct delayed_work work;
342 331
343 struct ieee80211_sub_if_data *sdata; 332 struct ieee80211_sub_if_data *sdata;
344 333
345 enum work_done_result (*done)(struct ieee80211_work *wk,
346 struct sk_buff *skb);
347
348 struct ieee80211_channel *chan; 334 struct ieee80211_channel *chan;
349 enum nl80211_channel_type chan_type; 335 enum nl80211_channel_type chan_type;
350 336
351 unsigned long timeout; 337 bool started, abort, hw_begun, notified;
352 enum ieee80211_work_type type;
353 338
354 bool started; 339 unsigned long hw_start_time;
355 340
356 union { 341 u32 duration, req_duration;
357 struct { 342 struct sk_buff *frame;
358 u32 duration; 343 u64 mgmt_tx_cookie;
359 } remain;
360 struct {
361 struct sk_buff *frame;
362 u32 wait;
363 bool status;
364 } offchan_tx;
365 };
366
367 size_t data_len;
368 u8 data[];
369}; 344};
370 345
371/* flags used in struct ieee80211_if_managed.flags */ 346/* flags used in struct ieee80211_if_managed.flags */
@@ -848,13 +823,6 @@ struct ieee80211_local {
848 const struct ieee80211_ops *ops; 823 const struct ieee80211_ops *ops;
849 824
850 /* 825 /*
851 * work stuff, potentially off-channel (in the future)
852 */
853 struct list_head work_list;
854 struct timer_list work_timer;
855 struct work_struct work_work;
856
857 /*
858 * private workqueue to mac80211. mac80211 makes this accessible 826 * private workqueue to mac80211. mac80211 makes this accessible
859 * via ieee80211_queue_work() 827 * via ieee80211_queue_work()
860 */ 828 */
@@ -1088,14 +1056,12 @@ struct ieee80211_local {
1088 } debugfs; 1056 } debugfs;
1089#endif 1057#endif
1090 1058
1091 struct ieee80211_channel *hw_roc_channel; 1059 /*
1092 struct net_device *hw_roc_dev; 1060 * Remain-on-channel support
1093 struct sk_buff *hw_roc_skb, *hw_roc_skb_for_status; 1061 */
1062 struct list_head roc_list;
1094 struct work_struct hw_roc_start, hw_roc_done; 1063 struct work_struct hw_roc_start, hw_roc_done;
1095 enum nl80211_channel_type hw_roc_channel_type; 1064 unsigned long hw_roc_start_time;
1096 unsigned int hw_roc_duration;
1097 u32 hw_roc_cookie;
1098 bool hw_roc_for_tx;
1099 1065
1100 struct idr ack_status_frames; 1066 struct idr ack_status_frames;
1101 spinlock_t ack_status_lock; 1067 spinlock_t ack_status_lock;
@@ -1291,7 +1257,12 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
1291 bool offchannel_ps_enable); 1257 bool offchannel_ps_enable);
1292void ieee80211_offchannel_return(struct ieee80211_local *local, 1258void ieee80211_offchannel_return(struct ieee80211_local *local,
1293 bool offchannel_ps_disable); 1259 bool offchannel_ps_disable);
1294void ieee80211_hw_roc_setup(struct ieee80211_local *local); 1260void ieee80211_roc_setup(struct ieee80211_local *local);
1261void ieee80211_start_next_roc(struct ieee80211_local *local);
1262void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
1263void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc);
1264void ieee80211_sw_roc_work(struct work_struct *work);
1265void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
1295 1266
1296/* interface handling */ 1267/* interface handling */
1297int ieee80211_iface_init(void); 1268int ieee80211_iface_init(void);
@@ -1501,18 +1472,6 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1501 enum nl80211_channel_type channel_type, 1472 enum nl80211_channel_type channel_type,
1502 u16 prot_mode); 1473 u16 prot_mode);
1503 1474
1504/* internal work items */
1505void ieee80211_work_init(struct ieee80211_local *local);
1506void ieee80211_add_work(struct ieee80211_work *wk);
1507void free_work(struct ieee80211_work *wk);
1508void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata);
1509int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
1510 struct ieee80211_channel *chan,
1511 enum nl80211_channel_type channel_type,
1512 unsigned int duration, u64 *cookie);
1513int ieee80211_wk_cancel_remain_on_channel(
1514 struct ieee80211_sub_if_data *sdata, u64 cookie);
1515
1516/* channel management */ 1475/* channel management */
1517enum ieee80211_chan_mode { 1476enum ieee80211_chan_mode {
1518 CHAN_MODE_UNDEFINED, 1477 CHAN_MODE_UNDEFINED,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 968d71c50713..87aeb4f21ffd 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -528,10 +528,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
528 */ 528 */
529 netif_tx_stop_all_queues(sdata->dev); 529 netif_tx_stop_all_queues(sdata->dev);
530 530
531 /* 531 ieee80211_roc_purge(sdata);
532 * Purge work for this interface.
533 */
534 ieee80211_work_purge(sdata);
535 532
536 /* 533 /*
537 * Remove all stations associated with this interface. 534 * Remove all stations associated with this interface.
@@ -637,18 +634,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
637 ieee80211_configure_filter(local); 634 ieee80211_configure_filter(local);
638 break; 635 break;
639 default: 636 default:
640 mutex_lock(&local->mtx);
641 if (local->hw_roc_dev == sdata->dev &&
642 local->hw_roc_channel) {
643 /* ignore return value since this is racy */
644 drv_cancel_remain_on_channel(local);
645 ieee80211_queue_work(&local->hw, &local->hw_roc_done);
646 }
647 mutex_unlock(&local->mtx);
648
649 flush_work(&local->hw_roc_start);
650 flush_work(&local->hw_roc_done);
651
652 flush_work(&sdata->work); 637 flush_work(&sdata->work);
653 /* 638 /*
654 * When we get here, the interface is marked down. 639 * When we get here, the interface is marked down.
@@ -1457,8 +1442,8 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
1457 struct ieee80211_sub_if_data *sdata; 1442 struct ieee80211_sub_if_data *sdata;
1458 int count = 0; 1443 int count = 0;
1459 bool working = false, scanning = false; 1444 bool working = false, scanning = false;
1460 struct ieee80211_work *wk;
1461 unsigned int led_trig_start = 0, led_trig_stop = 0; 1445 unsigned int led_trig_start = 0, led_trig_stop = 0;
1446 struct ieee80211_roc_work *roc;
1462 1447
1463#ifdef CONFIG_PROVE_LOCKING 1448#ifdef CONFIG_PROVE_LOCKING
1464 WARN_ON(debug_locks && !lockdep_rtnl_is_held() && 1449 WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
@@ -1494,9 +1479,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
1494 } 1479 }
1495 1480
1496 if (!local->ops->remain_on_channel) { 1481 if (!local->ops->remain_on_channel) {
1497 list_for_each_entry(wk, &local->work_list, list) { 1482 list_for_each_entry(roc, &local->roc_list, list) {
1498 working = true; 1483 working = true;
1499 wk->sdata->vif.bss_conf.idle = false; 1484 roc->sdata->vif.bss_conf.idle = false;
1500 } 1485 }
1501 } 1486 }
1502 1487
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 779ac613ee57..d81c178c7712 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -625,8 +625,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
625 625
626 INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); 626 INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
627 627
628 ieee80211_work_init(local);
629
630 INIT_WORK(&local->restart_work, ieee80211_restart_work); 628 INIT_WORK(&local->restart_work, ieee80211_restart_work);
631 629
632 INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); 630 INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
@@ -669,7 +667,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
669 667
670 ieee80211_led_names(local); 668 ieee80211_led_names(local);
671 669
672 ieee80211_hw_roc_setup(local); 670 ieee80211_roc_setup(local);
673 671
674 return &local->hw; 672 return &local->hw;
675} 673}
@@ -1016,12 +1014,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
1016 1014
1017 rtnl_unlock(); 1015 rtnl_unlock();
1018 1016
1019 /*
1020 * Now all work items will be gone, but the
1021 * timer might still be armed, so delete it
1022 */
1023 del_timer_sync(&local->work_timer);
1024
1025 cancel_work_sync(&local->restart_work); 1017 cancel_work_sync(&local->restart_work);
1026 cancel_work_sync(&local->reconfig_filter); 1018 cancel_work_sync(&local->reconfig_filter);
1027 1019
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 8f482b15bc51..abb226dc4753 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -16,6 +16,7 @@
16#include <net/mac80211.h> 16#include <net/mac80211.h>
17#include "ieee80211_i.h" 17#include "ieee80211_i.h"
18#include "driver-trace.h" 18#include "driver-trace.h"
19#include "driver-ops.h"
19 20
20/* 21/*
21 * Tell our hardware to disable PS. 22 * Tell our hardware to disable PS.
@@ -181,32 +182,58 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
181 mutex_unlock(&local->iflist_mtx); 182 mutex_unlock(&local->iflist_mtx);
182} 183}
183 184
185void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)
186{
187 if (roc->notified)
188 return;
189
190 if (roc->mgmt_tx_cookie) {
191 if (!WARN_ON(!roc->frame)) {
192 ieee80211_tx_skb(roc->sdata, roc->frame);
193 roc->frame = NULL;
194 }
195 } else {
196 cfg80211_ready_on_channel(roc->sdata->dev, (unsigned long)roc,
197 roc->chan, roc->chan_type,
198 roc->req_duration, GFP_KERNEL);
199 }
200
201 roc->notified = true;
202}
203
184static void ieee80211_hw_roc_start(struct work_struct *work) 204static void ieee80211_hw_roc_start(struct work_struct *work)
185{ 205{
186 struct ieee80211_local *local = 206 struct ieee80211_local *local =
187 container_of(work, struct ieee80211_local, hw_roc_start); 207 container_of(work, struct ieee80211_local, hw_roc_start);
188 struct ieee80211_sub_if_data *sdata; 208 struct ieee80211_roc_work *roc, *dep, *tmp;
189 209
190 mutex_lock(&local->mtx); 210 mutex_lock(&local->mtx);
191 211
192 if (!local->hw_roc_channel) { 212 if (list_empty(&local->roc_list))
193 mutex_unlock(&local->mtx); 213 goto out_unlock;
194 return;
195 }
196 214
197 if (local->hw_roc_skb) { 215 roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work,
198 sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev); 216 list);
199 ieee80211_tx_skb(sdata, local->hw_roc_skb); 217
200 local->hw_roc_skb = NULL; 218 if (!roc->started)
201 } else { 219 goto out_unlock;
202 cfg80211_ready_on_channel(local->hw_roc_dev, 220
203 local->hw_roc_cookie, 221 roc->hw_begun = true;
204 local->hw_roc_channel, 222 roc->hw_start_time = local->hw_roc_start_time;
205 local->hw_roc_channel_type,
206 local->hw_roc_duration,
207 GFP_KERNEL);
208 }
209 223
224 ieee80211_handle_roc_started(roc);
225 list_for_each_entry_safe(dep, tmp, &roc->dependents, list) {
226 ieee80211_handle_roc_started(dep);
227
228 if (dep->duration > roc->duration) {
229 u32 dur = dep->duration;
230 dep->duration = dur - roc->duration;
231 roc->duration = dur;
232 list_del(&dep->list);
233 list_add(&dep->list, &roc->list);
234 }
235 }
236 out_unlock:
210 mutex_unlock(&local->mtx); 237 mutex_unlock(&local->mtx);
211} 238}
212 239
@@ -214,50 +241,179 @@ void ieee80211_ready_on_channel(struct ieee80211_hw *hw)
214{ 241{
215 struct ieee80211_local *local = hw_to_local(hw); 242 struct ieee80211_local *local = hw_to_local(hw);
216 243
244 local->hw_roc_start_time = jiffies;
245
217 trace_api_ready_on_channel(local); 246 trace_api_ready_on_channel(local);
218 247
219 ieee80211_queue_work(hw, &local->hw_roc_start); 248 ieee80211_queue_work(hw, &local->hw_roc_start);
220} 249}
221EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel); 250EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel);
222 251
223static void ieee80211_hw_roc_done(struct work_struct *work) 252void ieee80211_start_next_roc(struct ieee80211_local *local)
224{ 253{
225 struct ieee80211_local *local = 254 struct ieee80211_roc_work *roc;
226 container_of(work, struct ieee80211_local, hw_roc_done);
227 255
228 mutex_lock(&local->mtx); 256 lockdep_assert_held(&local->mtx);
229 257
230 if (!local->hw_roc_channel) { 258 if (list_empty(&local->roc_list)) {
231 mutex_unlock(&local->mtx); 259 ieee80211_run_deferred_scan(local);
232 return; 260 return;
233 } 261 }
234 262
235 /* was never transmitted */ 263 roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work,
236 if (local->hw_roc_skb) { 264 list);
237 u64 cookie;
238 265
239 cookie = local->hw_roc_cookie ^ 2; 266 if (local->ops->remain_on_channel) {
267 int ret, duration = roc->duration;
240 268
241 cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie, 269 /* XXX: duplicated, see ieee80211_start_roc_work() */
242 local->hw_roc_skb->data, 270 if (!duration)
243 local->hw_roc_skb->len, false, 271 duration = 10;
244 GFP_KERNEL);
245 272
246 kfree_skb(local->hw_roc_skb); 273 ret = drv_remain_on_channel(local, roc->chan,
247 local->hw_roc_skb = NULL; 274 roc->chan_type,
248 local->hw_roc_skb_for_status = NULL; 275 duration);
276
277 roc->started = true;
278
279 if (ret) {
280 wiphy_warn(local->hw.wiphy,
281 "failed to start next HW ROC (%d)\n", ret);
282 /*
283 * queue the work struct again to avoid recursion
284 * when multiple failures occur
285 */
286 ieee80211_remain_on_channel_expired(&local->hw);
287 }
288 } else {
289 /* delay it a bit */
290 ieee80211_queue_delayed_work(&local->hw, &roc->work,
291 round_jiffies_relative(HZ/2));
292 }
293}
294
295void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
296{
297 struct ieee80211_roc_work *dep, *tmp;
298
299 /* was never transmitted */
300 if (roc->frame) {
301 cfg80211_mgmt_tx_status(roc->sdata->dev,
302 (unsigned long)roc->frame,
303 roc->frame->data, roc->frame->len,
304 false, GFP_KERNEL);
305 kfree_skb(roc->frame);
249 } 306 }
250 307
251 if (!local->hw_roc_for_tx) 308 if (!roc->mgmt_tx_cookie)
252 cfg80211_remain_on_channel_expired(local->hw_roc_dev, 309 cfg80211_remain_on_channel_expired(roc->sdata->dev,
253 local->hw_roc_cookie, 310 (unsigned long)roc,
254 local->hw_roc_channel, 311 roc->chan, roc->chan_type,
255 local->hw_roc_channel_type,
256 GFP_KERNEL); 312 GFP_KERNEL);
257 313
258 local->hw_roc_channel = NULL; 314 list_for_each_entry_safe(dep, tmp, &roc->dependents, list)
259 local->hw_roc_cookie = 0; 315 ieee80211_roc_notify_destroy(dep);
316
317 kfree(roc);
318}
319
320void ieee80211_sw_roc_work(struct work_struct *work)
321{
322 struct ieee80211_roc_work *roc =
323 container_of(work, struct ieee80211_roc_work, work.work);
324 struct ieee80211_sub_if_data *sdata = roc->sdata;
325 struct ieee80211_local *local = sdata->local;
326
327 mutex_lock(&local->mtx);
328
329 if (roc->abort)
330 goto finish;
331
332 if (WARN_ON(list_empty(&local->roc_list)))
333 goto out_unlock;
334
335 if (WARN_ON(roc != list_first_entry(&local->roc_list,
336 struct ieee80211_roc_work,
337 list)))
338 goto out_unlock;
339
340 if (!roc->started) {
341 struct ieee80211_roc_work *dep;
342
343 /* start this ROC */
260 344
345 /* switch channel etc */
346 ieee80211_recalc_idle(local);
347
348 local->tmp_channel = roc->chan;
349 local->tmp_channel_type = roc->chan_type;
350 ieee80211_hw_config(local, 0);
351
352 /* tell userspace or send frame */
353 ieee80211_handle_roc_started(roc);
354 list_for_each_entry(dep, &roc->dependents, list)
355 ieee80211_handle_roc_started(dep);
356
357 /* if it was pure TX, just finish right away */
358 if (!roc->duration)
359 goto finish;
360
361 roc->started = true;
362 ieee80211_queue_delayed_work(&local->hw, &roc->work,
363 msecs_to_jiffies(roc->duration));
364 } else {
365 /* finish this ROC */
366 finish:
367 list_del(&roc->list);
368 ieee80211_roc_notify_destroy(roc);
369
370 if (roc->started) {
371 drv_flush(local, false);
372
373 local->tmp_channel = NULL;
374 ieee80211_hw_config(local, 0);
375
376 ieee80211_offchannel_return(local, true);
377 }
378
379 ieee80211_recalc_idle(local);
380
381 ieee80211_start_next_roc(local);
382 ieee80211_run_deferred_scan(local);
383 }
384
385 out_unlock:
386 mutex_unlock(&local->mtx);
387}
388
389static void ieee80211_hw_roc_done(struct work_struct *work)
390{
391 struct ieee80211_local *local =
392 container_of(work, struct ieee80211_local, hw_roc_done);
393 struct ieee80211_roc_work *roc;
394
395 mutex_lock(&local->mtx);
396
397 if (list_empty(&local->roc_list))
398 goto out_unlock;
399
400 roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work,
401 list);
402
403 if (!roc->started)
404 goto out_unlock;
405
406 list_del(&roc->list);
407
408 ieee80211_roc_notify_destroy(roc);
409
410 /* if there's another roc, start it now */
411 ieee80211_start_next_roc(local);
412
413 /* or scan maybe */
414 ieee80211_run_deferred_scan(local);
415
416 out_unlock:
261 mutex_unlock(&local->mtx); 417 mutex_unlock(&local->mtx);
262} 418}
263 419
@@ -271,8 +427,48 @@ void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw)
271} 427}
272EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired); 428EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired);
273 429
274void ieee80211_hw_roc_setup(struct ieee80211_local *local) 430void ieee80211_roc_setup(struct ieee80211_local *local)
275{ 431{
276 INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start); 432 INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start);
277 INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done); 433 INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done);
434 INIT_LIST_HEAD(&local->roc_list);
435}
436
437void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
438{
439 struct ieee80211_local *local = sdata->local;
440 struct ieee80211_roc_work *roc, *tmp;
441 LIST_HEAD(tmp_list);
442
443 mutex_lock(&local->mtx);
444 list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
445 if (roc->sdata != sdata)
446 continue;
447
448 if (roc->started && local->ops->remain_on_channel) {
449 /* can race, so ignore return value */
450 drv_cancel_remain_on_channel(local);
451 }
452
453 list_move_tail(&roc->list, &tmp_list);
454 roc->abort = true;
455 }
456
457 ieee80211_start_next_roc(local);
458 ieee80211_run_deferred_scan(local);
459 mutex_unlock(&local->mtx);
460
461 list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
462 if (local->ops->remain_on_channel) {
463 list_del(&roc->list);
464 ieee80211_roc_notify_destroy(roc);
465 } else {
466 ieee80211_queue_delayed_work(&local->hw, &roc->work, 0);
467
468 /* work will clean up etc */
469 flush_delayed_work(&roc->work);
470 }
471 }
472
473 WARN_ON_ONCE(!list_empty(&tmp_list));
278} 474}
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 169da0742c81..379f178eab5f 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -323,7 +323,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
323 ieee80211_mlme_notify_scan_completed(local); 323 ieee80211_mlme_notify_scan_completed(local);
324 ieee80211_ibss_notify_scan_completed(local); 324 ieee80211_ibss_notify_scan_completed(local);
325 ieee80211_mesh_notify_scan_completed(local); 325 ieee80211_mesh_notify_scan_completed(local);
326 ieee80211_queue_work(&local->hw, &local->work_work); 326 ieee80211_start_next_roc(local);
327} 327}
328 328
329void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) 329void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
@@ -376,7 +376,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
376static bool ieee80211_can_scan(struct ieee80211_local *local, 376static bool ieee80211_can_scan(struct ieee80211_local *local,
377 struct ieee80211_sub_if_data *sdata) 377 struct ieee80211_sub_if_data *sdata)
378{ 378{
379 if (!list_empty(&local->work_list)) 379 if (!list_empty(&local->roc_list))
380 return false; 380 return false;
381 381
382 if (sdata->vif.type == NL80211_IFTYPE_STATION && 382 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 63a769015068..6b4f42527887 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -520,36 +520,16 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
520 520
521 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { 521 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
522 u64 cookie = (unsigned long)skb; 522 u64 cookie = (unsigned long)skb;
523 acked = info->flags & IEEE80211_TX_STAT_ACK;
523 524
524 if (ieee80211_is_nullfunc(hdr->frame_control) || 525 if (ieee80211_is_nullfunc(hdr->frame_control) ||
525 ieee80211_is_qos_nullfunc(hdr->frame_control)) { 526 ieee80211_is_qos_nullfunc(hdr->frame_control))
526 acked = info->flags & IEEE80211_TX_STAT_ACK;
527
528 cfg80211_probe_status(skb->dev, hdr->addr1, 527 cfg80211_probe_status(skb->dev, hdr->addr1,
529 cookie, acked, GFP_ATOMIC); 528 cookie, acked, GFP_ATOMIC);
530 } else { 529 else
531 struct ieee80211_work *wk;
532
533 rcu_read_lock();
534 list_for_each_entry_rcu(wk, &local->work_list, list) {
535 if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX)
536 continue;
537 if (wk->offchan_tx.frame != skb)
538 continue;
539 wk->offchan_tx.status = true;
540 break;
541 }
542 rcu_read_unlock();
543 if (local->hw_roc_skb_for_status == skb) {
544 cookie = local->hw_roc_cookie ^ 2;
545 local->hw_roc_skb_for_status = NULL;
546 }
547
548 cfg80211_mgmt_tx_status( 530 cfg80211_mgmt_tx_status(
549 skb->dev, cookie, skb->data, skb->len, 531 skb->dev, cookie, skb->data, skb->len,
550 !!(info->flags & IEEE80211_TX_STAT_ACK), 532 acked, GFP_ATOMIC);
551 GFP_ATOMIC);
552 }
553 } 533 }
554 534
555 if (unlikely(info->ack_frame_id)) { 535 if (unlikely(info->ack_frame_id)) {
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
deleted file mode 100644
index b2650a9d45ff..000000000000
--- a/net/mac80211/work.c
+++ /dev/null
@@ -1,370 +0,0 @@
1/*
2 * mac80211 work implementation
3 *
4 * Copyright 2003-2008, Jouni Malinen <j@w1.fi>
5 * Copyright 2004, Instant802 Networks, Inc.
6 * Copyright 2005, Devicescape Software, Inc.
7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9 * Copyright 2009, Johannes Berg <johannes@sipsolutions.net>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/delay.h>
17#include <linux/if_ether.h>
18#include <linux/skbuff.h>
19#include <linux/if_arp.h>
20#include <linux/etherdevice.h>
21#include <linux/crc32.h>
22#include <linux/slab.h>
23#include <net/mac80211.h>
24#include <asm/unaligned.h>
25
26#include "ieee80211_i.h"
27#include "rate.h"
28#include "driver-ops.h"
29
30enum work_action {
31 WORK_ACT_NONE,
32 WORK_ACT_TIMEOUT,
33};
34
35
36/* utils */
37static inline void ASSERT_WORK_MTX(struct ieee80211_local *local)
38{
39 lockdep_assert_held(&local->mtx);
40}
41
42/*
43 * We can have multiple work items (and connection probing)
44 * scheduling this timer, but we need to take care to only
45 * reschedule it when it should fire _earlier_ than it was
46 * asked for before, or if it's not pending right now. This
47 * function ensures that. Note that it then is required to
48 * run this function for all timeouts after the first one
49 * has happened -- the work that runs from this timer will
50 * do that.
51 */
52static void run_again(struct ieee80211_local *local,
53 unsigned long timeout)
54{
55 ASSERT_WORK_MTX(local);
56
57 if (!timer_pending(&local->work_timer) ||
58 time_before(timeout, local->work_timer.expires))
59 mod_timer(&local->work_timer, timeout);
60}
61
62void free_work(struct ieee80211_work *wk)
63{
64 kfree_rcu(wk, rcu_head);
65}
66
67static enum work_action __must_check
68ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
69{
70 /*
71 * First time we run, do nothing -- the generic code will
72 * have switched to the right channel etc.
73 */
74 if (!wk->started) {
75 wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration);
76
77 cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk,
78 wk->chan, wk->chan_type,
79 wk->remain.duration, GFP_KERNEL);
80
81 return WORK_ACT_NONE;
82 }
83
84 return WORK_ACT_TIMEOUT;
85}
86
87static enum work_action __must_check
88ieee80211_offchannel_tx(struct ieee80211_work *wk)
89{
90 if (!wk->started) {
91 wk->timeout = jiffies + msecs_to_jiffies(wk->offchan_tx.wait);
92
93 /*
94 * After this, offchan_tx.frame remains but now is no
95 * longer a valid pointer -- we still need it as the
96 * cookie for canceling this work/status matching.
97 */
98 ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame);
99
100 return WORK_ACT_NONE;
101 }
102
103 return WORK_ACT_TIMEOUT;
104}
105
106static void ieee80211_work_timer(unsigned long data)
107{
108 struct ieee80211_local *local = (void *) data;
109
110 if (local->quiescing)
111 return;
112
113 ieee80211_queue_work(&local->hw, &local->work_work);
114}
115
116static void ieee80211_work_work(struct work_struct *work)
117{
118 struct ieee80211_local *local =
119 container_of(work, struct ieee80211_local, work_work);
120 struct ieee80211_work *wk, *tmp;
121 LIST_HEAD(free_work);
122 enum work_action rma;
123 bool remain_off_channel = false;
124
125 /*
126 * ieee80211_queue_work() should have picked up most cases,
127 * here we'll pick the rest.
128 */
129 if (WARN(local->suspended, "work scheduled while going to suspend\n"))
130 return;
131
132 mutex_lock(&local->mtx);
133
134 if (local->scanning) {
135 mutex_unlock(&local->mtx);
136 return;
137 }
138
139 ieee80211_recalc_idle(local);
140
141 list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
142 bool started = wk->started;
143
144 /* mark work as started if it's on the current off-channel */
145 if (!started && local->tmp_channel &&
146 wk->chan == local->tmp_channel &&
147 wk->chan_type == local->tmp_channel_type) {
148 started = true;
149 wk->timeout = jiffies;
150 }
151
152 if (!started && !local->tmp_channel) {
153 ieee80211_offchannel_stop_vifs(local, true);
154
155 local->tmp_channel = wk->chan;
156 local->tmp_channel_type = wk->chan_type;
157
158 ieee80211_hw_config(local, 0);
159
160 started = true;
161 wk->timeout = jiffies;
162 }
163
164 /* don't try to work with items that aren't started */
165 if (!started)
166 continue;
167
168 if (time_is_after_jiffies(wk->timeout)) {
169 /*
170 * This work item isn't supposed to be worked on
171 * right now, but take care to adjust the timer
172 * properly.
173 */
174 run_again(local, wk->timeout);
175 continue;
176 }
177
178 switch (wk->type) {
179 default:
180 WARN_ON(1);
181 /* nothing */
182 rma = WORK_ACT_NONE;
183 break;
184 case IEEE80211_WORK_ABORT:
185 rma = WORK_ACT_TIMEOUT;
186 break;
187 case IEEE80211_WORK_REMAIN_ON_CHANNEL:
188 rma = ieee80211_remain_on_channel_timeout(wk);
189 break;
190 case IEEE80211_WORK_OFFCHANNEL_TX:
191 rma = ieee80211_offchannel_tx(wk);
192 break;
193 }
194
195 wk->started = started;
196
197 switch (rma) {
198 case WORK_ACT_NONE:
199 /* might have changed the timeout */
200 run_again(local, wk->timeout);
201 break;
202 case WORK_ACT_TIMEOUT:
203 list_del_rcu(&wk->list);
204 synchronize_rcu();
205 list_add(&wk->list, &free_work);
206 break;
207 default:
208 WARN(1, "unexpected: %d", rma);
209 }
210 }
211
212 list_for_each_entry(wk, &local->work_list, list) {
213 if (!wk->started)
214 continue;
215 if (wk->chan != local->tmp_channel ||
216 wk->chan_type != local->tmp_channel_type)
217 continue;
218 remain_off_channel = true;
219 }
220
221 if (!remain_off_channel && local->tmp_channel) {
222 local->tmp_channel = NULL;
223 ieee80211_hw_config(local, 0);
224
225 ieee80211_offchannel_return(local, true);
226
227 /* give connection some time to breathe */
228 run_again(local, jiffies + HZ/2);
229 }
230
231 ieee80211_recalc_idle(local);
232 ieee80211_run_deferred_scan(local);
233
234 mutex_unlock(&local->mtx);
235
236 list_for_each_entry_safe(wk, tmp, &free_work, list) {
237 wk->done(wk, NULL);
238 list_del(&wk->list);
239 kfree(wk);
240 }
241}
242
243void ieee80211_add_work(struct ieee80211_work *wk)
244{
245 struct ieee80211_local *local;
246
247 if (WARN_ON(!wk->chan))
248 return;
249
250 if (WARN_ON(!wk->sdata))
251 return;
252
253 if (WARN_ON(!wk->done))
254 return;
255
256 if (WARN_ON(!ieee80211_sdata_running(wk->sdata)))
257 return;
258
259 wk->started = false;
260
261 local = wk->sdata->local;
262 mutex_lock(&local->mtx);
263 list_add_tail(&wk->list, &local->work_list);
264 mutex_unlock(&local->mtx);
265
266 ieee80211_queue_work(&local->hw, &local->work_work);
267}
268
269void ieee80211_work_init(struct ieee80211_local *local)
270{
271 INIT_LIST_HEAD(&local->work_list);
272 setup_timer(&local->work_timer, ieee80211_work_timer,
273 (unsigned long)local);
274 INIT_WORK(&local->work_work, ieee80211_work_work);
275}
276
277void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
278{
279 struct ieee80211_local *local = sdata->local;
280 struct ieee80211_work *wk;
281 bool cleanup = false;
282
283 mutex_lock(&local->mtx);
284 list_for_each_entry(wk, &local->work_list, list) {
285 if (wk->sdata != sdata)
286 continue;
287 cleanup = true;
288 wk->type = IEEE80211_WORK_ABORT;
289 wk->started = true;
290 wk->timeout = jiffies;
291 }
292 mutex_unlock(&local->mtx);
293
294 /* run cleanups etc. */
295 if (cleanup)
296 ieee80211_work_work(&local->work_work);
297
298 mutex_lock(&local->mtx);
299 list_for_each_entry(wk, &local->work_list, list) {
300 if (wk->sdata != sdata)
301 continue;
302 WARN_ON(1);
303 break;
304 }
305 mutex_unlock(&local->mtx);
306}
307
308static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk,
309 struct sk_buff *skb)
310{
311 /*
312 * We are done serving the remain-on-channel command.
313 */
314 cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk,
315 wk->chan, wk->chan_type,
316 GFP_KERNEL);
317
318 return WORK_DONE_DESTROY;
319}
320
321int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
322 struct ieee80211_channel *chan,
323 enum nl80211_channel_type channel_type,
324 unsigned int duration, u64 *cookie)
325{
326 struct ieee80211_work *wk;
327
328 wk = kzalloc(sizeof(*wk), GFP_KERNEL);
329 if (!wk)
330 return -ENOMEM;
331
332 wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL;
333 wk->chan = chan;
334 wk->chan_type = channel_type;
335 wk->sdata = sdata;
336 wk->done = ieee80211_remain_done;
337
338 wk->remain.duration = duration;
339
340 *cookie = (unsigned long) wk;
341
342 ieee80211_add_work(wk);
343
344 return 0;
345}
346
347int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
348 u64 cookie)
349{
350 struct ieee80211_local *local = sdata->local;
351 struct ieee80211_work *wk, *tmp;
352 bool found = false;
353
354 mutex_lock(&local->mtx);
355 list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
356 if ((unsigned long) wk == cookie) {
357 wk->timeout = jiffies;
358 found = true;
359 break;
360 }
361 }
362 mutex_unlock(&local->mtx);
363
364 if (!found)
365 return -ENOENT;
366
367 ieee80211_queue_work(&local->hw, &local->work_work);
368
369 return 0;
370}