drp.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. /*
  2. * Ultra Wide Band
  3. * Dynamic Reservation Protocol handling
  4. *
  5. * Copyright (C) 2005-2006 Intel Corporation
  6. * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
  7. * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License version
  11. * 2 as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include <linux/kthread.h>
  22. #include <linux/freezer.h>
  23. #include <linux/slab.h>
  24. #include <linux/delay.h>
  25. #include "uwb-internal.h"
  26. /* DRP Conflict Actions ([ECMA-368 2nd Edition] 17.4.6) */
  27. enum uwb_drp_conflict_action {
  28. /* Reservation is maintained, no action needed */
  29. UWB_DRP_CONFLICT_MANTAIN = 0,
  30. /* the device shall not transmit frames in conflicting MASs in
  31. * the following superframe. If the device is the reservation
  32. * target, it shall also set the Reason Code in its DRP IE to
  33. * Conflict in its beacon in the following superframe.
  34. */
  35. UWB_DRP_CONFLICT_ACT1,
  36. /* the device shall not set the Reservation Status bit to ONE
  37. * and shall not transmit frames in conflicting MASs. If the
  38. * device is the reservation target, it shall also set the
  39. * Reason Code in its DRP IE to Conflict.
  40. */
  41. UWB_DRP_CONFLICT_ACT2,
  42. /* the device shall not transmit frames in conflicting MASs in
  43. * the following superframe. It shall remove the conflicting
  44. * MASs from the reservation or set the Reservation Status to
  45. * ZERO in its beacon in the following superframe. If the
  46. * device is the reservation target, it shall also set the
  47. * Reason Code in its DRP IE to Conflict.
  48. */
  49. UWB_DRP_CONFLICT_ACT3,
  50. };
  51. static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg,
  52. struct uwb_rceb *reply, ssize_t reply_size)
  53. {
  54. struct uwb_rc_evt_set_drp_ie *r = (struct uwb_rc_evt_set_drp_ie *)reply;
  55. unsigned long flags;
  56. if (r != NULL) {
  57. if (r->bResultCode != UWB_RC_RES_SUCCESS)
  58. dev_err(&rc->uwb_dev.dev, "SET-DRP-IE failed: %s (%d)\n",
  59. uwb_rc_strerror(r->bResultCode), r->bResultCode);
  60. } else
  61. dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n");
  62. spin_lock_irqsave(&rc->rsvs_lock, flags);
  63. if (rc->set_drp_ie_pending > 1) {
  64. rc->set_drp_ie_pending = 0;
  65. uwb_rsv_queue_update(rc);
  66. } else {
  67. rc->set_drp_ie_pending = 0;
  68. }
  69. spin_unlock_irqrestore(&rc->rsvs_lock, flags);
  70. }
  71. /**
  72. * Construct and send the SET DRP IE
  73. *
  74. * @rc: UWB Host controller
  75. * @returns: >= 0 number of bytes still available in the beacon
  76. * < 0 errno code on error.
  77. *
  78. * See WUSB[8.6.2.7]: The host must set all the DRP IEs that it wants the
  79. * device to include in its beacon at the same time. We thus have to
  80. * traverse all reservations and include the DRP IEs of all PENDING
  81. * and NEGOTIATED reservations in a SET DRP command for transmission.
  82. *
  83. * A DRP Availability IE is appended.
  84. *
  85. * rc->rsvs_mutex is held
  86. *
  87. * FIXME We currently ignore the returned value indicating the remaining space
  88. * in beacon. This could be used to deny reservation requests earlier if
  89. * determined that they would cause the beacon space to be exceeded.
  90. */
  91. int uwb_rc_send_all_drp_ie(struct uwb_rc *rc)
  92. {
  93. int result;
  94. struct uwb_rc_cmd_set_drp_ie *cmd;
  95. struct uwb_rsv *rsv;
  96. struct uwb_rsv_move *mv;
  97. int num_bytes = 0;
  98. u8 *IEDataptr;
  99. result = -ENOMEM;
  100. /* First traverse all reservations to determine memory needed. */
  101. list_for_each_entry(rsv, &rc->reservations, rc_node) {
  102. if (rsv->drp_ie != NULL) {
  103. num_bytes += rsv->drp_ie->hdr.length + 2;
  104. if (uwb_rsv_has_two_drp_ies(rsv) &&
  105. (rsv->mv.companion_drp_ie != NULL)) {
  106. mv = &rsv->mv;
  107. num_bytes +=
  108. mv->companion_drp_ie->hdr.length + 2;
  109. }
  110. }
  111. }
  112. num_bytes += sizeof(rc->drp_avail.ie);
  113. cmd = kzalloc(sizeof(*cmd) + num_bytes, GFP_KERNEL);
  114. if (cmd == NULL)
  115. goto error;
  116. cmd->rccb.bCommandType = UWB_RC_CET_GENERAL;
  117. cmd->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SET_DRP_IE);
  118. cmd->wIELength = num_bytes;
  119. IEDataptr = (u8 *)&cmd->IEData[0];
  120. /* FIXME: DRV avail IE is not always needed */
  121. /* put DRP avail IE first */
  122. memcpy(IEDataptr, &rc->drp_avail.ie, sizeof(rc->drp_avail.ie));
  123. IEDataptr += sizeof(struct uwb_ie_drp_avail);
  124. /* Next traverse all reservations to place IEs in allocated memory. */
  125. list_for_each_entry(rsv, &rc->reservations, rc_node) {
  126. if (rsv->drp_ie != NULL) {
  127. memcpy(IEDataptr, rsv->drp_ie,
  128. rsv->drp_ie->hdr.length + 2);
  129. IEDataptr += rsv->drp_ie->hdr.length + 2;
  130. if (uwb_rsv_has_two_drp_ies(rsv) &&
  131. (rsv->mv.companion_drp_ie != NULL)) {
  132. mv = &rsv->mv;
  133. memcpy(IEDataptr, mv->companion_drp_ie,
  134. mv->companion_drp_ie->hdr.length + 2);
  135. IEDataptr +=
  136. mv->companion_drp_ie->hdr.length + 2;
  137. }
  138. }
  139. }
  140. result = uwb_rc_cmd_async(rc, "SET-DRP-IE",
  141. &cmd->rccb, sizeof(*cmd) + num_bytes,
  142. UWB_RC_CET_GENERAL, UWB_RC_CMD_SET_DRP_IE,
  143. uwb_rc_set_drp_cmd_done, NULL);
  144. rc->set_drp_ie_pending = 1;
  145. kfree(cmd);
  146. error:
  147. return result;
  148. }
  149. /*
  150. * Evaluate the action to perform using conflict resolution rules
  151. *
  152. * Return a uwb_drp_conflict_action.
  153. */
  154. static int evaluate_conflict_action(struct uwb_ie_drp *ext_drp_ie, int ext_beacon_slot,
  155. struct uwb_rsv *rsv, int our_status)
  156. {
  157. int our_tie_breaker = rsv->tiebreaker;
  158. int our_type = rsv->type;
  159. int our_beacon_slot = rsv->rc->uwb_dev.beacon_slot;
  160. int ext_tie_breaker = uwb_ie_drp_tiebreaker(ext_drp_ie);
  161. int ext_status = uwb_ie_drp_status(ext_drp_ie);
  162. int ext_type = uwb_ie_drp_type(ext_drp_ie);
  163. /* [ECMA-368 2nd Edition] 17.4.6 */
  164. if (ext_type == UWB_DRP_TYPE_PCA && our_type == UWB_DRP_TYPE_PCA) {
  165. return UWB_DRP_CONFLICT_MANTAIN;
  166. }
  167. /* [ECMA-368 2nd Edition] 17.4.6-1 */
  168. if (our_type == UWB_DRP_TYPE_ALIEN_BP) {
  169. return UWB_DRP_CONFLICT_MANTAIN;
  170. }
  171. /* [ECMA-368 2nd Edition] 17.4.6-2 */
  172. if (ext_type == UWB_DRP_TYPE_ALIEN_BP) {
  173. /* here we know our_type != UWB_DRP_TYPE_ALIEN_BP */
  174. return UWB_DRP_CONFLICT_ACT1;
  175. }
  176. /* [ECMA-368 2nd Edition] 17.4.6-3 */
  177. if (our_status == 0 && ext_status == 1) {
  178. return UWB_DRP_CONFLICT_ACT2;
  179. }
  180. /* [ECMA-368 2nd Edition] 17.4.6-4 */
  181. if (our_status == 1 && ext_status == 0) {
  182. return UWB_DRP_CONFLICT_MANTAIN;
  183. }
  184. /* [ECMA-368 2nd Edition] 17.4.6-5a */
  185. if (our_tie_breaker == ext_tie_breaker &&
  186. our_beacon_slot < ext_beacon_slot) {
  187. return UWB_DRP_CONFLICT_MANTAIN;
  188. }
  189. /* [ECMA-368 2nd Edition] 17.4.6-5b */
  190. if (our_tie_breaker != ext_tie_breaker &&
  191. our_beacon_slot > ext_beacon_slot) {
  192. return UWB_DRP_CONFLICT_MANTAIN;
  193. }
  194. if (our_status == 0) {
  195. if (our_tie_breaker == ext_tie_breaker) {
  196. /* [ECMA-368 2nd Edition] 17.4.6-6a */
  197. if (our_beacon_slot > ext_beacon_slot) {
  198. return UWB_DRP_CONFLICT_ACT2;
  199. }
  200. } else {
  201. /* [ECMA-368 2nd Edition] 17.4.6-6b */
  202. if (our_beacon_slot < ext_beacon_slot) {
  203. return UWB_DRP_CONFLICT_ACT2;
  204. }
  205. }
  206. } else {
  207. if (our_tie_breaker == ext_tie_breaker) {
  208. /* [ECMA-368 2nd Edition] 17.4.6-7a */
  209. if (our_beacon_slot > ext_beacon_slot) {
  210. return UWB_DRP_CONFLICT_ACT3;
  211. }
  212. } else {
  213. /* [ECMA-368 2nd Edition] 17.4.6-7b */
  214. if (our_beacon_slot < ext_beacon_slot) {
  215. return UWB_DRP_CONFLICT_ACT3;
  216. }
  217. }
  218. }
  219. return UWB_DRP_CONFLICT_MANTAIN;
  220. }
  221. static void handle_conflict_normal(struct uwb_ie_drp *drp_ie,
  222. int ext_beacon_slot,
  223. struct uwb_rsv *rsv,
  224. struct uwb_mas_bm *conflicting_mas)
  225. {
  226. struct uwb_rc *rc = rsv->rc;
  227. struct uwb_rsv_move *mv = &rsv->mv;
  228. struct uwb_drp_backoff_win *bow = &rc->bow;
  229. int action;
  230. action = evaluate_conflict_action(drp_ie, ext_beacon_slot, rsv, uwb_rsv_status(rsv));
  231. if (uwb_rsv_is_owner(rsv)) {
  232. switch(action) {
  233. case UWB_DRP_CONFLICT_ACT2:
  234. /* try move */
  235. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_TO_BE_MOVED);
  236. if (bow->can_reserve_extra_mases == false)
  237. uwb_rsv_backoff_win_increment(rc);
  238. break;
  239. case UWB_DRP_CONFLICT_ACT3:
  240. uwb_rsv_backoff_win_increment(rc);
  241. /* drop some mases with reason modified */
  242. /* put in the companion the mases to be dropped */
  243. bitmap_and(mv->companion_mas.bm, rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS);
  244. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED);
  245. default:
  246. break;
  247. }
  248. } else {
  249. switch(action) {
  250. case UWB_DRP_CONFLICT_ACT2:
  251. case UWB_DRP_CONFLICT_ACT3:
  252. uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT);
  253. default:
  254. break;
  255. }
  256. }
  257. }
  258. static void handle_conflict_expanding(struct uwb_ie_drp *drp_ie, int ext_beacon_slot,
  259. struct uwb_rsv *rsv, bool companion_only,
  260. struct uwb_mas_bm *conflicting_mas)
  261. {
  262. struct uwb_rc *rc = rsv->rc;
  263. struct uwb_drp_backoff_win *bow = &rc->bow;
  264. struct uwb_rsv_move *mv = &rsv->mv;
  265. int action;
  266. if (companion_only) {
  267. /* status of companion is 0 at this point */
  268. action = evaluate_conflict_action(drp_ie, ext_beacon_slot, rsv, 0);
  269. if (uwb_rsv_is_owner(rsv)) {
  270. switch(action) {
  271. case UWB_DRP_CONFLICT_ACT2:
  272. case UWB_DRP_CONFLICT_ACT3:
  273. uwb_rsv_set_state(rsv,
  274. UWB_RSV_STATE_O_ESTABLISHED);
  275. rsv->needs_release_companion_mas = false;
  276. if (bow->can_reserve_extra_mases == false)
  277. uwb_rsv_backoff_win_increment(rc);
  278. uwb_drp_avail_release(rsv->rc,
  279. &rsv->mv.companion_mas);
  280. }
  281. } else { /* rsv is target */
  282. switch(action) {
  283. case UWB_DRP_CONFLICT_ACT2:
  284. case UWB_DRP_CONFLICT_ACT3:
  285. uwb_rsv_set_state(rsv,
  286. UWB_RSV_STATE_T_EXPANDING_CONFLICT);
  287. /* send_drp_avail_ie = true; */
  288. }
  289. }
  290. } else { /* also base part of the reservation is conflicting */
  291. if (uwb_rsv_is_owner(rsv)) {
  292. uwb_rsv_backoff_win_increment(rc);
  293. /* remove companion part */
  294. uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas);
  295. /* drop some mases with reason modified */
  296. /* put in the companion the mases to be dropped */
  297. bitmap_andnot(mv->companion_mas.bm, rsv->mas.bm,
  298. conflicting_mas->bm, UWB_NUM_MAS);
  299. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED);
  300. } else { /* it is a target rsv */
  301. uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT);
  302. /* send_drp_avail_ie = true; */
  303. }
  304. }
  305. }
  306. static void uwb_drp_handle_conflict_rsv(struct uwb_rc *rc, struct uwb_rsv *rsv,
  307. struct uwb_rc_evt_drp *drp_evt,
  308. struct uwb_ie_drp *drp_ie,
  309. struct uwb_mas_bm *conflicting_mas)
  310. {
  311. struct uwb_rsv_move *mv;
  312. /* check if the conflicting reservation has two drp_ies */
  313. if (uwb_rsv_has_two_drp_ies(rsv)) {
  314. mv = &rsv->mv;
  315. if (bitmap_intersects(rsv->mas.bm, conflicting_mas->bm,
  316. UWB_NUM_MAS)) {
  317. handle_conflict_expanding(drp_ie,
  318. drp_evt->beacon_slot_number,
  319. rsv, false, conflicting_mas);
  320. } else {
  321. if (bitmap_intersects(mv->companion_mas.bm,
  322. conflicting_mas->bm, UWB_NUM_MAS)) {
  323. handle_conflict_expanding(
  324. drp_ie, drp_evt->beacon_slot_number,
  325. rsv, true, conflicting_mas);
  326. }
  327. }
  328. } else if (bitmap_intersects(rsv->mas.bm, conflicting_mas->bm,
  329. UWB_NUM_MAS)) {
  330. handle_conflict_normal(drp_ie, drp_evt->beacon_slot_number,
  331. rsv, conflicting_mas);
  332. }
  333. }
  334. static void uwb_drp_handle_all_conflict_rsv(struct uwb_rc *rc,
  335. struct uwb_rc_evt_drp *drp_evt,
  336. struct uwb_ie_drp *drp_ie,
  337. struct uwb_mas_bm *conflicting_mas)
  338. {
  339. struct uwb_rsv *rsv;
  340. list_for_each_entry(rsv, &rc->reservations, rc_node) {
  341. uwb_drp_handle_conflict_rsv(rc, rsv, drp_evt, drp_ie,
  342. conflicting_mas);
  343. }
  344. }
  345. static void uwb_drp_process_target_accepted(struct uwb_rc *rc,
  346. struct uwb_rsv *rsv, struct uwb_rc_evt_drp *drp_evt,
  347. struct uwb_ie_drp *drp_ie, struct uwb_mas_bm *mas)
  348. {
  349. struct uwb_rsv_move *mv = &rsv->mv;
  350. int status;
  351. status = uwb_ie_drp_status(drp_ie);
  352. if (rsv->state == UWB_RSV_STATE_T_CONFLICT) {
  353. uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT);
  354. return;
  355. }
  356. if (rsv->state == UWB_RSV_STATE_T_EXPANDING_ACCEPTED) {
  357. /* drp_ie is companion */
  358. if (!bitmap_equal(rsv->mas.bm, mas->bm, UWB_NUM_MAS)) {
  359. /* stroke companion */
  360. uwb_rsv_set_state(rsv,
  361. UWB_RSV_STATE_T_EXPANDING_ACCEPTED);
  362. }
  363. } else {
  364. if (!bitmap_equal(rsv->mas.bm, mas->bm, UWB_NUM_MAS)) {
  365. if (uwb_drp_avail_reserve_pending(rc, mas) == -EBUSY) {
  366. /* FIXME: there is a conflict, find
  367. * the conflicting reservations and
  368. * take a sensible action. Consider
  369. * that in drp_ie there is the
  370. * "neighbour" */
  371. uwb_drp_handle_all_conflict_rsv(rc, drp_evt,
  372. drp_ie, mas);
  373. } else {
  374. /* accept the extra reservation */
  375. bitmap_copy(mv->companion_mas.bm, mas->bm,
  376. UWB_NUM_MAS);
  377. uwb_rsv_set_state(rsv,
  378. UWB_RSV_STATE_T_EXPANDING_ACCEPTED);
  379. }
  380. } else {
  381. if (status) {
  382. uwb_rsv_set_state(rsv,
  383. UWB_RSV_STATE_T_ACCEPTED);
  384. }
  385. }
  386. }
  387. }
  388. /*
  389. * Based on the DRP IE, transition a target reservation to a new
  390. * state.
  391. */
  392. static void uwb_drp_process_target(struct uwb_rc *rc, struct uwb_rsv *rsv,
  393. struct uwb_ie_drp *drp_ie, struct uwb_rc_evt_drp *drp_evt)
  394. {
  395. struct device *dev = &rc->uwb_dev.dev;
  396. struct uwb_rsv_move *mv = &rsv->mv;
  397. int status;
  398. enum uwb_drp_reason reason_code;
  399. struct uwb_mas_bm mas;
  400. status = uwb_ie_drp_status(drp_ie);
  401. reason_code = uwb_ie_drp_reason_code(drp_ie);
  402. uwb_drp_ie_to_bm(&mas, drp_ie);
  403. switch (reason_code) {
  404. case UWB_DRP_REASON_ACCEPTED:
  405. uwb_drp_process_target_accepted(rc, rsv, drp_evt, drp_ie, &mas);
  406. break;
  407. case UWB_DRP_REASON_MODIFIED:
  408. /* check to see if we have already modified the reservation */
  409. if (bitmap_equal(rsv->mas.bm, mas.bm, UWB_NUM_MAS)) {
  410. uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED);
  411. break;
  412. }
  413. /* find if the owner wants to expand or reduce */
  414. if (bitmap_subset(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) {
  415. /* owner is reducing */
  416. bitmap_andnot(mv->companion_mas.bm, rsv->mas.bm, mas.bm,
  417. UWB_NUM_MAS);
  418. uwb_drp_avail_release(rsv->rc, &mv->companion_mas);
  419. }
  420. bitmap_copy(rsv->mas.bm, mas.bm, UWB_NUM_MAS);
  421. uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_RESIZED);
  422. break;
  423. default:
  424. dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n",
  425. reason_code, status);
  426. }
  427. }
  428. static void uwb_drp_process_owner_accepted(struct uwb_rsv *rsv,
  429. struct uwb_mas_bm *mas)
  430. {
  431. struct uwb_rsv_move *mv = &rsv->mv;
  432. switch (rsv->state) {
  433. case UWB_RSV_STATE_O_PENDING:
  434. case UWB_RSV_STATE_O_INITIATED:
  435. case UWB_RSV_STATE_O_ESTABLISHED:
  436. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED);
  437. break;
  438. case UWB_RSV_STATE_O_MODIFIED:
  439. if (bitmap_equal(mas->bm, rsv->mas.bm, UWB_NUM_MAS))
  440. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED);
  441. else
  442. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED);
  443. break;
  444. case UWB_RSV_STATE_O_MOVE_REDUCING: /* shouldn' t be a problem */
  445. if (bitmap_equal(mas->bm, rsv->mas.bm, UWB_NUM_MAS))
  446. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED);
  447. else
  448. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_REDUCING);
  449. break;
  450. case UWB_RSV_STATE_O_MOVE_EXPANDING:
  451. if (bitmap_equal(mas->bm, mv->companion_mas.bm, UWB_NUM_MAS)) {
  452. /* Companion reservation accepted */
  453. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_COMBINING);
  454. } else {
  455. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_EXPANDING);
  456. }
  457. break;
  458. case UWB_RSV_STATE_O_MOVE_COMBINING:
  459. if (bitmap_equal(mas->bm, rsv->mas.bm, UWB_NUM_MAS))
  460. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_REDUCING);
  461. else
  462. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_COMBINING);
  463. break;
  464. default:
  465. break;
  466. }
  467. }
  468. /*
  469. * Based on the DRP IE, transition an owner reservation to a new
  470. * state.
  471. */
  472. static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv,
  473. struct uwb_dev *src, struct uwb_ie_drp *drp_ie,
  474. struct uwb_rc_evt_drp *drp_evt)
  475. {
  476. struct device *dev = &rc->uwb_dev.dev;
  477. int status;
  478. enum uwb_drp_reason reason_code;
  479. struct uwb_mas_bm mas;
  480. status = uwb_ie_drp_status(drp_ie);
  481. reason_code = uwb_ie_drp_reason_code(drp_ie);
  482. uwb_drp_ie_to_bm(&mas, drp_ie);
  483. if (status) {
  484. switch (reason_code) {
  485. case UWB_DRP_REASON_ACCEPTED:
  486. uwb_drp_process_owner_accepted(rsv, &mas);
  487. break;
  488. default:
  489. dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n",
  490. reason_code, status);
  491. }
  492. } else {
  493. switch (reason_code) {
  494. case UWB_DRP_REASON_PENDING:
  495. uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_PENDING);
  496. break;
  497. case UWB_DRP_REASON_DENIED:
  498. uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
  499. break;
  500. case UWB_DRP_REASON_CONFLICT:
  501. /* resolve the conflict */
  502. bitmap_complement(mas.bm, src->last_availability_bm,
  503. UWB_NUM_MAS);
  504. uwb_drp_handle_conflict_rsv(rc, rsv, drp_evt, drp_ie, &mas);
  505. break;
  506. default:
  507. dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n",
  508. reason_code, status);
  509. }
  510. }
  511. }
  512. static void uwb_cnflt_alien_stroke_timer(struct uwb_cnflt_alien *cnflt)
  513. {
  514. unsigned timeout_us = UWB_MAX_LOST_BEACONS * UWB_SUPERFRAME_LENGTH_US;
  515. mod_timer(&cnflt->timer, jiffies + usecs_to_jiffies(timeout_us));
  516. }
  517. static void uwb_cnflt_update_work(struct work_struct *work)
  518. {
  519. struct uwb_cnflt_alien *cnflt = container_of(work,
  520. struct uwb_cnflt_alien,
  521. cnflt_update_work);
  522. struct uwb_cnflt_alien *c;
  523. struct uwb_rc *rc = cnflt->rc;
  524. unsigned long delay_us = UWB_MAS_LENGTH_US * UWB_MAS_PER_ZONE;
  525. mutex_lock(&rc->rsvs_mutex);
  526. list_del(&cnflt->rc_node);
  527. /* update rc global conflicting alien bitmap */
  528. bitmap_zero(rc->cnflt_alien_bitmap.bm, UWB_NUM_MAS);
  529. list_for_each_entry(c, &rc->cnflt_alien_list, rc_node) {
  530. bitmap_or(rc->cnflt_alien_bitmap.bm, rc->cnflt_alien_bitmap.bm,
  531. c->mas.bm, UWB_NUM_MAS);
  532. }
  533. queue_delayed_work(rc->rsv_workq, &rc->rsv_alien_bp_work,
  534. usecs_to_jiffies(delay_us));
  535. kfree(cnflt);
  536. mutex_unlock(&rc->rsvs_mutex);
  537. }
  538. static void uwb_cnflt_timer(unsigned long arg)
  539. {
  540. struct uwb_cnflt_alien *cnflt = (struct uwb_cnflt_alien *)arg;
  541. queue_work(cnflt->rc->rsv_workq, &cnflt->cnflt_update_work);
  542. }
  543. /*
  544. * We have received an DRP_IE of type Alien BP and we need to make
  545. * sure we do not transmit in conflicting MASs.
  546. */
  547. static void uwb_drp_handle_alien_drp(struct uwb_rc *rc, struct uwb_ie_drp *drp_ie)
  548. {
  549. struct device *dev = &rc->uwb_dev.dev;
  550. struct uwb_mas_bm mas;
  551. struct uwb_cnflt_alien *cnflt;
  552. unsigned long delay_us = UWB_MAS_LENGTH_US * UWB_MAS_PER_ZONE;
  553. uwb_drp_ie_to_bm(&mas, drp_ie);
  554. list_for_each_entry(cnflt, &rc->cnflt_alien_list, rc_node) {
  555. if (bitmap_equal(cnflt->mas.bm, mas.bm, UWB_NUM_MAS)) {
  556. /* Existing alien BP reservation conflicting
  557. * bitmap, just reset the timer */
  558. uwb_cnflt_alien_stroke_timer(cnflt);
  559. return;
  560. }
  561. }
  562. /* New alien BP reservation conflicting bitmap */
  563. /* alloc and initialize new uwb_cnflt_alien */
  564. cnflt = kzalloc(sizeof(struct uwb_cnflt_alien), GFP_KERNEL);
  565. if (!cnflt) {
  566. dev_err(dev, "failed to alloc uwb_cnflt_alien struct\n");
  567. return;
  568. }
  569. INIT_LIST_HEAD(&cnflt->rc_node);
  570. setup_timer(&cnflt->timer, uwb_cnflt_timer, (unsigned long)cnflt);
  571. cnflt->rc = rc;
  572. INIT_WORK(&cnflt->cnflt_update_work, uwb_cnflt_update_work);
  573. bitmap_copy(cnflt->mas.bm, mas.bm, UWB_NUM_MAS);
  574. list_add_tail(&cnflt->rc_node, &rc->cnflt_alien_list);
  575. /* update rc global conflicting alien bitmap */
  576. bitmap_or(rc->cnflt_alien_bitmap.bm, rc->cnflt_alien_bitmap.bm, mas.bm, UWB_NUM_MAS);
  577. queue_delayed_work(rc->rsv_workq, &rc->rsv_alien_bp_work, usecs_to_jiffies(delay_us));
  578. /* start the timer */
  579. uwb_cnflt_alien_stroke_timer(cnflt);
  580. }
  581. static void uwb_drp_process_not_involved(struct uwb_rc *rc,
  582. struct uwb_rc_evt_drp *drp_evt,
  583. struct uwb_ie_drp *drp_ie)
  584. {
  585. struct uwb_mas_bm mas;
  586. uwb_drp_ie_to_bm(&mas, drp_ie);
  587. uwb_drp_handle_all_conflict_rsv(rc, drp_evt, drp_ie, &mas);
  588. }
  589. static void uwb_drp_process_involved(struct uwb_rc *rc, struct uwb_dev *src,
  590. struct uwb_rc_evt_drp *drp_evt,
  591. struct uwb_ie_drp *drp_ie)
  592. {
  593. struct uwb_rsv *rsv;
  594. rsv = uwb_rsv_find(rc, src, drp_ie);
  595. if (!rsv) {
  596. /*
  597. * No reservation? It's either for a recently
  598. * terminated reservation; or the DRP IE couldn't be
  599. * processed (e.g., an invalid IE or out of memory).
  600. */
  601. return;
  602. }
  603. /*
  604. * Do nothing with DRP IEs for reservations that have been
  605. * terminated.
  606. */
  607. if (rsv->state == UWB_RSV_STATE_NONE) {
  608. uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
  609. return;
  610. }
  611. if (uwb_ie_drp_owner(drp_ie))
  612. uwb_drp_process_target(rc, rsv, drp_ie, drp_evt);
  613. else
  614. uwb_drp_process_owner(rc, rsv, src, drp_ie, drp_evt);
  615. }
  616. static bool uwb_drp_involves_us(struct uwb_rc *rc, struct uwb_ie_drp *drp_ie)
  617. {
  618. return uwb_dev_addr_cmp(&rc->uwb_dev.dev_addr, &drp_ie->dev_addr) == 0;
  619. }
  620. /*
  621. * Process a received DRP IE.
  622. */
  623. static void uwb_drp_process(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt,
  624. struct uwb_dev *src, struct uwb_ie_drp *drp_ie)
  625. {
  626. if (uwb_ie_drp_type(drp_ie) == UWB_DRP_TYPE_ALIEN_BP)
  627. uwb_drp_handle_alien_drp(rc, drp_ie);
  628. else if (uwb_drp_involves_us(rc, drp_ie))
  629. uwb_drp_process_involved(rc, src, drp_evt, drp_ie);
  630. else
  631. uwb_drp_process_not_involved(rc, drp_evt, drp_ie);
  632. }
  633. /*
  634. * Process a received DRP Availability IE
  635. */
  636. static void uwb_drp_availability_process(struct uwb_rc *rc, struct uwb_dev *src,
  637. struct uwb_ie_drp_avail *drp_availability_ie)
  638. {
  639. bitmap_copy(src->last_availability_bm,
  640. drp_availability_ie->bmp, UWB_NUM_MAS);
  641. }
  642. /*
  643. * Process all the DRP IEs (both DRP IEs and the DRP Availability IE)
  644. * from a device.
  645. */
  646. static
  647. void uwb_drp_process_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt,
  648. size_t ielen, struct uwb_dev *src_dev)
  649. {
  650. struct device *dev = &rc->uwb_dev.dev;
  651. struct uwb_ie_hdr *ie_hdr;
  652. void *ptr;
  653. ptr = drp_evt->ie_data;
  654. for (;;) {
  655. ie_hdr = uwb_ie_next(&ptr, &ielen);
  656. if (!ie_hdr)
  657. break;
  658. switch (ie_hdr->element_id) {
  659. case UWB_IE_DRP_AVAILABILITY:
  660. uwb_drp_availability_process(rc, src_dev, (struct uwb_ie_drp_avail *)ie_hdr);
  661. break;
  662. case UWB_IE_DRP:
  663. uwb_drp_process(rc, drp_evt, src_dev, (struct uwb_ie_drp *)ie_hdr);
  664. break;
  665. default:
  666. dev_warn(dev, "unexpected IE in DRP notification\n");
  667. break;
  668. }
  669. }
  670. if (ielen > 0)
  671. dev_warn(dev, "%d octets remaining in DRP notification\n",
  672. (int)ielen);
  673. }
  674. /**
  675. * uwbd_evt_handle_rc_drp - handle a DRP_IE event
  676. * @evt: the DRP_IE event from the radio controller
  677. *
  678. * This processes DRP notifications from the radio controller, either
  679. * initiating a new reservation or transitioning an existing
  680. * reservation into a different state.
  681. *
  682. * DRP notifications can occur for three different reasons:
  683. *
  684. * - UWB_DRP_NOTIF_DRP_IE_RECVD: one or more DRP IEs with the RC as
  685. * the target or source have been received.
  686. *
  687. * These DRP IEs could be new or for an existing reservation.
  688. *
  689. * If the DRP IE for an existing reservation ceases to be to
  690. * received for at least mMaxLostBeacons, the reservation should be
  691. * considered to be terminated. Note that the TERMINATE reason (see
  692. * below) may not always be signalled (e.g., the remote device has
  693. * two or more reservations established with the RC).
  694. *
  695. * - UWB_DRP_NOTIF_CONFLICT: DRP IEs from any device in the beacon
  696. * group conflict with the RC's reservations.
  697. *
  698. * - UWB_DRP_NOTIF_TERMINATE: DRP IEs are no longer being received
  699. * from a device (i.e., it's terminated all reservations).
  700. *
  701. * Only the software state of the reservations is changed; the setting
  702. * of the radio controller's DRP IEs is done after all the events in
  703. * an event buffer are processed. This saves waiting multiple times
  704. * for the SET_DRP_IE command to complete.
  705. */
  706. int uwbd_evt_handle_rc_drp(struct uwb_event *evt)
  707. {
  708. struct device *dev = &evt->rc->uwb_dev.dev;
  709. struct uwb_rc *rc = evt->rc;
  710. struct uwb_rc_evt_drp *drp_evt;
  711. size_t ielength, bytes_left;
  712. struct uwb_dev_addr src_addr;
  713. struct uwb_dev *src_dev;
  714. /* Is there enough data to decode the event (and any IEs in
  715. its payload)? */
  716. if (evt->notif.size < sizeof(*drp_evt)) {
  717. dev_err(dev, "DRP event: Not enough data to decode event "
  718. "[%zu bytes left, %zu needed]\n",
  719. evt->notif.size, sizeof(*drp_evt));
  720. return 0;
  721. }
  722. bytes_left = evt->notif.size - sizeof(*drp_evt);
  723. drp_evt = container_of(evt->notif.rceb, struct uwb_rc_evt_drp, rceb);
  724. ielength = le16_to_cpu(drp_evt->ie_length);
  725. if (bytes_left != ielength) {
  726. dev_err(dev, "DRP event: Not enough data in payload [%zu"
  727. "bytes left, %zu declared in the event]\n",
  728. bytes_left, ielength);
  729. return 0;
  730. }
  731. memcpy(src_addr.data, &drp_evt->src_addr, sizeof(src_addr));
  732. src_dev = uwb_dev_get_by_devaddr(rc, &src_addr);
  733. if (!src_dev) {
  734. /*
  735. * A DRP notification from an unrecognized device.
  736. *
  737. * This is probably from a WUSB device that doesn't
  738. * have an EUI-48 and therefore doesn't show up in the
  739. * UWB device database. It's safe to simply ignore
  740. * these.
  741. */
  742. return 0;
  743. }
  744. mutex_lock(&rc->rsvs_mutex);
  745. /* We do not distinguish from the reason */
  746. uwb_drp_process_all(rc, drp_evt, ielength, src_dev);
  747. mutex_unlock(&rc->rsvs_mutex);
  748. uwb_dev_put(src_dev);
  749. return 0;
  750. }