rsv.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. /*
  2. * UWB reservation management.
  3. *
  4. * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License version
  8. * 2 as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <linux/version.h>
  19. #include <linux/kernel.h>
  20. #include <linux/uwb.h>
  21. #include "uwb-internal.h"
  22. static void uwb_rsv_timer(unsigned long arg);
  23. static const char *rsv_states[] = {
  24. [UWB_RSV_STATE_NONE] = "none",
  25. [UWB_RSV_STATE_O_INITIATED] = "initiated",
  26. [UWB_RSV_STATE_O_PENDING] = "pending",
  27. [UWB_RSV_STATE_O_MODIFIED] = "modified",
  28. [UWB_RSV_STATE_O_ESTABLISHED] = "established",
  29. [UWB_RSV_STATE_T_ACCEPTED] = "accepted",
  30. [UWB_RSV_STATE_T_DENIED] = "denied",
  31. [UWB_RSV_STATE_T_PENDING] = "pending",
  32. };
  33. static const char *rsv_types[] = {
  34. [UWB_DRP_TYPE_ALIEN_BP] = "alien-bp",
  35. [UWB_DRP_TYPE_HARD] = "hard",
  36. [UWB_DRP_TYPE_SOFT] = "soft",
  37. [UWB_DRP_TYPE_PRIVATE] = "private",
  38. [UWB_DRP_TYPE_PCA] = "pca",
  39. };
  40. /**
  41. * uwb_rsv_state_str - return a string for a reservation state
  42. * @state: the reservation state.
  43. */
  44. const char *uwb_rsv_state_str(enum uwb_rsv_state state)
  45. {
  46. if (state < UWB_RSV_STATE_NONE || state >= UWB_RSV_STATE_LAST)
  47. return "unknown";
  48. return rsv_states[state];
  49. }
  50. EXPORT_SYMBOL_GPL(uwb_rsv_state_str);
  51. /**
  52. * uwb_rsv_type_str - return a string for a reservation type
  53. * @type: the reservation type
  54. */
  55. const char *uwb_rsv_type_str(enum uwb_drp_type type)
  56. {
  57. if (type < UWB_DRP_TYPE_ALIEN_BP || type > UWB_DRP_TYPE_PCA)
  58. return "invalid";
  59. return rsv_types[type];
  60. }
  61. EXPORT_SYMBOL_GPL(uwb_rsv_type_str);
  62. static void uwb_rsv_dump(struct uwb_rsv *rsv)
  63. {
  64. struct device *dev = &rsv->rc->uwb_dev.dev;
  65. struct uwb_dev_addr devaddr;
  66. char owner[UWB_ADDR_STRSIZE], target[UWB_ADDR_STRSIZE];
  67. uwb_dev_addr_print(owner, sizeof(owner), &rsv->owner->dev_addr);
  68. if (rsv->target.type == UWB_RSV_TARGET_DEV)
  69. devaddr = rsv->target.dev->dev_addr;
  70. else
  71. devaddr = rsv->target.devaddr;
  72. uwb_dev_addr_print(target, sizeof(target), &devaddr);
  73. dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state));
  74. }
  75. static void uwb_rsv_release(struct kref *kref)
  76. {
  77. struct uwb_rsv *rsv = container_of(kref, struct uwb_rsv, kref);
  78. kfree(rsv);
  79. }
  80. static void uwb_rsv_get(struct uwb_rsv *rsv)
  81. {
  82. kref_get(&rsv->kref);
  83. }
  84. static void uwb_rsv_put(struct uwb_rsv *rsv)
  85. {
  86. kref_put(&rsv->kref, uwb_rsv_release);
  87. }
  88. /*
  89. * Get a free stream index for a reservation.
  90. *
  91. * If the target is a DevAddr (e.g., a WUSB cluster reservation) then
  92. * the stream is allocated from a pool of per-RC stream indexes,
  93. * otherwise a unique stream index for the target is selected.
  94. */
  95. static int uwb_rsv_get_stream(struct uwb_rsv *rsv)
  96. {
  97. struct uwb_rc *rc = rsv->rc;
  98. unsigned long *streams_bm;
  99. int stream;
  100. switch (rsv->target.type) {
  101. case UWB_RSV_TARGET_DEV:
  102. streams_bm = rsv->target.dev->streams;
  103. break;
  104. case UWB_RSV_TARGET_DEVADDR:
  105. streams_bm = rc->uwb_dev.streams;
  106. break;
  107. default:
  108. return -EINVAL;
  109. }
  110. stream = find_first_zero_bit(streams_bm, UWB_NUM_STREAMS);
  111. if (stream >= UWB_NUM_STREAMS)
  112. return -EBUSY;
  113. rsv->stream = stream;
  114. set_bit(stream, streams_bm);
  115. return 0;
  116. }
  117. static void uwb_rsv_put_stream(struct uwb_rsv *rsv)
  118. {
  119. struct uwb_rc *rc = rsv->rc;
  120. unsigned long *streams_bm;
  121. switch (rsv->target.type) {
  122. case UWB_RSV_TARGET_DEV:
  123. streams_bm = rsv->target.dev->streams;
  124. break;
  125. case UWB_RSV_TARGET_DEVADDR:
  126. streams_bm = rc->uwb_dev.streams;
  127. break;
  128. default:
  129. return;
  130. }
  131. clear_bit(rsv->stream, streams_bm);
  132. }
  133. /*
  134. * Generate a MAS allocation with a single row component.
  135. */
  136. static void uwb_rsv_gen_alloc_row(struct uwb_mas_bm *mas,
  137. int first_mas, int mas_per_zone,
  138. int zs, int ze)
  139. {
  140. struct uwb_mas_bm col;
  141. int z;
  142. bitmap_zero(mas->bm, UWB_NUM_MAS);
  143. bitmap_zero(col.bm, UWB_NUM_MAS);
  144. bitmap_fill(col.bm, mas_per_zone);
  145. bitmap_shift_left(col.bm, col.bm, first_mas + zs * UWB_MAS_PER_ZONE, UWB_NUM_MAS);
  146. for (z = zs; z <= ze; z++) {
  147. bitmap_or(mas->bm, mas->bm, col.bm, UWB_NUM_MAS);
  148. bitmap_shift_left(col.bm, col.bm, UWB_MAS_PER_ZONE, UWB_NUM_MAS);
  149. }
  150. }
  151. /*
  152. * Allocate some MAS for this reservation based on current local
  153. * availability, the reservation parameters (max_mas, min_mas,
  154. * sparsity), and the WiMedia rules for MAS allocations.
  155. *
  156. * Returns -EBUSY is insufficient free MAS are available.
  157. *
  158. * FIXME: to simplify this, only safe reservations with a single row
  159. * component in zones 1 to 15 are tried (zone 0 is skipped to avoid
  160. * problems with the MAS reserved for the BP).
  161. *
  162. * [ECMA-368] section B.2.
  163. */
  164. static int uwb_rsv_alloc_mas(struct uwb_rsv *rsv)
  165. {
  166. static const int safe_mas_in_row[UWB_NUM_ZONES] = {
  167. 8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1,
  168. };
  169. int n, r;
  170. struct uwb_mas_bm mas;
  171. bool found = false;
  172. /*
  173. * Search all valid safe allocations until either: too few MAS
  174. * are available; or the smallest allocation with sufficient
  175. * MAS is found.
  176. *
  177. * The top of the zones are preferred, so space for larger
  178. * allocations is available in the bottom of the zone (e.g., a
  179. * 15 MAS allocation should start in row 14 leaving space for
  180. * a 120 MAS allocation at row 0).
  181. */
  182. for (n = safe_mas_in_row[0]; n >= 1; n--) {
  183. int num_mas;
  184. num_mas = n * (UWB_NUM_ZONES - 1);
  185. if (num_mas < rsv->min_mas)
  186. break;
  187. if (found && num_mas < rsv->max_mas)
  188. break;
  189. for (r = UWB_MAS_PER_ZONE-1; r >= 0; r--) {
  190. if (safe_mas_in_row[r] < n)
  191. continue;
  192. uwb_rsv_gen_alloc_row(&mas, r, n, 1, UWB_NUM_ZONES);
  193. if (uwb_drp_avail_reserve_pending(rsv->rc, &mas) == 0) {
  194. found = true;
  195. break;
  196. }
  197. }
  198. }
  199. if (!found)
  200. return -EBUSY;
  201. bitmap_copy(rsv->mas.bm, mas.bm, UWB_NUM_MAS);
  202. return 0;
  203. }
  204. static void uwb_rsv_stroke_timer(struct uwb_rsv *rsv)
  205. {
  206. int sframes = UWB_MAX_LOST_BEACONS;
  207. /*
  208. * Multicast reservations can become established within 1
  209. * super frame and should not be terminated if no response is
  210. * received.
  211. */
  212. if (rsv->is_multicast) {
  213. if (rsv->state == UWB_RSV_STATE_O_INITIATED)
  214. sframes = 1;
  215. if (rsv->state == UWB_RSV_STATE_O_ESTABLISHED)
  216. sframes = 0;
  217. }
  218. rsv->expired = false;
  219. if (sframes > 0) {
  220. /*
  221. * Add an additional 2 superframes to account for the
  222. * time to send the SET DRP IE command.
  223. */
  224. unsigned timeout_us = (sframes + 2) * UWB_SUPERFRAME_LENGTH_US;
  225. mod_timer(&rsv->timer, jiffies + usecs_to_jiffies(timeout_us));
  226. } else
  227. del_timer(&rsv->timer);
  228. }
  229. /*
  230. * Update a reservations state, and schedule an update of the
  231. * transmitted DRP IEs.
  232. */
  233. static void uwb_rsv_state_update(struct uwb_rsv *rsv,
  234. enum uwb_rsv_state new_state)
  235. {
  236. rsv->state = new_state;
  237. rsv->ie_valid = false;
  238. uwb_rsv_dump(rsv);
  239. uwb_rsv_stroke_timer(rsv);
  240. uwb_rsv_sched_update(rsv->rc);
  241. }
  242. static void uwb_rsv_callback(struct uwb_rsv *rsv)
  243. {
  244. if (rsv->callback)
  245. rsv->callback(rsv);
  246. }
  247. void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state)
  248. {
  249. if (rsv->state == new_state) {
  250. switch (rsv->state) {
  251. case UWB_RSV_STATE_O_ESTABLISHED:
  252. case UWB_RSV_STATE_T_ACCEPTED:
  253. case UWB_RSV_STATE_NONE:
  254. uwb_rsv_stroke_timer(rsv);
  255. break;
  256. default:
  257. /* Expecting a state transition so leave timer
  258. as-is. */
  259. break;
  260. }
  261. return;
  262. }
  263. switch (new_state) {
  264. case UWB_RSV_STATE_NONE:
  265. uwb_drp_avail_release(rsv->rc, &rsv->mas);
  266. if (uwb_rsv_is_owner(rsv))
  267. uwb_rsv_put_stream(rsv);
  268. uwb_rsv_state_update(rsv, UWB_RSV_STATE_NONE);
  269. uwb_rsv_callback(rsv);
  270. break;
  271. case UWB_RSV_STATE_O_INITIATED:
  272. uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_INITIATED);
  273. break;
  274. case UWB_RSV_STATE_O_PENDING:
  275. uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_PENDING);
  276. break;
  277. case UWB_RSV_STATE_O_ESTABLISHED:
  278. uwb_drp_avail_reserve(rsv->rc, &rsv->mas);
  279. uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_ESTABLISHED);
  280. uwb_rsv_callback(rsv);
  281. break;
  282. case UWB_RSV_STATE_T_ACCEPTED:
  283. uwb_drp_avail_reserve(rsv->rc, &rsv->mas);
  284. uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_ACCEPTED);
  285. uwb_rsv_callback(rsv);
  286. break;
  287. case UWB_RSV_STATE_T_DENIED:
  288. uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_DENIED);
  289. break;
  290. default:
  291. dev_err(&rsv->rc->uwb_dev.dev, "unhandled state: %s (%d)\n",
  292. uwb_rsv_state_str(new_state), new_state);
  293. }
  294. }
  295. static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc)
  296. {
  297. struct uwb_rsv *rsv;
  298. rsv = kzalloc(sizeof(struct uwb_rsv), GFP_KERNEL);
  299. if (!rsv)
  300. return NULL;
  301. INIT_LIST_HEAD(&rsv->rc_node);
  302. INIT_LIST_HEAD(&rsv->pal_node);
  303. kref_init(&rsv->kref);
  304. init_timer(&rsv->timer);
  305. rsv->timer.function = uwb_rsv_timer;
  306. rsv->timer.data = (unsigned long)rsv;
  307. rsv->rc = rc;
  308. return rsv;
  309. }
  310. /**
  311. * uwb_rsv_create - allocate and initialize a UWB reservation structure
  312. * @rc: the radio controller
  313. * @cb: callback to use when the reservation completes or terminates
  314. * @pal_priv: data private to the PAL to be passed in the callback
  315. *
  316. * The callback is called when the state of the reservation changes from:
  317. *
  318. * - pending to accepted
  319. * - pending to denined
  320. * - accepted to terminated
  321. * - pending to terminated
  322. */
  323. struct uwb_rsv *uwb_rsv_create(struct uwb_rc *rc, uwb_rsv_cb_f cb, void *pal_priv)
  324. {
  325. struct uwb_rsv *rsv;
  326. rsv = uwb_rsv_alloc(rc);
  327. if (!rsv)
  328. return NULL;
  329. rsv->callback = cb;
  330. rsv->pal_priv = pal_priv;
  331. return rsv;
  332. }
  333. EXPORT_SYMBOL_GPL(uwb_rsv_create);
  334. void uwb_rsv_remove(struct uwb_rsv *rsv)
  335. {
  336. if (rsv->state != UWB_RSV_STATE_NONE)
  337. uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
  338. del_timer_sync(&rsv->timer);
  339. uwb_dev_put(rsv->owner);
  340. if (rsv->target.type == UWB_RSV_TARGET_DEV)
  341. uwb_dev_put(rsv->target.dev);
  342. list_del_init(&rsv->rc_node);
  343. uwb_rsv_put(rsv);
  344. }
  345. /**
  346. * uwb_rsv_destroy - free a UWB reservation structure
  347. * @rsv: the reservation to free
  348. *
  349. * The reservation must already be terminated.
  350. */
  351. void uwb_rsv_destroy(struct uwb_rsv *rsv)
  352. {
  353. uwb_rsv_put(rsv);
  354. }
  355. EXPORT_SYMBOL_GPL(uwb_rsv_destroy);
  356. /**
  357. * usb_rsv_establish - start a reservation establishment
  358. * @rsv: the reservation
  359. *
  360. * The PAL should fill in @rsv's owner, target, type, max_mas,
  361. * min_mas, sparsity and is_multicast fields. If the target is a
  362. * uwb_dev it must be referenced.
  363. *
  364. * The reservation's callback will be called when the reservation is
  365. * accepted, denied or times out.
  366. */
  367. int uwb_rsv_establish(struct uwb_rsv *rsv)
  368. {
  369. struct uwb_rc *rc = rsv->rc;
  370. int ret;
  371. mutex_lock(&rc->rsvs_mutex);
  372. ret = uwb_rsv_get_stream(rsv);
  373. if (ret)
  374. goto out;
  375. ret = uwb_rsv_alloc_mas(rsv);
  376. if (ret) {
  377. uwb_rsv_put_stream(rsv);
  378. goto out;
  379. }
  380. uwb_rsv_get(rsv);
  381. list_add_tail(&rsv->rc_node, &rc->reservations);
  382. rsv->owner = &rc->uwb_dev;
  383. uwb_dev_get(rsv->owner);
  384. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_INITIATED);
  385. out:
  386. mutex_unlock(&rc->rsvs_mutex);
  387. return ret;
  388. }
  389. EXPORT_SYMBOL_GPL(uwb_rsv_establish);
  390. /**
  391. * uwb_rsv_modify - modify an already established reservation
  392. * @rsv: the reservation to modify
  393. * @max_mas: new maximum MAS to reserve
  394. * @min_mas: new minimum MAS to reserve
  395. * @sparsity: new sparsity to use
  396. *
  397. * FIXME: implement this once there are PALs that use it.
  398. */
  399. int uwb_rsv_modify(struct uwb_rsv *rsv, int max_mas, int min_mas, int sparsity)
  400. {
  401. return -ENOSYS;
  402. }
  403. EXPORT_SYMBOL_GPL(uwb_rsv_modify);
  404. /**
  405. * uwb_rsv_terminate - terminate an established reservation
  406. * @rsv: the reservation to terminate
  407. *
  408. * A reservation is terminated by removing the DRP IE from the beacon,
  409. * the other end will consider the reservation to be terminated when
  410. * it does not see the DRP IE for at least mMaxLostBeacons.
  411. *
  412. * If applicable, the reference to the target uwb_dev will be released.
  413. */
  414. void uwb_rsv_terminate(struct uwb_rsv *rsv)
  415. {
  416. struct uwb_rc *rc = rsv->rc;
  417. mutex_lock(&rc->rsvs_mutex);
  418. uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
  419. mutex_unlock(&rc->rsvs_mutex);
  420. }
  421. EXPORT_SYMBOL_GPL(uwb_rsv_terminate);
  422. /**
  423. * uwb_rsv_accept - accept a new reservation from a peer
  424. * @rsv: the reservation
  425. * @cb: call back for reservation changes
  426. * @pal_priv: data to be passed in the above call back
  427. *
  428. * Reservation requests from peers are denied unless a PAL accepts it
  429. * by calling this function.
  430. *
  431. * The PAL call uwb_rsv_destroy() for all accepted reservations before
  432. * calling uwb_pal_unregister().
  433. */
  434. void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv)
  435. {
  436. uwb_rsv_get(rsv);
  437. rsv->callback = cb;
  438. rsv->pal_priv = pal_priv;
  439. rsv->state = UWB_RSV_STATE_T_ACCEPTED;
  440. }
  441. EXPORT_SYMBOL_GPL(uwb_rsv_accept);
  442. /*
  443. * Is a received DRP IE for this reservation?
  444. */
  445. static bool uwb_rsv_match(struct uwb_rsv *rsv, struct uwb_dev *src,
  446. struct uwb_ie_drp *drp_ie)
  447. {
  448. struct uwb_dev_addr *rsv_src;
  449. int stream;
  450. stream = uwb_ie_drp_stream_index(drp_ie);
  451. if (rsv->stream != stream)
  452. return false;
  453. switch (rsv->target.type) {
  454. case UWB_RSV_TARGET_DEVADDR:
  455. return rsv->stream == stream;
  456. case UWB_RSV_TARGET_DEV:
  457. if (uwb_ie_drp_owner(drp_ie))
  458. rsv_src = &rsv->owner->dev_addr;
  459. else
  460. rsv_src = &rsv->target.dev->dev_addr;
  461. return uwb_dev_addr_cmp(&src->dev_addr, rsv_src) == 0;
  462. }
  463. return false;
  464. }
  465. static struct uwb_rsv *uwb_rsv_new_target(struct uwb_rc *rc,
  466. struct uwb_dev *src,
  467. struct uwb_ie_drp *drp_ie)
  468. {
  469. struct uwb_rsv *rsv;
  470. struct uwb_pal *pal;
  471. enum uwb_rsv_state state;
  472. rsv = uwb_rsv_alloc(rc);
  473. if (!rsv)
  474. return NULL;
  475. rsv->rc = rc;
  476. rsv->owner = src;
  477. uwb_dev_get(rsv->owner);
  478. rsv->target.type = UWB_RSV_TARGET_DEV;
  479. rsv->target.dev = &rc->uwb_dev;
  480. rsv->type = uwb_ie_drp_type(drp_ie);
  481. rsv->stream = uwb_ie_drp_stream_index(drp_ie);
  482. uwb_drp_ie_to_bm(&rsv->mas, drp_ie);
  483. /*
  484. * See if any PALs are interested in this reservation. If not,
  485. * deny the request.
  486. */
  487. rsv->state = UWB_RSV_STATE_T_DENIED;
  488. spin_lock(&rc->pal_lock);
  489. list_for_each_entry(pal, &rc->pals, node) {
  490. if (pal->new_rsv)
  491. pal->new_rsv(rsv);
  492. if (rsv->state == UWB_RSV_STATE_T_ACCEPTED)
  493. break;
  494. }
  495. spin_unlock(&rc->pal_lock);
  496. list_add_tail(&rsv->rc_node, &rc->reservations);
  497. state = rsv->state;
  498. rsv->state = UWB_RSV_STATE_NONE;
  499. uwb_rsv_set_state(rsv, state);
  500. return rsv;
  501. }
  502. /**
  503. * uwb_rsv_find - find a reservation for a received DRP IE.
  504. * @rc: the radio controller
  505. * @src: source of the DRP IE
  506. * @drp_ie: the DRP IE
  507. *
  508. * If the reservation cannot be found and the DRP IE is from a peer
  509. * attempting to establish a new reservation, create a new reservation
  510. * and add it to the list.
  511. */
  512. struct uwb_rsv *uwb_rsv_find(struct uwb_rc *rc, struct uwb_dev *src,
  513. struct uwb_ie_drp *drp_ie)
  514. {
  515. struct uwb_rsv *rsv;
  516. list_for_each_entry(rsv, &rc->reservations, rc_node) {
  517. if (uwb_rsv_match(rsv, src, drp_ie))
  518. return rsv;
  519. }
  520. if (uwb_ie_drp_owner(drp_ie))
  521. return uwb_rsv_new_target(rc, src, drp_ie);
  522. return NULL;
  523. }
  524. /*
  525. * Go through all the reservations and check for timeouts and (if
  526. * necessary) update their DRP IEs.
  527. *
  528. * FIXME: look at building the SET_DRP_IE command here rather than
  529. * having to rescan the list in uwb_rc_send_all_drp_ie().
  530. */
  531. static bool uwb_rsv_update_all(struct uwb_rc *rc)
  532. {
  533. struct uwb_rsv *rsv, *t;
  534. bool ie_updated = false;
  535. list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) {
  536. if (rsv->expired)
  537. uwb_drp_handle_timeout(rsv);
  538. if (!rsv->ie_valid) {
  539. uwb_drp_ie_update(rsv);
  540. ie_updated = true;
  541. }
  542. }
  543. return ie_updated;
  544. }
  545. void uwb_rsv_sched_update(struct uwb_rc *rc)
  546. {
  547. queue_work(rc->rsv_workq, &rc->rsv_update_work);
  548. }
  549. /*
  550. * Update DRP IEs and, if necessary, the DRP Availability IE and send
  551. * the updated IEs to the radio controller.
  552. */
  553. static void uwb_rsv_update_work(struct work_struct *work)
  554. {
  555. struct uwb_rc *rc = container_of(work, struct uwb_rc, rsv_update_work);
  556. bool ie_updated;
  557. mutex_lock(&rc->rsvs_mutex);
  558. ie_updated = uwb_rsv_update_all(rc);
  559. if (!rc->drp_avail.ie_valid) {
  560. uwb_drp_avail_ie_update(rc);
  561. ie_updated = true;
  562. }
  563. if (ie_updated)
  564. uwb_rc_send_all_drp_ie(rc);
  565. mutex_unlock(&rc->rsvs_mutex);
  566. }
  567. static void uwb_rsv_timer(unsigned long arg)
  568. {
  569. struct uwb_rsv *rsv = (struct uwb_rsv *)arg;
  570. rsv->expired = true;
  571. uwb_rsv_sched_update(rsv->rc);
  572. }
  573. void uwb_rsv_init(struct uwb_rc *rc)
  574. {
  575. INIT_LIST_HEAD(&rc->reservations);
  576. mutex_init(&rc->rsvs_mutex);
  577. INIT_WORK(&rc->rsv_update_work, uwb_rsv_update_work);
  578. bitmap_complement(rc->uwb_dev.streams, rc->uwb_dev.streams, UWB_NUM_STREAMS);
  579. }
  580. int uwb_rsv_setup(struct uwb_rc *rc)
  581. {
  582. char name[16];
  583. snprintf(name, sizeof(name), "%s_rsvd", dev_name(&rc->uwb_dev.dev));
  584. rc->rsv_workq = create_singlethread_workqueue(name);
  585. if (rc->rsv_workq == NULL)
  586. return -ENOMEM;
  587. return 0;
  588. }
  589. void uwb_rsv_cleanup(struct uwb_rc *rc)
  590. {
  591. struct uwb_rsv *rsv, *t;
  592. mutex_lock(&rc->rsvs_mutex);
  593. list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) {
  594. uwb_rsv_remove(rsv);
  595. }
  596. mutex_unlock(&rc->rsvs_mutex);
  597. cancel_work_sync(&rc->rsv_update_work);
  598. destroy_workqueue(rc->rsv_workq);
  599. }