diff options
author | Stefano Panella <stefano.panella@csr.com> | 2008-12-12 08:00:06 -0500 |
---|---|---|
committer | David Vrabel <david.vrabel@csr.com> | 2008-12-12 08:00:06 -0500 |
commit | 5b37717a23b8e40f6cf7ad85a26ddcf41c171e2c (patch) | |
tree | 3c611f907bc61c6e1900c4092e8f2f1e8eefd907 /drivers/uwb/drp.c | |
parent | c35fa3ea1ae8198bd65c2c6e59d9ebd68c115a59 (diff) |
uwb: improved MAS allocator and reservation conflict handling
Greatly enhance the MAS allocator:
- Handle row and column reservations.
- Permit all the available MAS to be allocated.
- Follows the WiMedia rules on MAS selection.
Take appropriate action when reservation conflicts are detected.
- Correctly identify which reservation wins the conflict.
- Protect alien BP reservations.
- If an owned reservation loses, resize/move it.
- Follow the backoff procedure before requesting additional MAS.
When reservations are terminated, move the remaining reservations (if
necessary) so they keep following the MAS allocation rules.
Signed-off-by: Stefano Panella <stefano.panella@csr.com>
Signed-off-by: David Vrabel <david.vrabel@csr.com>
Diffstat (limited to 'drivers/uwb/drp.c')
-rw-r--r-- | drivers/uwb/drp.c | 681 |
1 files changed, 527 insertions, 154 deletions
diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c index fe328146adb7..2b4f9406789d 100644 --- a/drivers/uwb/drp.c +++ b/drivers/uwb/drp.c | |||
@@ -23,6 +23,59 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include "uwb-internal.h" | 24 | #include "uwb-internal.h" |
25 | 25 | ||
26 | |||
27 | /* DRP Conflict Actions ([ECMA-368 2nd Edition] 17.4.6) */ | ||
28 | enum uwb_drp_conflict_action { | ||
29 | /* Reservation is mantained, no action needed */ | ||
30 | UWB_DRP_CONFLICT_MANTAIN = 0, | ||
31 | |||
32 | /* the device shall not transmit frames in conflicting MASs in | ||
33 | * the following superframe. If the device is the reservation | ||
34 | * target, it shall also set the Reason Code in its DRP IE to | ||
35 | * Conflict in its beacon in the following superframe. | ||
36 | */ | ||
37 | UWB_DRP_CONFLICT_ACT1, | ||
38 | |||
39 | /* the device shall not set the Reservation Status bit to ONE | ||
40 | * and shall not transmit frames in conflicting MASs. If the | ||
41 | * device is the reservation target, it shall also set the | ||
42 | * Reason Code in its DRP IE to Conflict. | ||
43 | */ | ||
44 | UWB_DRP_CONFLICT_ACT2, | ||
45 | |||
46 | /* the device shall not transmit frames in conflicting MASs in | ||
47 | * the following superframe. It shall remove the conflicting | ||
48 | * MASs from the reservation or set the Reservation Status to | ||
49 | * ZERO in its beacon in the following superframe. If the | ||
50 | * device is the reservation target, it shall also set the | ||
51 | * Reason Code in its DRP IE to Conflict. | ||
52 | */ | ||
53 | UWB_DRP_CONFLICT_ACT3, | ||
54 | }; | ||
55 | |||
56 | |||
57 | static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg, | ||
58 | struct uwb_rceb *reply, ssize_t reply_size) | ||
59 | { | ||
60 | struct uwb_rc_evt_set_drp_ie *r = (struct uwb_rc_evt_set_drp_ie *)reply; | ||
61 | |||
62 | if (r != NULL) { | ||
63 | if (r->bResultCode != UWB_RC_RES_SUCCESS) | ||
64 | dev_err(&rc->uwb_dev.dev, "SET-DRP-IE failed: %s (%d)\n", | ||
65 | uwb_rc_strerror(r->bResultCode), r->bResultCode); | ||
66 | } else | ||
67 | dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n"); | ||
68 | |||
69 | spin_lock(&rc->rsvs_lock); | ||
70 | if (rc->set_drp_ie_pending > 1) { | ||
71 | rc->set_drp_ie_pending = 0; | ||
72 | uwb_rsv_queue_update(rc); | ||
73 | } else { | ||
74 | rc->set_drp_ie_pending = 0; | ||
75 | } | ||
76 | spin_unlock(&rc->rsvs_lock); | ||
77 | } | ||
78 | |||
26 | /** | 79 | /** |
27 | * Construct and send the SET DRP IE | 80 | * Construct and send the SET DRP IE |
28 | * | 81 | * |
@@ -46,18 +99,23 @@ | |||
46 | int uwb_rc_send_all_drp_ie(struct uwb_rc *rc) | 99 | int uwb_rc_send_all_drp_ie(struct uwb_rc *rc) |
47 | { | 100 | { |
48 | int result; | 101 | int result; |
49 | struct device *dev = &rc->uwb_dev.dev; | ||
50 | struct uwb_rc_cmd_set_drp_ie *cmd; | 102 | struct uwb_rc_cmd_set_drp_ie *cmd; |
51 | struct uwb_rc_evt_set_drp_ie reply; | ||
52 | struct uwb_rsv *rsv; | 103 | struct uwb_rsv *rsv; |
104 | struct uwb_rsv_move *mv; | ||
53 | int num_bytes = 0; | 105 | int num_bytes = 0; |
54 | u8 *IEDataptr; | 106 | u8 *IEDataptr; |
55 | 107 | ||
56 | result = -ENOMEM; | 108 | result = -ENOMEM; |
57 | /* First traverse all reservations to determine memory needed. */ | 109 | /* First traverse all reservations to determine memory needed. */ |
58 | list_for_each_entry(rsv, &rc->reservations, rc_node) { | 110 | list_for_each_entry(rsv, &rc->reservations, rc_node) { |
59 | if (rsv->drp_ie != NULL) | 111 | if (rsv->drp_ie != NULL) { |
60 | num_bytes += rsv->drp_ie->hdr.length + 2; | 112 | num_bytes += rsv->drp_ie->hdr.length + 2; |
113 | if (uwb_rsv_has_two_drp_ies(rsv) && | ||
114 | (rsv->mv.companion_drp_ie != NULL)) { | ||
115 | mv = &rsv->mv; | ||
116 | num_bytes += mv->companion_drp_ie->hdr.length + 2; | ||
117 | } | ||
118 | } | ||
61 | } | 119 | } |
62 | num_bytes += sizeof(rc->drp_avail.ie); | 120 | num_bytes += sizeof(rc->drp_avail.ie); |
63 | cmd = kzalloc(sizeof(*cmd) + num_bytes, GFP_KERNEL); | 121 | cmd = kzalloc(sizeof(*cmd) + num_bytes, GFP_KERNEL); |
@@ -68,109 +126,322 @@ int uwb_rc_send_all_drp_ie(struct uwb_rc *rc) | |||
68 | cmd->wIELength = num_bytes; | 126 | cmd->wIELength = num_bytes; |
69 | IEDataptr = (u8 *)&cmd->IEData[0]; | 127 | IEDataptr = (u8 *)&cmd->IEData[0]; |
70 | 128 | ||
129 | /* FIXME: DRV avail IE is not always needed */ | ||
130 | /* put DRP avail IE first */ | ||
131 | memcpy(IEDataptr, &rc->drp_avail.ie, sizeof(rc->drp_avail.ie)); | ||
132 | IEDataptr += sizeof(struct uwb_ie_drp_avail); | ||
133 | |||
71 | /* Next traverse all reservations to place IEs in allocated memory. */ | 134 | /* Next traverse all reservations to place IEs in allocated memory. */ |
72 | list_for_each_entry(rsv, &rc->reservations, rc_node) { | 135 | list_for_each_entry(rsv, &rc->reservations, rc_node) { |
73 | if (rsv->drp_ie != NULL) { | 136 | if (rsv->drp_ie != NULL) { |
74 | memcpy(IEDataptr, rsv->drp_ie, | 137 | memcpy(IEDataptr, rsv->drp_ie, |
75 | rsv->drp_ie->hdr.length + 2); | 138 | rsv->drp_ie->hdr.length + 2); |
76 | IEDataptr += rsv->drp_ie->hdr.length + 2; | 139 | IEDataptr += rsv->drp_ie->hdr.length + 2; |
140 | |||
141 | if (uwb_rsv_has_two_drp_ies(rsv) && | ||
142 | (rsv->mv.companion_drp_ie != NULL)) { | ||
143 | mv = &rsv->mv; | ||
144 | memcpy(IEDataptr, mv->companion_drp_ie, | ||
145 | mv->companion_drp_ie->hdr.length + 2); | ||
146 | IEDataptr += mv->companion_drp_ie->hdr.length + 2; | ||
147 | } | ||
77 | } | 148 | } |
78 | } | 149 | } |
79 | memcpy(IEDataptr, &rc->drp_avail.ie, sizeof(rc->drp_avail.ie)); | ||
80 | 150 | ||
81 | reply.rceb.bEventType = UWB_RC_CET_GENERAL; | 151 | result = uwb_rc_cmd_async(rc, "SET-DRP-IE", &cmd->rccb, sizeof(*cmd) + num_bytes, |
82 | reply.rceb.wEvent = UWB_RC_CMD_SET_DRP_IE; | 152 | UWB_RC_CET_GENERAL, UWB_RC_CMD_SET_DRP_IE, |
83 | result = uwb_rc_cmd(rc, "SET-DRP-IE", &cmd->rccb, | 153 | uwb_rc_set_drp_cmd_done, NULL); |
84 | sizeof(*cmd) + num_bytes, &reply.rceb, | 154 | |
85 | sizeof(reply)); | 155 | rc->set_drp_ie_pending = 1; |
86 | if (result < 0) | 156 | |
87 | goto error_cmd; | ||
88 | result = le16_to_cpu(reply.wRemainingSpace); | ||
89 | if (reply.bResultCode != UWB_RC_RES_SUCCESS) { | ||
90 | dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: command execution " | ||
91 | "failed: %s (%d). RemainingSpace in beacon " | ||
92 | "= %d\n", uwb_rc_strerror(reply.bResultCode), | ||
93 | reply.bResultCode, result); | ||
94 | result = -EIO; | ||
95 | } else { | ||
96 | dev_dbg(dev, "SET-DRP-IE sent. RemainingSpace in beacon " | ||
97 | "= %d.\n", result); | ||
98 | result = 0; | ||
99 | } | ||
100 | error_cmd: | ||
101 | kfree(cmd); | 157 | kfree(cmd); |
102 | error: | 158 | error: |
103 | return result; | 159 | return result; |
104 | } | 160 | } |
105 | 161 | ||
106 | void uwb_drp_handle_timeout(struct uwb_rsv *rsv) | 162 | /* |
163 | * Evaluate the action to perform using conflict resolution rules | ||
164 | * | ||
165 | * Return a uwb_drp_conflict_action. | ||
166 | */ | ||
167 | static int evaluate_conflict_action(struct uwb_ie_drp *ext_drp_ie, int ext_beacon_slot, | ||
168 | struct uwb_rsv *rsv, int our_status) | ||
107 | { | 169 | { |
108 | struct device *dev = &rsv->rc->uwb_dev.dev; | 170 | int our_tie_breaker = rsv->tiebreaker; |
171 | int our_type = rsv->type; | ||
172 | int our_beacon_slot = rsv->rc->uwb_dev.beacon_slot; | ||
173 | |||
174 | int ext_tie_breaker = uwb_ie_drp_tiebreaker(ext_drp_ie); | ||
175 | int ext_status = uwb_ie_drp_status(ext_drp_ie); | ||
176 | int ext_type = uwb_ie_drp_type(ext_drp_ie); | ||
177 | |||
178 | |||
179 | /* [ECMA-368 2nd Edition] 17.4.6 */ | ||
180 | if (ext_type == UWB_DRP_TYPE_PCA && our_type == UWB_DRP_TYPE_PCA) { | ||
181 | return UWB_DRP_CONFLICT_MANTAIN; | ||
182 | } | ||
183 | |||
184 | /* [ECMA-368 2nd Edition] 17.4.6-1 */ | ||
185 | if (our_type == UWB_DRP_TYPE_ALIEN_BP) { | ||
186 | return UWB_DRP_CONFLICT_MANTAIN; | ||
187 | } | ||
188 | |||
189 | /* [ECMA-368 2nd Edition] 17.4.6-2 */ | ||
190 | if (ext_type == UWB_DRP_TYPE_ALIEN_BP) { | ||
191 | /* here we know our_type != UWB_DRP_TYPE_ALIEN_BP */ | ||
192 | return UWB_DRP_CONFLICT_ACT1; | ||
193 | } | ||
194 | |||
195 | /* [ECMA-368 2nd Edition] 17.4.6-3 */ | ||
196 | if (our_status == 0 && ext_status == 1) { | ||
197 | return UWB_DRP_CONFLICT_ACT2; | ||
198 | } | ||
109 | 199 | ||
110 | dev_dbg(dev, "reservation timeout in state %s (%d)\n", | 200 | /* [ECMA-368 2nd Edition] 17.4.6-4 */ |
111 | uwb_rsv_state_str(rsv->state), rsv->state); | 201 | if (our_status == 1 && ext_status == 0) { |
202 | return UWB_DRP_CONFLICT_MANTAIN; | ||
203 | } | ||
112 | 204 | ||
113 | switch (rsv->state) { | 205 | /* [ECMA-368 2nd Edition] 17.4.6-5a */ |
114 | case UWB_RSV_STATE_O_INITIATED: | 206 | if (our_tie_breaker == ext_tie_breaker && |
115 | if (rsv->is_multicast) { | 207 | our_beacon_slot < ext_beacon_slot) { |
116 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | 208 | return UWB_DRP_CONFLICT_MANTAIN; |
117 | return; | 209 | } |
210 | |||
211 | /* [ECMA-368 2nd Edition] 17.4.6-5b */ | ||
212 | if (our_tie_breaker != ext_tie_breaker && | ||
213 | our_beacon_slot > ext_beacon_slot) { | ||
214 | return UWB_DRP_CONFLICT_MANTAIN; | ||
215 | } | ||
216 | |||
217 | if (our_status == 0) { | ||
218 | if (our_tie_breaker == ext_tie_breaker) { | ||
219 | /* [ECMA-368 2nd Edition] 17.4.6-6a */ | ||
220 | if (our_beacon_slot > ext_beacon_slot) { | ||
221 | return UWB_DRP_CONFLICT_ACT2; | ||
222 | } | ||
223 | } else { | ||
224 | /* [ECMA-368 2nd Edition] 17.4.6-6b */ | ||
225 | if (our_beacon_slot < ext_beacon_slot) { | ||
226 | return UWB_DRP_CONFLICT_ACT2; | ||
227 | } | ||
118 | } | 228 | } |
119 | break; | 229 | } else { |
120 | case UWB_RSV_STATE_O_ESTABLISHED: | 230 | if (our_tie_breaker == ext_tie_breaker) { |
121 | if (rsv->is_multicast) | 231 | /* [ECMA-368 2nd Edition] 17.4.6-7a */ |
122 | return; | 232 | if (our_beacon_slot > ext_beacon_slot) { |
123 | break; | 233 | return UWB_DRP_CONFLICT_ACT3; |
124 | default: | 234 | } |
125 | break; | 235 | } else { |
236 | /* [ECMA-368 2nd Edition] 17.4.6-7b */ | ||
237 | if (our_beacon_slot < ext_beacon_slot) { | ||
238 | return UWB_DRP_CONFLICT_ACT3; | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | return UWB_DRP_CONFLICT_MANTAIN; | ||
243 | } | ||
244 | |||
245 | static void handle_conflict_normal(struct uwb_ie_drp *drp_ie, | ||
246 | int ext_beacon_slot, | ||
247 | struct uwb_rsv *rsv, | ||
248 | struct uwb_mas_bm *conflicting_mas) | ||
249 | { | ||
250 | struct uwb_rc *rc = rsv->rc; | ||
251 | struct uwb_rsv_move *mv = &rsv->mv; | ||
252 | struct uwb_drp_backoff_win *bow = &rc->bow; | ||
253 | int action; | ||
254 | |||
255 | action = evaluate_conflict_action(drp_ie, ext_beacon_slot, rsv, uwb_rsv_status(rsv)); | ||
256 | |||
257 | if (uwb_rsv_is_owner(rsv)) { | ||
258 | switch(action) { | ||
259 | case UWB_DRP_CONFLICT_ACT2: | ||
260 | /* try move */ | ||
261 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_TO_BE_MOVED); | ||
262 | if (bow->can_reserve_extra_mases == false) | ||
263 | uwb_rsv_backoff_win_increment(rc); | ||
264 | |||
265 | break; | ||
266 | case UWB_DRP_CONFLICT_ACT3: | ||
267 | uwb_rsv_backoff_win_increment(rc); | ||
268 | /* drop some mases with reason modified */ | ||
269 | /* put in the companion the mases to be dropped */ | ||
270 | bitmap_and(mv->companion_mas.bm, rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS); | ||
271 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED); | ||
272 | default: | ||
273 | break; | ||
274 | } | ||
275 | } else { | ||
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_CONFLICT); | ||
280 | default: | ||
281 | break; | ||
282 | } | ||
283 | |||
284 | } | ||
285 | |||
286 | } | ||
287 | |||
288 | static void handle_conflict_expanding(struct uwb_ie_drp *drp_ie, int ext_beacon_slot, | ||
289 | struct uwb_rsv *rsv, bool companion_only, | ||
290 | struct uwb_mas_bm *conflicting_mas) | ||
291 | { | ||
292 | struct uwb_rc *rc = rsv->rc; | ||
293 | struct uwb_drp_backoff_win *bow = &rc->bow; | ||
294 | struct uwb_rsv_move *mv = &rsv->mv; | ||
295 | int action; | ||
296 | |||
297 | if (companion_only) { | ||
298 | /* status of companion is 0 at this point */ | ||
299 | action = evaluate_conflict_action(drp_ie, ext_beacon_slot, rsv, 0); | ||
300 | if (uwb_rsv_is_owner(rsv)) { | ||
301 | switch(action) { | ||
302 | case UWB_DRP_CONFLICT_ACT2: | ||
303 | case UWB_DRP_CONFLICT_ACT3: | ||
304 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | ||
305 | rsv->needs_release_companion_mas = false; | ||
306 | if (bow->can_reserve_extra_mases == false) | ||
307 | uwb_rsv_backoff_win_increment(rc); | ||
308 | uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas); | ||
309 | } | ||
310 | } else { /* rsv is target */ | ||
311 | switch(action) { | ||
312 | case UWB_DRP_CONFLICT_ACT2: | ||
313 | case UWB_DRP_CONFLICT_ACT3: | ||
314 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_EXPANDING_CONFLICT); | ||
315 | /* send_drp_avail_ie = true; */ | ||
316 | } | ||
317 | } | ||
318 | } else { /* also base part of the reservation is conflicting */ | ||
319 | if (uwb_rsv_is_owner(rsv)) { | ||
320 | uwb_rsv_backoff_win_increment(rc); | ||
321 | /* remove companion part */ | ||
322 | uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas); | ||
323 | |||
324 | /* drop some mases with reason modified */ | ||
325 | |||
326 | /* put in the companion the mases to be dropped */ | ||
327 | bitmap_andnot(mv->companion_mas.bm, rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS); | ||
328 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED); | ||
329 | } else { /* it is a target rsv */ | ||
330 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT); | ||
331 | /* send_drp_avail_ie = true; */ | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | |||
336 | static void uwb_drp_handle_conflict_rsv(struct uwb_rc *rc, struct uwb_rsv *rsv, | ||
337 | struct uwb_rc_evt_drp *drp_evt, | ||
338 | struct uwb_ie_drp *drp_ie, | ||
339 | struct uwb_mas_bm *conflicting_mas) | ||
340 | { | ||
341 | struct uwb_rsv_move *mv; | ||
342 | |||
343 | /* check if the conflicting reservation has two drp_ies */ | ||
344 | if (uwb_rsv_has_two_drp_ies(rsv)) { | ||
345 | mv = &rsv->mv; | ||
346 | if (bitmap_intersects(rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS)) { | ||
347 | handle_conflict_expanding(drp_ie, drp_evt->beacon_slot_number, | ||
348 | rsv, false, conflicting_mas); | ||
349 | } else { | ||
350 | if (bitmap_intersects(mv->companion_mas.bm, conflicting_mas->bm, UWB_NUM_MAS)) { | ||
351 | handle_conflict_expanding(drp_ie, drp_evt->beacon_slot_number, | ||
352 | rsv, true, conflicting_mas); | ||
353 | } | ||
354 | } | ||
355 | } else if (bitmap_intersects(rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS)) { | ||
356 | handle_conflict_normal(drp_ie, drp_evt->beacon_slot_number, rsv, conflicting_mas); | ||
126 | } | 357 | } |
127 | uwb_rsv_remove(rsv); | ||
128 | } | 358 | } |
129 | 359 | ||
360 | static void uwb_drp_handle_all_conflict_rsv(struct uwb_rc *rc, | ||
361 | struct uwb_rc_evt_drp *drp_evt, | ||
362 | struct uwb_ie_drp *drp_ie, | ||
363 | struct uwb_mas_bm *conflicting_mas) | ||
364 | { | ||
365 | struct uwb_rsv *rsv; | ||
366 | |||
367 | list_for_each_entry(rsv, &rc->reservations, rc_node) { | ||
368 | uwb_drp_handle_conflict_rsv(rc, rsv, drp_evt, drp_ie, conflicting_mas); | ||
369 | } | ||
370 | } | ||
371 | |||
130 | /* | 372 | /* |
131 | * Based on the DRP IE, transition a target reservation to a new | 373 | * Based on the DRP IE, transition a target reservation to a new |
132 | * state. | 374 | * state. |
133 | */ | 375 | */ |
134 | static void uwb_drp_process_target(struct uwb_rc *rc, struct uwb_rsv *rsv, | 376 | static void uwb_drp_process_target(struct uwb_rc *rc, struct uwb_rsv *rsv, |
135 | struct uwb_ie_drp *drp_ie) | 377 | struct uwb_ie_drp *drp_ie, struct uwb_rc_evt_drp *drp_evt) |
136 | { | 378 | { |
137 | struct device *dev = &rc->uwb_dev.dev; | 379 | struct device *dev = &rc->uwb_dev.dev; |
380 | struct uwb_rsv_move *mv = &rsv->mv; | ||
138 | int status; | 381 | int status; |
139 | enum uwb_drp_reason reason_code; | 382 | enum uwb_drp_reason reason_code; |
140 | 383 | struct uwb_mas_bm mas; | |
384 | |||
141 | status = uwb_ie_drp_status(drp_ie); | 385 | status = uwb_ie_drp_status(drp_ie); |
142 | reason_code = uwb_ie_drp_reason_code(drp_ie); | 386 | reason_code = uwb_ie_drp_reason_code(drp_ie); |
387 | uwb_drp_ie_to_bm(&mas, drp_ie); | ||
143 | 388 | ||
144 | if (status) { | 389 | switch (reason_code) { |
145 | switch (reason_code) { | 390 | case UWB_DRP_REASON_ACCEPTED: |
146 | case UWB_DRP_REASON_ACCEPTED: | 391 | |
147 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED); | 392 | if (rsv->state == UWB_RSV_STATE_T_CONFLICT) { |
148 | break; | 393 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT); |
149 | case UWB_DRP_REASON_MODIFIED: | ||
150 | dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", | ||
151 | reason_code, status); | ||
152 | break; | 394 | break; |
153 | default: | ||
154 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", | ||
155 | reason_code, status); | ||
156 | } | 395 | } |
157 | } else { | 396 | |
158 | switch (reason_code) { | 397 | if (rsv->state == UWB_RSV_STATE_T_EXPANDING_ACCEPTED) { |
159 | case UWB_DRP_REASON_ACCEPTED: | 398 | /* drp_ie is companion */ |
160 | /* New reservations are handled in uwb_rsv_find(). */ | 399 | if (!bitmap_equal(rsv->mas.bm, mas.bm, UWB_NUM_MAS)) |
161 | break; | 400 | /* stroke companion */ |
162 | case UWB_DRP_REASON_DENIED: | 401 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_EXPANDING_ACCEPTED); |
163 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | 402 | } else { |
164 | break; | 403 | if (!bitmap_equal(rsv->mas.bm, mas.bm, UWB_NUM_MAS)) { |
165 | case UWB_DRP_REASON_CONFLICT: | 404 | if (uwb_drp_avail_reserve_pending(rc, &mas) == -EBUSY) { |
166 | case UWB_DRP_REASON_MODIFIED: | 405 | /* FIXME: there is a conflict, find |
167 | dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", | 406 | * the conflicting reservations and |
168 | reason_code, status); | 407 | * take a sensible action. Consider |
408 | * that in drp_ie there is the | ||
409 | * "neighbour" */ | ||
410 | uwb_drp_handle_all_conflict_rsv(rc, drp_evt, drp_ie, &mas); | ||
411 | } else { | ||
412 | /* accept the extra reservation */ | ||
413 | bitmap_copy(mv->companion_mas.bm, mas.bm, UWB_NUM_MAS); | ||
414 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_EXPANDING_ACCEPTED); | ||
415 | } | ||
416 | } else { | ||
417 | if (status) { | ||
418 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED); | ||
419 | } | ||
420 | } | ||
421 | |||
422 | } | ||
423 | break; | ||
424 | |||
425 | case UWB_DRP_REASON_MODIFIED: | ||
426 | /* check to see if we have already modified the reservation */ | ||
427 | if (bitmap_equal(rsv->mas.bm, mas.bm, UWB_NUM_MAS)) { | ||
428 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED); | ||
169 | break; | 429 | break; |
170 | default: | ||
171 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", | ||
172 | reason_code, status); | ||
173 | } | 430 | } |
431 | |||
432 | /* find if the owner wants to expand or reduce */ | ||
433 | if (bitmap_subset(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) { | ||
434 | /* owner is reducing */ | ||
435 | bitmap_andnot(mv->companion_mas.bm, rsv->mas.bm, mas.bm, UWB_NUM_MAS); | ||
436 | uwb_drp_avail_release(rsv->rc, &mv->companion_mas); | ||
437 | } | ||
438 | |||
439 | bitmap_copy(rsv->mas.bm, mas.bm, UWB_NUM_MAS); | ||
440 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_RESIZED); | ||
441 | break; | ||
442 | default: | ||
443 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", | ||
444 | reason_code, status); | ||
174 | } | 445 | } |
175 | } | 446 | } |
176 | 447 | ||
@@ -179,23 +450,60 @@ static void uwb_drp_process_target(struct uwb_rc *rc, struct uwb_rsv *rsv, | |||
179 | * state. | 450 | * state. |
180 | */ | 451 | */ |
181 | static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv, | 452 | static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv, |
182 | struct uwb_ie_drp *drp_ie) | 453 | struct uwb_dev *src, struct uwb_ie_drp *drp_ie, |
454 | struct uwb_rc_evt_drp *drp_evt) | ||
183 | { | 455 | { |
184 | struct device *dev = &rc->uwb_dev.dev; | 456 | struct device *dev = &rc->uwb_dev.dev; |
457 | struct uwb_rsv_move *mv = &rsv->mv; | ||
185 | int status; | 458 | int status; |
186 | enum uwb_drp_reason reason_code; | 459 | enum uwb_drp_reason reason_code; |
460 | struct uwb_mas_bm mas; | ||
187 | 461 | ||
188 | status = uwb_ie_drp_status(drp_ie); | 462 | status = uwb_ie_drp_status(drp_ie); |
189 | reason_code = uwb_ie_drp_reason_code(drp_ie); | 463 | reason_code = uwb_ie_drp_reason_code(drp_ie); |
464 | uwb_drp_ie_to_bm(&mas, drp_ie); | ||
190 | 465 | ||
191 | if (status) { | 466 | if (status) { |
192 | switch (reason_code) { | 467 | switch (reason_code) { |
193 | case UWB_DRP_REASON_ACCEPTED: | 468 | case UWB_DRP_REASON_ACCEPTED: |
194 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | 469 | switch (rsv->state) { |
195 | break; | 470 | case UWB_RSV_STATE_O_PENDING: |
196 | case UWB_DRP_REASON_MODIFIED: | 471 | case UWB_RSV_STATE_O_INITIATED: |
197 | dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", | 472 | case UWB_RSV_STATE_O_ESTABLISHED: |
198 | reason_code, status); | 473 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); |
474 | break; | ||
475 | case UWB_RSV_STATE_O_MODIFIED: | ||
476 | if (bitmap_equal(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) { | ||
477 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | ||
478 | } else { | ||
479 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED); | ||
480 | } | ||
481 | break; | ||
482 | |||
483 | case UWB_RSV_STATE_O_MOVE_REDUCING: /* shouldn' t be a problem */ | ||
484 | if (bitmap_equal(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) { | ||
485 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | ||
486 | } else { | ||
487 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_REDUCING); | ||
488 | } | ||
489 | break; | ||
490 | case UWB_RSV_STATE_O_MOVE_EXPANDING: | ||
491 | if (bitmap_equal(mas.bm, mv->companion_mas.bm, UWB_NUM_MAS)) { | ||
492 | /* Companion reservation accepted */ | ||
493 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_COMBINING); | ||
494 | } else { | ||
495 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_EXPANDING); | ||
496 | } | ||
497 | break; | ||
498 | case UWB_RSV_STATE_O_MOVE_COMBINING: | ||
499 | if (bitmap_equal(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) | ||
500 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_REDUCING); | ||
501 | else | ||
502 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_COMBINING); | ||
503 | break; | ||
504 | default: | ||
505 | break; | ||
506 | } | ||
199 | break; | 507 | break; |
200 | default: | 508 | default: |
201 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", | 509 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", |
@@ -210,9 +518,10 @@ static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv, | |||
210 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | 518 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); |
211 | break; | 519 | break; |
212 | case UWB_DRP_REASON_CONFLICT: | 520 | case UWB_DRP_REASON_CONFLICT: |
213 | case UWB_DRP_REASON_MODIFIED: | 521 | /* resolve the conflict */ |
214 | dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", | 522 | bitmap_complement(mas.bm, src->last_availability_bm, |
215 | reason_code, status); | 523 | UWB_NUM_MAS); |
524 | uwb_drp_handle_conflict_rsv(rc, rsv, drp_evt, drp_ie, &mas); | ||
216 | break; | 525 | break; |
217 | default: | 526 | default: |
218 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", | 527 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", |
@@ -221,12 +530,110 @@ static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv, | |||
221 | } | 530 | } |
222 | } | 531 | } |
223 | 532 | ||
533 | static void uwb_cnflt_alien_stroke_timer(struct uwb_cnflt_alien *cnflt) | ||
534 | { | ||
535 | unsigned timeout_us = UWB_MAX_LOST_BEACONS * UWB_SUPERFRAME_LENGTH_US; | ||
536 | mod_timer(&cnflt->timer, jiffies + usecs_to_jiffies(timeout_us)); | ||
537 | } | ||
538 | |||
539 | static void uwb_cnflt_update_work(struct work_struct *work) | ||
540 | { | ||
541 | struct uwb_cnflt_alien *cnflt = container_of(work, | ||
542 | struct uwb_cnflt_alien, | ||
543 | cnflt_update_work); | ||
544 | struct uwb_cnflt_alien *c; | ||
545 | struct uwb_rc *rc = cnflt->rc; | ||
546 | |||
547 | unsigned long delay_us = UWB_MAS_LENGTH_US * UWB_MAS_PER_ZONE; | ||
548 | |||
549 | mutex_lock(&rc->rsvs_mutex); | ||
550 | |||
551 | list_del(&cnflt->rc_node); | ||
552 | |||
553 | /* update rc global conflicting alien bitmap */ | ||
554 | bitmap_zero(rc->cnflt_alien_bitmap.bm, UWB_NUM_MAS); | ||
555 | |||
556 | list_for_each_entry(c, &rc->cnflt_alien_list, rc_node) { | ||
557 | bitmap_or(rc->cnflt_alien_bitmap.bm, rc->cnflt_alien_bitmap.bm, c->mas.bm, UWB_NUM_MAS); | ||
558 | } | ||
559 | |||
560 | queue_delayed_work(rc->rsv_workq, &rc->rsv_alien_bp_work, usecs_to_jiffies(delay_us)); | ||
561 | |||
562 | kfree(cnflt); | ||
563 | mutex_unlock(&rc->rsvs_mutex); | ||
564 | } | ||
565 | |||
566 | static void uwb_cnflt_timer(unsigned long arg) | ||
567 | { | ||
568 | struct uwb_cnflt_alien *cnflt = (struct uwb_cnflt_alien *)arg; | ||
569 | |||
570 | queue_work(cnflt->rc->rsv_workq, &cnflt->cnflt_update_work); | ||
571 | } | ||
572 | |||
224 | /* | 573 | /* |
225 | * Process a received DRP IE, it's either for a reservation owned by | 574 | * We have received an DRP_IE of type Alien BP and we need to make |
226 | * the RC or targeted at it (or it's for a WUSB cluster reservation). | 575 | * sure we do not transmit in conflicting MASs. |
227 | */ | 576 | */ |
228 | static void uwb_drp_process(struct uwb_rc *rc, struct uwb_dev *src, | 577 | static void uwb_drp_handle_alien_drp(struct uwb_rc *rc, struct uwb_ie_drp *drp_ie) |
229 | struct uwb_ie_drp *drp_ie) | 578 | { |
579 | struct device *dev = &rc->uwb_dev.dev; | ||
580 | struct uwb_mas_bm mas; | ||
581 | struct uwb_cnflt_alien *cnflt; | ||
582 | char buf[72]; | ||
583 | unsigned long delay_us = UWB_MAS_LENGTH_US * UWB_MAS_PER_ZONE; | ||
584 | |||
585 | uwb_drp_ie_to_bm(&mas, drp_ie); | ||
586 | bitmap_scnprintf(buf, sizeof(buf), mas.bm, UWB_NUM_MAS); | ||
587 | |||
588 | list_for_each_entry(cnflt, &rc->cnflt_alien_list, rc_node) { | ||
589 | if (bitmap_equal(cnflt->mas.bm, mas.bm, UWB_NUM_MAS)) { | ||
590 | /* Existing alien BP reservation conflicting | ||
591 | * bitmap, just reset the timer */ | ||
592 | uwb_cnflt_alien_stroke_timer(cnflt); | ||
593 | return; | ||
594 | } | ||
595 | } | ||
596 | |||
597 | /* New alien BP reservation conflicting bitmap */ | ||
598 | |||
599 | /* alloc and initialize new uwb_cnflt_alien */ | ||
600 | cnflt = kzalloc(sizeof(struct uwb_cnflt_alien), GFP_KERNEL); | ||
601 | if (!cnflt) | ||
602 | dev_err(dev, "failed to alloc uwb_cnflt_alien struct\n"); | ||
603 | INIT_LIST_HEAD(&cnflt->rc_node); | ||
604 | init_timer(&cnflt->timer); | ||
605 | cnflt->timer.function = uwb_cnflt_timer; | ||
606 | cnflt->timer.data = (unsigned long)cnflt; | ||
607 | |||
608 | cnflt->rc = rc; | ||
609 | INIT_WORK(&cnflt->cnflt_update_work, uwb_cnflt_update_work); | ||
610 | |||
611 | bitmap_copy(cnflt->mas.bm, mas.bm, UWB_NUM_MAS); | ||
612 | |||
613 | list_add_tail(&cnflt->rc_node, &rc->cnflt_alien_list); | ||
614 | |||
615 | /* update rc global conflicting alien bitmap */ | ||
616 | bitmap_or(rc->cnflt_alien_bitmap.bm, rc->cnflt_alien_bitmap.bm, mas.bm, UWB_NUM_MAS); | ||
617 | |||
618 | queue_delayed_work(rc->rsv_workq, &rc->rsv_alien_bp_work, usecs_to_jiffies(delay_us)); | ||
619 | |||
620 | /* start the timer */ | ||
621 | uwb_cnflt_alien_stroke_timer(cnflt); | ||
622 | } | ||
623 | |||
624 | static void uwb_drp_process_not_involved(struct uwb_rc *rc, | ||
625 | struct uwb_rc_evt_drp *drp_evt, | ||
626 | struct uwb_ie_drp *drp_ie) | ||
627 | { | ||
628 | struct uwb_mas_bm mas; | ||
629 | |||
630 | uwb_drp_ie_to_bm(&mas, drp_ie); | ||
631 | uwb_drp_handle_all_conflict_rsv(rc, drp_evt, drp_ie, &mas); | ||
632 | } | ||
633 | |||
634 | static void uwb_drp_process_involved(struct uwb_rc *rc, struct uwb_dev *src, | ||
635 | struct uwb_rc_evt_drp *drp_evt, | ||
636 | struct uwb_ie_drp *drp_ie) | ||
230 | { | 637 | { |
231 | struct uwb_rsv *rsv; | 638 | struct uwb_rsv *rsv; |
232 | 639 | ||
@@ -239,7 +646,7 @@ static void uwb_drp_process(struct uwb_rc *rc, struct uwb_dev *src, | |||
239 | */ | 646 | */ |
240 | return; | 647 | return; |
241 | } | 648 | } |
242 | 649 | ||
243 | /* | 650 | /* |
244 | * Do nothing with DRP IEs for reservations that have been | 651 | * Do nothing with DRP IEs for reservations that have been |
245 | * terminated. | 652 | * terminated. |
@@ -248,13 +655,43 @@ static void uwb_drp_process(struct uwb_rc *rc, struct uwb_dev *src, | |||
248 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | 655 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); |
249 | return; | 656 | return; |
250 | } | 657 | } |
251 | 658 | ||
252 | if (uwb_ie_drp_owner(drp_ie)) | 659 | if (uwb_ie_drp_owner(drp_ie)) |
253 | uwb_drp_process_target(rc, rsv, drp_ie); | 660 | uwb_drp_process_target(rc, rsv, drp_ie, drp_evt); |
661 | else | ||
662 | uwb_drp_process_owner(rc, rsv, src, drp_ie, drp_evt); | ||
663 | |||
664 | } | ||
665 | |||
666 | |||
667 | static bool uwb_drp_involves_us(struct uwb_rc *rc, struct uwb_ie_drp *drp_ie) | ||
668 | { | ||
669 | return uwb_dev_addr_cmp(&rc->uwb_dev.dev_addr, &drp_ie->dev_addr) == 0; | ||
670 | } | ||
671 | |||
672 | /* | ||
673 | * Process a received DRP IE. | ||
674 | */ | ||
675 | static void uwb_drp_process(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, | ||
676 | struct uwb_dev *src, struct uwb_ie_drp *drp_ie) | ||
677 | { | ||
678 | if (uwb_ie_drp_type(drp_ie) == UWB_DRP_TYPE_ALIEN_BP) | ||
679 | uwb_drp_handle_alien_drp(rc, drp_ie); | ||
680 | else if (uwb_drp_involves_us(rc, drp_ie)) | ||
681 | uwb_drp_process_involved(rc, src, drp_evt, drp_ie); | ||
254 | else | 682 | else |
255 | uwb_drp_process_owner(rc, rsv, drp_ie); | 683 | uwb_drp_process_not_involved(rc, drp_evt, drp_ie); |
256 | } | 684 | } |
257 | 685 | ||
686 | /* | ||
687 | * Process a received DRP Availability IE | ||
688 | */ | ||
689 | static void uwb_drp_availability_process(struct uwb_rc *rc, struct uwb_dev *src, | ||
690 | struct uwb_ie_drp_avail *drp_availability_ie) | ||
691 | { | ||
692 | bitmap_copy(src->last_availability_bm, | ||
693 | drp_availability_ie->bmp, UWB_NUM_MAS); | ||
694 | } | ||
258 | 695 | ||
259 | /* | 696 | /* |
260 | * Process all the DRP IEs (both DRP IEs and the DRP Availability IE) | 697 | * Process all the DRP IEs (both DRP IEs and the DRP Availability IE) |
@@ -276,10 +713,10 @@ void uwb_drp_process_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, | |||
276 | 713 | ||
277 | switch (ie_hdr->element_id) { | 714 | switch (ie_hdr->element_id) { |
278 | case UWB_IE_DRP_AVAILABILITY: | 715 | case UWB_IE_DRP_AVAILABILITY: |
279 | /* FIXME: does something need to be done with this? */ | 716 | uwb_drp_availability_process(rc, src_dev, (struct uwb_ie_drp_avail *)ie_hdr); |
280 | break; | 717 | break; |
281 | case UWB_IE_DRP: | 718 | case UWB_IE_DRP: |
282 | uwb_drp_process(rc, src_dev, (struct uwb_ie_drp *)ie_hdr); | 719 | uwb_drp_process(rc, drp_evt, src_dev, (struct uwb_ie_drp *)ie_hdr); |
283 | break; | 720 | break; |
284 | default: | 721 | default: |
285 | dev_warn(dev, "unexpected IE in DRP notification\n"); | 722 | dev_warn(dev, "unexpected IE in DRP notification\n"); |
@@ -292,55 +729,6 @@ void uwb_drp_process_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, | |||
292 | (int)ielen); | 729 | (int)ielen); |
293 | } | 730 | } |
294 | 731 | ||
295 | |||
296 | /* | ||
297 | * Go through all the DRP IEs and find the ones that conflict with our | ||
298 | * reservations. | ||
299 | * | ||
300 | * FIXME: must resolve the conflict according the the rules in | ||
301 | * [ECMA-368]. | ||
302 | */ | ||
303 | static | ||
304 | void uwb_drp_process_conflict_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, | ||
305 | size_t ielen, struct uwb_dev *src_dev) | ||
306 | { | ||
307 | struct device *dev = &rc->uwb_dev.dev; | ||
308 | struct uwb_ie_hdr *ie_hdr; | ||
309 | struct uwb_ie_drp *drp_ie; | ||
310 | void *ptr; | ||
311 | |||
312 | ptr = drp_evt->ie_data; | ||
313 | for (;;) { | ||
314 | ie_hdr = uwb_ie_next(&ptr, &ielen); | ||
315 | if (!ie_hdr) | ||
316 | break; | ||
317 | |||
318 | drp_ie = container_of(ie_hdr, struct uwb_ie_drp, hdr); | ||
319 | |||
320 | /* FIXME: check if this DRP IE conflicts. */ | ||
321 | } | ||
322 | |||
323 | if (ielen > 0) | ||
324 | dev_warn(dev, "%d octets remaining in DRP notification\n", | ||
325 | (int)ielen); | ||
326 | } | ||
327 | |||
328 | |||
329 | /* | ||
330 | * Terminate all reservations owned by, or targeted at, 'uwb_dev'. | ||
331 | */ | ||
332 | static void uwb_drp_terminate_all(struct uwb_rc *rc, struct uwb_dev *uwb_dev) | ||
333 | { | ||
334 | struct uwb_rsv *rsv; | ||
335 | |||
336 | list_for_each_entry(rsv, &rc->reservations, rc_node) { | ||
337 | if (rsv->owner == uwb_dev | ||
338 | || (rsv->target.type == UWB_RSV_TARGET_DEV && rsv->target.dev == uwb_dev)) | ||
339 | uwb_rsv_remove(rsv); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | |||
344 | /** | 732 | /** |
345 | * uwbd_evt_handle_rc_drp - handle a DRP_IE event | 733 | * uwbd_evt_handle_rc_drp - handle a DRP_IE event |
346 | * @evt: the DRP_IE event from the radio controller | 734 | * @evt: the DRP_IE event from the radio controller |
@@ -381,7 +769,6 @@ int uwbd_evt_handle_rc_drp(struct uwb_event *evt) | |||
381 | size_t ielength, bytes_left; | 769 | size_t ielength, bytes_left; |
382 | struct uwb_dev_addr src_addr; | 770 | struct uwb_dev_addr src_addr; |
383 | struct uwb_dev *src_dev; | 771 | struct uwb_dev *src_dev; |
384 | int reason; | ||
385 | 772 | ||
386 | /* Is there enough data to decode the event (and any IEs in | 773 | /* Is there enough data to decode the event (and any IEs in |
387 | its payload)? */ | 774 | its payload)? */ |
@@ -417,22 +804,8 @@ int uwbd_evt_handle_rc_drp(struct uwb_event *evt) | |||
417 | 804 | ||
418 | mutex_lock(&rc->rsvs_mutex); | 805 | mutex_lock(&rc->rsvs_mutex); |
419 | 806 | ||
420 | reason = uwb_rc_evt_drp_reason(drp_evt); | 807 | /* We do not distinguish from the reason */ |
421 | 808 | uwb_drp_process_all(rc, drp_evt, ielength, src_dev); | |
422 | switch (reason) { | ||
423 | case UWB_DRP_NOTIF_DRP_IE_RCVD: | ||
424 | uwb_drp_process_all(rc, drp_evt, ielength, src_dev); | ||
425 | break; | ||
426 | case UWB_DRP_NOTIF_CONFLICT: | ||
427 | uwb_drp_process_conflict_all(rc, drp_evt, ielength, src_dev); | ||
428 | break; | ||
429 | case UWB_DRP_NOTIF_TERMINATE: | ||
430 | uwb_drp_terminate_all(rc, src_dev); | ||
431 | break; | ||
432 | default: | ||
433 | dev_warn(dev, "ignored DRP event with reason code: %d\n", reason); | ||
434 | break; | ||
435 | } | ||
436 | 809 | ||
437 | mutex_unlock(&rc->rsvs_mutex); | 810 | mutex_unlock(&rc->rsvs_mutex); |
438 | 811 | ||