drp.c 24 KB

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