drp.c 24 KB

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