work.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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. #include <linux/delay.h>
  16. #include <linux/if_ether.h>
  17. #include <linux/skbuff.h>
  18. #include <linux/if_arp.h>
  19. #include <linux/etherdevice.h>
  20. #include <linux/crc32.h>
  21. #include <linux/slab.h>
  22. #include <net/mac80211.h>
  23. #include <asm/unaligned.h>
  24. #include "ieee80211_i.h"
  25. #include "rate.h"
  26. #include "driver-ops.h"
  27. enum work_action {
  28. WORK_ACT_NONE,
  29. WORK_ACT_TIMEOUT,
  30. };
  31. /* utils */
  32. static inline void ASSERT_WORK_MTX(struct ieee80211_local *local)
  33. {
  34. lockdep_assert_held(&local->mtx);
  35. }
  36. /*
  37. * We can have multiple work items (and connection probing)
  38. * scheduling this timer, but we need to take care to only
  39. * reschedule it when it should fire _earlier_ than it was
  40. * asked for before, or if it's not pending right now. This
  41. * function ensures that. Note that it then is required to
  42. * run this function for all timeouts after the first one
  43. * has happened -- the work that runs from this timer will
  44. * do that.
  45. */
  46. static void run_again(struct ieee80211_local *local,
  47. unsigned long timeout)
  48. {
  49. ASSERT_WORK_MTX(local);
  50. if (!timer_pending(&local->work_timer) ||
  51. time_before(timeout, local->work_timer.expires))
  52. mod_timer(&local->work_timer, timeout);
  53. }
  54. void free_work(struct ieee80211_work *wk)
  55. {
  56. kfree_rcu(wk, rcu_head);
  57. }
  58. static enum work_action __must_check
  59. ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
  60. {
  61. /*
  62. * First time we run, do nothing -- the generic code will
  63. * have switched to the right channel etc.
  64. */
  65. if (!wk->started) {
  66. wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration);
  67. cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk,
  68. wk->chan, wk->chan_type,
  69. wk->remain.duration, GFP_KERNEL);
  70. return WORK_ACT_NONE;
  71. }
  72. return WORK_ACT_TIMEOUT;
  73. }
  74. static enum work_action __must_check
  75. ieee80211_offchannel_tx(struct ieee80211_work *wk)
  76. {
  77. if (!wk->started) {
  78. wk->timeout = jiffies + msecs_to_jiffies(wk->offchan_tx.wait);
  79. /*
  80. * After this, offchan_tx.frame remains but now is no
  81. * longer a valid pointer -- we still need it as the
  82. * cookie for canceling this work/status matching.
  83. */
  84. ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame);
  85. return WORK_ACT_NONE;
  86. }
  87. return WORK_ACT_TIMEOUT;
  88. }
  89. static void ieee80211_work_timer(unsigned long data)
  90. {
  91. struct ieee80211_local *local = (void *) data;
  92. if (local->quiescing)
  93. return;
  94. ieee80211_queue_work(&local->hw, &local->work_work);
  95. }
  96. static void ieee80211_work_work(struct work_struct *work)
  97. {
  98. struct ieee80211_local *local =
  99. container_of(work, struct ieee80211_local, work_work);
  100. struct ieee80211_work *wk, *tmp;
  101. LIST_HEAD(free_work);
  102. enum work_action rma;
  103. bool remain_off_channel = false;
  104. if (local->scanning)
  105. return;
  106. /*
  107. * ieee80211_queue_work() should have picked up most cases,
  108. * here we'll pick the rest.
  109. */
  110. if (WARN(local->suspended, "work scheduled while going to suspend\n"))
  111. return;
  112. mutex_lock(&local->mtx);
  113. ieee80211_recalc_idle(local);
  114. list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
  115. bool started = wk->started;
  116. /* mark work as started if it's on the current off-channel */
  117. if (!started && local->tmp_channel &&
  118. wk->chan == local->tmp_channel &&
  119. wk->chan_type == local->tmp_channel_type) {
  120. started = true;
  121. wk->timeout = jiffies;
  122. }
  123. if (!started && !local->tmp_channel) {
  124. ieee80211_offchannel_stop_vifs(local);
  125. local->tmp_channel = wk->chan;
  126. local->tmp_channel_type = wk->chan_type;
  127. ieee80211_hw_config(local, 0);
  128. started = true;
  129. wk->timeout = jiffies;
  130. }
  131. /* don't try to work with items that aren't started */
  132. if (!started)
  133. continue;
  134. if (time_is_after_jiffies(wk->timeout)) {
  135. /*
  136. * This work item isn't supposed to be worked on
  137. * right now, but take care to adjust the timer
  138. * properly.
  139. */
  140. run_again(local, wk->timeout);
  141. continue;
  142. }
  143. switch (wk->type) {
  144. default:
  145. WARN_ON(1);
  146. /* nothing */
  147. rma = WORK_ACT_NONE;
  148. break;
  149. case IEEE80211_WORK_ABORT:
  150. rma = WORK_ACT_TIMEOUT;
  151. break;
  152. case IEEE80211_WORK_REMAIN_ON_CHANNEL:
  153. rma = ieee80211_remain_on_channel_timeout(wk);
  154. break;
  155. case IEEE80211_WORK_OFFCHANNEL_TX:
  156. rma = ieee80211_offchannel_tx(wk);
  157. break;
  158. }
  159. wk->started = started;
  160. switch (rma) {
  161. case WORK_ACT_NONE:
  162. /* might have changed the timeout */
  163. run_again(local, wk->timeout);
  164. break;
  165. case WORK_ACT_TIMEOUT:
  166. list_del_rcu(&wk->list);
  167. synchronize_rcu();
  168. list_add(&wk->list, &free_work);
  169. break;
  170. default:
  171. WARN(1, "unexpected: %d", rma);
  172. }
  173. }
  174. list_for_each_entry(wk, &local->work_list, list) {
  175. if (!wk->started)
  176. continue;
  177. if (wk->chan != local->tmp_channel ||
  178. wk->chan_type != local->tmp_channel_type)
  179. continue;
  180. remain_off_channel = true;
  181. }
  182. if (!remain_off_channel && local->tmp_channel) {
  183. local->tmp_channel = NULL;
  184. ieee80211_hw_config(local, 0);
  185. ieee80211_offchannel_return(local);
  186. /* give connection some time to breathe */
  187. run_again(local, jiffies + HZ/2);
  188. }
  189. if (list_empty(&local->work_list) && local->scan_req &&
  190. !local->scanning)
  191. ieee80211_queue_delayed_work(&local->hw,
  192. &local->scan_work,
  193. round_jiffies_relative(0));
  194. ieee80211_recalc_idle(local);
  195. mutex_unlock(&local->mtx);
  196. list_for_each_entry_safe(wk, tmp, &free_work, list) {
  197. wk->done(wk, NULL);
  198. list_del(&wk->list);
  199. kfree(wk);
  200. }
  201. }
  202. void ieee80211_add_work(struct ieee80211_work *wk)
  203. {
  204. struct ieee80211_local *local;
  205. if (WARN_ON(!wk->chan))
  206. return;
  207. if (WARN_ON(!wk->sdata))
  208. return;
  209. if (WARN_ON(!wk->done))
  210. return;
  211. if (WARN_ON(!ieee80211_sdata_running(wk->sdata)))
  212. return;
  213. wk->started = false;
  214. local = wk->sdata->local;
  215. mutex_lock(&local->mtx);
  216. list_add_tail(&wk->list, &local->work_list);
  217. mutex_unlock(&local->mtx);
  218. ieee80211_queue_work(&local->hw, &local->work_work);
  219. }
  220. void ieee80211_work_init(struct ieee80211_local *local)
  221. {
  222. INIT_LIST_HEAD(&local->work_list);
  223. setup_timer(&local->work_timer, ieee80211_work_timer,
  224. (unsigned long)local);
  225. INIT_WORK(&local->work_work, ieee80211_work_work);
  226. }
  227. void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
  228. {
  229. struct ieee80211_local *local = sdata->local;
  230. struct ieee80211_work *wk;
  231. bool cleanup = false;
  232. mutex_lock(&local->mtx);
  233. list_for_each_entry(wk, &local->work_list, list) {
  234. if (wk->sdata != sdata)
  235. continue;
  236. cleanup = true;
  237. wk->type = IEEE80211_WORK_ABORT;
  238. wk->started = true;
  239. wk->timeout = jiffies;
  240. }
  241. mutex_unlock(&local->mtx);
  242. /* run cleanups etc. */
  243. if (cleanup)
  244. ieee80211_work_work(&local->work_work);
  245. mutex_lock(&local->mtx);
  246. list_for_each_entry(wk, &local->work_list, list) {
  247. if (wk->sdata != sdata)
  248. continue;
  249. WARN_ON(1);
  250. break;
  251. }
  252. mutex_unlock(&local->mtx);
  253. }
  254. static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk,
  255. struct sk_buff *skb)
  256. {
  257. /*
  258. * We are done serving the remain-on-channel command.
  259. */
  260. cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk,
  261. wk->chan, wk->chan_type,
  262. GFP_KERNEL);
  263. return WORK_DONE_DESTROY;
  264. }
  265. int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
  266. struct ieee80211_channel *chan,
  267. enum nl80211_channel_type channel_type,
  268. unsigned int duration, u64 *cookie)
  269. {
  270. struct ieee80211_work *wk;
  271. wk = kzalloc(sizeof(*wk), GFP_KERNEL);
  272. if (!wk)
  273. return -ENOMEM;
  274. wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL;
  275. wk->chan = chan;
  276. wk->chan_type = channel_type;
  277. wk->sdata = sdata;
  278. wk->done = ieee80211_remain_done;
  279. wk->remain.duration = duration;
  280. *cookie = (unsigned long) wk;
  281. ieee80211_add_work(wk);
  282. return 0;
  283. }
  284. int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
  285. u64 cookie)
  286. {
  287. struct ieee80211_local *local = sdata->local;
  288. struct ieee80211_work *wk, *tmp;
  289. bool found = false;
  290. mutex_lock(&local->mtx);
  291. list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
  292. if ((unsigned long) wk == cookie) {
  293. wk->timeout = jiffies;
  294. found = true;
  295. break;
  296. }
  297. }
  298. mutex_unlock(&local->mtx);
  299. if (!found)
  300. return -ENOENT;
  301. ieee80211_queue_work(&local->hw, &local->work_work);
  302. return 0;
  303. }