aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-06-05 08:28:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-06 15:31:18 -0400
commit2eb278e083549f4eb29838037004054b3b55df62 (patch)
tree803f076e7d7a1ed58e1c9e196bda7c2c2bb24bdf
parent196ac1c13d4db6c276dbb1c9190c8d7d45a83f1f (diff)
mac80211: unify SW/offload remain-on-channel
Redesign all the off-channel code, getting rid of the generic off-channel work concept, replacing it with a simple remain-on-channel list. This fixes a number of small issues with the ROC implementation: * offloaded remain-on-channel couldn't be queued, now we can queue it as well, if needed * in iwlwifi (the only user) offloaded ROC is mutually exclusive with scanning, use the new queue to handle that case -- I expect that it will later depend on a HW flag The bigger issue though is that there's a bad bug in the current implementation: if we get a mgmt TX request while HW roc is active, and this new request has a wait time, we actually schedule a software ROC instead since we can't guarantee the existing offloaded ROC will still be that long. To fix this, the queuing mechanism was needed. The queuing mechanism for offloaded ROC isn't yet optimal, ideally we should add API to have the HW extend the ROC if needed. We could add that later but for now use a software implementation. Overall, this unifies the behaviour between the offloaded and software-implemented case as much as possible. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/net/mac80211.h3
-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
10 files changed, 532 insertions, 754 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 6e700bf8d4a5..d152f54064fd 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2184,9 +2184,6 @@ enum ieee80211_rate_control_changed {
2184 * normally except for the %IEEE80211_TX_CTL_TX_OFFCHAN flag. When the 2184 * normally except for the %IEEE80211_TX_CTL_TX_OFFCHAN flag. When the
2185 * duration (which will always be non-zero) expires, the driver must call 2185 * duration (which will always be non-zero) expires, the driver must call
2186 * ieee80211_remain_on_channel_expired(). 2186 * ieee80211_remain_on_channel_expired().
2187 * The driver must not call ieee80211_remain_on_channel_expired() before
2188 * the TX status for a frame that was sent off-channel, otherwise the TX
2189 * status is reported to userspace in an invalid way.
2190 * Note that this callback may be called while the device is in IDLE and 2187 * Note that this callback may be called while the device is in IDLE and
2191 * must be accepted in this case. 2188 * must be accepted in this case.
2192 * This callback may sleep. 2189 * This callback may sleep.
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}