diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/time-event.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/time-event.c | 103 |
1 files changed, 75 insertions, 28 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index 7fd6fbfbc1b3..c17b74c31398 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include "iwl-prph.h" | 73 | #include "iwl-prph.h" |
74 | 74 | ||
75 | /* A TimeUnit is 1024 microsecond */ | 75 | /* A TimeUnit is 1024 microsecond */ |
76 | #define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024)) | ||
77 | #define MSEC_TO_TU(_msec) (_msec*1000/1024) | 76 | #define MSEC_TO_TU(_msec) (_msec*1000/1024) |
78 | 77 | ||
79 | /* | 78 | /* |
@@ -185,7 +184,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, | |||
185 | } | 184 | } |
186 | } | 185 | } |
187 | 186 | ||
188 | if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_END) { | 187 | if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_END) { |
189 | IWL_DEBUG_TE(mvm, | 188 | IWL_DEBUG_TE(mvm, |
190 | "TE ended - current time %lu, estimated end %lu\n", | 189 | "TE ended - current time %lu, estimated end %lu\n", |
191 | jiffies, te_data->end_jiffies); | 190 | jiffies, te_data->end_jiffies); |
@@ -202,10 +201,9 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, | |||
202 | iwl_mvm_te_check_disconnect(mvm, te_data->vif, | 201 | iwl_mvm_te_check_disconnect(mvm, te_data->vif, |
203 | "No assocation and the time event is over already..."); | 202 | "No assocation and the time event is over already..."); |
204 | iwl_mvm_te_clear_data(mvm, te_data); | 203 | iwl_mvm_te_clear_data(mvm, te_data); |
205 | } else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) { | 204 | } else if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_START) { |
206 | te_data->running = true; | 205 | te_data->running = true; |
207 | te_data->end_jiffies = jiffies + | 206 | te_data->end_jiffies = TU_TO_EXP_TIME(te_data->duration); |
208 | TU_TO_JIFFIES(te_data->duration); | ||
209 | 207 | ||
210 | if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { | 208 | if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { |
211 | set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); | 209 | set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); |
@@ -270,10 +268,67 @@ static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait, | |||
270 | return true; | 268 | return true; |
271 | } | 269 | } |
272 | 270 | ||
271 | /* used to convert from time event API v2 to v1 */ | ||
272 | #define TE_V2_DEP_POLICY_MSK (TE_V2_DEP_OTHER | TE_V2_DEP_TSF |\ | ||
273 | TE_V2_EVENT_SOCIOPATHIC) | ||
274 | static inline u16 te_v2_get_notify(__le16 policy) | ||
275 | { | ||
276 | return le16_to_cpu(policy) & TE_V2_NOTIF_MSK; | ||
277 | } | ||
278 | |||
279 | static inline u16 te_v2_get_dep_policy(__le16 policy) | ||
280 | { | ||
281 | return (le16_to_cpu(policy) & TE_V2_DEP_POLICY_MSK) >> | ||
282 | TE_V2_PLACEMENT_POS; | ||
283 | } | ||
284 | |||
285 | static inline u16 te_v2_get_absence(__le16 policy) | ||
286 | { | ||
287 | return (le16_to_cpu(policy) & TE_V2_ABSENCE) >> TE_V2_ABSENCE_POS; | ||
288 | } | ||
289 | |||
290 | static void iwl_mvm_te_v2_to_v1(const struct iwl_time_event_cmd_v2 *cmd_v2, | ||
291 | struct iwl_time_event_cmd_v1 *cmd_v1) | ||
292 | { | ||
293 | cmd_v1->id_and_color = cmd_v2->id_and_color; | ||
294 | cmd_v1->action = cmd_v2->action; | ||
295 | cmd_v1->id = cmd_v2->id; | ||
296 | cmd_v1->apply_time = cmd_v2->apply_time; | ||
297 | cmd_v1->max_delay = cmd_v2->max_delay; | ||
298 | cmd_v1->depends_on = cmd_v2->depends_on; | ||
299 | cmd_v1->interval = cmd_v2->interval; | ||
300 | cmd_v1->duration = cmd_v2->duration; | ||
301 | if (cmd_v2->repeat == TE_V2_REPEAT_ENDLESS) | ||
302 | cmd_v1->repeat = cpu_to_le32(TE_V1_REPEAT_ENDLESS); | ||
303 | else | ||
304 | cmd_v1->repeat = cpu_to_le32(cmd_v2->repeat); | ||
305 | cmd_v1->max_frags = cpu_to_le32(cmd_v2->max_frags); | ||
306 | cmd_v1->interval_reciprocal = 0; /* unused */ | ||
307 | |||
308 | cmd_v1->dep_policy = cpu_to_le32(te_v2_get_dep_policy(cmd_v2->policy)); | ||
309 | cmd_v1->is_present = cpu_to_le32(!te_v2_get_absence(cmd_v2->policy)); | ||
310 | cmd_v1->notify = cpu_to_le32(te_v2_get_notify(cmd_v2->policy)); | ||
311 | } | ||
312 | |||
313 | static int iwl_mvm_send_time_event_cmd(struct iwl_mvm *mvm, | ||
314 | const struct iwl_time_event_cmd_v2 *cmd) | ||
315 | { | ||
316 | struct iwl_time_event_cmd_v1 cmd_v1; | ||
317 | |||
318 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2) | ||
319 | return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | ||
320 | sizeof(*cmd), cmd); | ||
321 | |||
322 | iwl_mvm_te_v2_to_v1(cmd, &cmd_v1); | ||
323 | return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | ||
324 | sizeof(cmd_v1), &cmd_v1); | ||
325 | } | ||
326 | |||
327 | |||
273 | static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, | 328 | static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, |
274 | struct ieee80211_vif *vif, | 329 | struct ieee80211_vif *vif, |
275 | struct iwl_mvm_time_event_data *te_data, | 330 | struct iwl_mvm_time_event_data *te_data, |
276 | struct iwl_time_event_cmd *te_cmd) | 331 | struct iwl_time_event_cmd_v2 *te_cmd) |
277 | { | 332 | { |
278 | static const u8 time_event_response[] = { TIME_EVENT_CMD }; | 333 | static const u8 time_event_response[] = { TIME_EVENT_CMD }; |
279 | struct iwl_notification_wait wait_time_event; | 334 | struct iwl_notification_wait wait_time_event; |
@@ -309,8 +364,7 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, | |||
309 | ARRAY_SIZE(time_event_response), | 364 | ARRAY_SIZE(time_event_response), |
310 | iwl_mvm_time_event_response, te_data); | 365 | iwl_mvm_time_event_response, te_data); |
311 | 366 | ||
312 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | 367 | ret = iwl_mvm_send_time_event_cmd(mvm, te_cmd); |
313 | sizeof(*te_cmd), te_cmd); | ||
314 | if (ret) { | 368 | if (ret) { |
315 | IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); | 369 | IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); |
316 | iwl_remove_notification(&mvm->notif_wait, &wait_time_event); | 370 | iwl_remove_notification(&mvm->notif_wait, &wait_time_event); |
@@ -337,13 +391,12 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, | |||
337 | { | 391 | { |
338 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 392 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
339 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; | 393 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; |
340 | struct iwl_time_event_cmd time_cmd = {}; | 394 | struct iwl_time_event_cmd_v2 time_cmd = {}; |
341 | 395 | ||
342 | lockdep_assert_held(&mvm->mutex); | 396 | lockdep_assert_held(&mvm->mutex); |
343 | 397 | ||
344 | if (te_data->running && | 398 | if (te_data->running && |
345 | time_after(te_data->end_jiffies, | 399 | time_after(te_data->end_jiffies, TU_TO_EXP_TIME(min_duration))) { |
346 | jiffies + TU_TO_JIFFIES(min_duration))) { | ||
347 | IWL_DEBUG_TE(mvm, "We have enough time in the current TE: %u\n", | 400 | IWL_DEBUG_TE(mvm, "We have enough time in the current TE: %u\n", |
348 | jiffies_to_msecs(te_data->end_jiffies - jiffies)); | 401 | jiffies_to_msecs(te_data->end_jiffies - jiffies)); |
349 | return; | 402 | return; |
@@ -372,17 +425,14 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, | |||
372 | time_cmd.apply_time = | 425 | time_cmd.apply_time = |
373 | cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); | 426 | cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); |
374 | 427 | ||
375 | time_cmd.dep_policy = TE_INDEPENDENT; | 428 | time_cmd.max_frags = TE_V2_FRAG_NONE; |
376 | time_cmd.is_present = cpu_to_le32(1); | ||
377 | time_cmd.max_frags = cpu_to_le32(TE_FRAG_NONE); | ||
378 | time_cmd.max_delay = cpu_to_le32(500); | 429 | time_cmd.max_delay = cpu_to_le32(500); |
379 | /* TODO: why do we need to interval = bi if it is not periodic? */ | 430 | /* TODO: why do we need to interval = bi if it is not periodic? */ |
380 | time_cmd.interval = cpu_to_le32(1); | 431 | time_cmd.interval = cpu_to_le32(1); |
381 | time_cmd.interval_reciprocal = cpu_to_le32(iwl_mvm_reciprocal(1)); | ||
382 | time_cmd.duration = cpu_to_le32(duration); | 432 | time_cmd.duration = cpu_to_le32(duration); |
383 | time_cmd.repeat = cpu_to_le32(1); | 433 | time_cmd.repeat = 1; |
384 | time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START | | 434 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | |
385 | TE_NOTIF_HOST_EVENT_END); | 435 | TE_V2_NOTIF_HOST_EVENT_END); |
386 | 436 | ||
387 | iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 437 | iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
388 | } | 438 | } |
@@ -396,7 +446,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm, | |||
396 | struct iwl_mvm_vif *mvmvif, | 446 | struct iwl_mvm_vif *mvmvif, |
397 | struct iwl_mvm_time_event_data *te_data) | 447 | struct iwl_mvm_time_event_data *te_data) |
398 | { | 448 | { |
399 | struct iwl_time_event_cmd time_cmd = {}; | 449 | struct iwl_time_event_cmd_v2 time_cmd = {}; |
400 | u32 id, uid; | 450 | u32 id, uid; |
401 | int ret; | 451 | int ret; |
402 | 452 | ||
@@ -433,8 +483,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm, | |||
433 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); | 483 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); |
434 | 484 | ||
435 | IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); | 485 | IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); |
436 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | 486 | ret = iwl_mvm_send_time_event_cmd(mvm, &time_cmd); |
437 | sizeof(time_cmd), &time_cmd); | ||
438 | if (WARN_ON(ret)) | 487 | if (WARN_ON(ret)) |
439 | return; | 488 | return; |
440 | } | 489 | } |
@@ -454,7 +503,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
454 | { | 503 | { |
455 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 504 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
456 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; | 505 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; |
457 | struct iwl_time_event_cmd time_cmd = {}; | 506 | struct iwl_time_event_cmd_v2 time_cmd = {}; |
458 | 507 | ||
459 | lockdep_assert_held(&mvm->mutex); | 508 | lockdep_assert_held(&mvm->mutex); |
460 | if (te_data->running) { | 509 | if (te_data->running) { |
@@ -485,8 +534,6 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
485 | } | 534 | } |
486 | 535 | ||
487 | time_cmd.apply_time = cpu_to_le32(0); | 536 | time_cmd.apply_time = cpu_to_le32(0); |
488 | time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT); | ||
489 | time_cmd.is_present = cpu_to_le32(1); | ||
490 | time_cmd.interval = cpu_to_le32(1); | 537 | time_cmd.interval = cpu_to_le32(1); |
491 | 538 | ||
492 | /* | 539 | /* |
@@ -495,12 +542,12 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
495 | * scheduled. To improve the chances of it being scheduled, allow them | 542 | * scheduled. To improve the chances of it being scheduled, allow them |
496 | * to be fragmented, and in addition allow them to be delayed. | 543 | * to be fragmented, and in addition allow them to be delayed. |
497 | */ | 544 | */ |
498 | time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20); | 545 | time_cmd.max_frags = min(MSEC_TO_TU(duration)/50, TE_V2_FRAG_ENDLESS); |
499 | time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); | 546 | time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); |
500 | time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); | 547 | time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); |
501 | time_cmd.repeat = cpu_to_le32(1); | 548 | time_cmd.repeat = 1; |
502 | time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START | | 549 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | |
503 | TE_NOTIF_HOST_EVENT_END); | 550 | TE_V2_NOTIF_HOST_EVENT_END); |
504 | 551 | ||
505 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 552 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
506 | } | 553 | } |