aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h226
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c96
3 files changed, 251 insertions, 73 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index bd335f0c40d1..1705d245dbe9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -76,6 +76,7 @@
76 * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS 76 * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
77 * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD 77 * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
78 * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api 78 * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api
79 * @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API.
79 * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six 80 * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
80 * (rather than two) IPv6 addresses 81 * (rather than two) IPv6 addresses
81 * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API 82 * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API
@@ -88,6 +89,7 @@ enum iwl_ucode_tlv_flag {
88 IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), 89 IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4),
89 IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6), 90 IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6),
90 IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), 91 IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8),
92 IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9),
91 IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), 93 IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10),
92 IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11), 94 IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11),
93}; 95};
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 55854a309f94..b1047102ea47 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -499,71 +499,199 @@ enum iwl_time_event_type {
499 TE_MAX 499 TE_MAX
500}; /* MAC_EVENT_TYPE_API_E_VER_1 */ 500}; /* MAC_EVENT_TYPE_API_E_VER_1 */
501 501
502
503
504/* Time event - defines for command API v1 */
505
506/*
507 * @TE_V1_FRAG_NONE: fragmentation of the time event is NOT allowed.
508 * @TE_V1_FRAG_SINGLE: fragmentation of the time event is allowed, but only
509 * the first fragment is scheduled.
510 * @TE_V1_FRAG_DUAL: fragmentation of the time event is allowed, but only
511 * the first 2 fragments are scheduled.
512 * @TE_V1_FRAG_ENDLESS: fragmentation of the time event is allowed, and any
513 * number of fragments are valid.
514 *
515 * Other than the constant defined above, specifying a fragmentation value 'x'
516 * means that the event can be fragmented but only the first 'x' will be
517 * scheduled.
518 */
519enum {
520 TE_V1_FRAG_NONE = 0,
521 TE_V1_FRAG_SINGLE = 1,
522 TE_V1_FRAG_DUAL = 2,
523 TE_V1_FRAG_ENDLESS = 0xffffffff
524};
525
526/* If a Time Event can be fragmented, this is the max number of fragments */
527#define TE_V1_FRAG_MAX_MSK 0x0fffffff
528/* Repeat the time event endlessly (until removed) */
529#define TE_V1_REPEAT_ENDLESS 0xffffffff
530/* If a Time Event has bounded repetitions, this is the maximal value */
531#define TE_V1_REPEAT_MAX_MSK_V1 0x0fffffff
532
502/* Time Event dependencies: none, on another TE, or in a specific time */ 533/* Time Event dependencies: none, on another TE, or in a specific time */
503enum { 534enum {
504 TE_INDEPENDENT = 0, 535 TE_V1_INDEPENDENT = 0,
505 TE_DEP_OTHER = 1, 536 TE_V1_DEP_OTHER = BIT(0),
506 TE_DEP_TSF = 2, 537 TE_V1_DEP_TSF = BIT(1),
507 TE_EVENT_SOCIOPATHIC = 4, 538 TE_V1_EVENT_SOCIOPATHIC = BIT(2),
508}; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */ 539}; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */
540
509/* 541/*
542 * @TE_V1_NOTIF_NONE: no notifications
543 * @TE_V1_NOTIF_HOST_EVENT_START: request/receive notification on event start
544 * @TE_V1_NOTIF_HOST_EVENT_END:request/receive notification on event end
545 * @TE_V1_NOTIF_INTERNAL_EVENT_START: internal FW use
546 * @TE_V1_NOTIF_INTERNAL_EVENT_END: internal FW use.
547 * @TE_V1_NOTIF_HOST_FRAG_START: request/receive notification on frag start
548 * @TE_V1_NOTIF_HOST_FRAG_END:request/receive notification on frag end
549 * @TE_V1_NOTIF_INTERNAL_FRAG_START: internal FW use.
550 * @TE_V1_NOTIF_INTERNAL_FRAG_END: internal FW use.
551 *
510 * Supported Time event notifications configuration. 552 * Supported Time event notifications configuration.
511 * A notification (both event and fragment) includes a status indicating weather 553 * A notification (both event and fragment) includes a status indicating weather
512 * the FW was able to schedule the event or not. For fragment start/end 554 * the FW was able to schedule the event or not. For fragment start/end
513 * notification the status is always success. There is no start/end fragment 555 * notification the status is always success. There is no start/end fragment
514 * notification for monolithic events. 556 * notification for monolithic events.
515 *
516 * @TE_NOTIF_NONE: no notifications
517 * @TE_NOTIF_HOST_EVENT_START: request/receive notification on event start
518 * @TE_NOTIF_HOST_EVENT_END:request/receive notification on event end
519 * @TE_NOTIF_INTERNAL_EVENT_START: internal FW use
520 * @TE_NOTIF_INTERNAL_EVENT_END: internal FW use.
521 * @TE_NOTIF_HOST_FRAG_START: request/receive notification on frag start
522 * @TE_NOTIF_HOST_FRAG_END:request/receive notification on frag end
523 * @TE_NOTIF_INTERNAL_FRAG_START: internal FW use.
524 * @TE_NOTIF_INTERNAL_FRAG_END: internal FW use.
525 */ 557 */
526enum { 558enum {
527 TE_NOTIF_NONE = 0, 559 TE_V1_NOTIF_NONE = 0,
528 TE_NOTIF_HOST_EVENT_START = 0x1, 560 TE_V1_NOTIF_HOST_EVENT_START = BIT(0),
529 TE_NOTIF_HOST_EVENT_END = 0x2, 561 TE_V1_NOTIF_HOST_EVENT_END = BIT(1),
530 TE_NOTIF_INTERNAL_EVENT_START = 0x4, 562 TE_V1_NOTIF_INTERNAL_EVENT_START = BIT(2),
531 TE_NOTIF_INTERNAL_EVENT_END = 0x8, 563 TE_V1_NOTIF_INTERNAL_EVENT_END = BIT(3),
532 TE_NOTIF_HOST_FRAG_START = 0x10, 564 TE_V1_NOTIF_HOST_FRAG_START = BIT(4),
533 TE_NOTIF_HOST_FRAG_END = 0x20, 565 TE_V1_NOTIF_HOST_FRAG_END = BIT(5),
534 TE_NOTIF_INTERNAL_FRAG_START = 0x40, 566 TE_V1_NOTIF_INTERNAL_FRAG_START = BIT(6),
535 TE_NOTIF_INTERNAL_FRAG_END = 0x80 567 TE_V1_NOTIF_INTERNAL_FRAG_END = BIT(7),
536}; /* MAC_EVENT_ACTION_API_E_VER_2 */ 568}; /* MAC_EVENT_ACTION_API_E_VER_2 */
537 569
570
571/**
572 * struct iwl_time_event_cmd_api_v1 - configuring Time Events
573 * with struct MAC_TIME_EVENT_DATA_API_S_VER_1 (see also
574 * with version 2. determined by IWL_UCODE_TLV_FLAGS)
575 * ( TIME_EVENT_CMD = 0x29 )
576 * @id_and_color: ID and color of the relevant MAC
577 * @action: action to perform, one of FW_CTXT_ACTION_*
578 * @id: this field has two meanings, depending on the action:
579 * If the action is ADD, then it means the type of event to add.
580 * For all other actions it is the unique event ID assigned when the
581 * event was added by the FW.
582 * @apply_time: When to start the Time Event (in GP2)
583 * @max_delay: maximum delay to event's start (apply time), in TU
584 * @depends_on: the unique ID of the event we depend on (if any)
585 * @interval: interval between repetitions, in TU
586 * @interval_reciprocal: 2^32 / interval
587 * @duration: duration of event in TU
588 * @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS
589 * @dep_policy: one of TE_V1_INDEPENDENT, TE_V1_DEP_OTHER, TE_V1_DEP_TSF
590 * and TE_V1_EVENT_SOCIOPATHIC
591 * @is_present: 0 or 1, are we present or absent during the Time Event
592 * @max_frags: maximal number of fragments the Time Event can be divided to
593 * @notify: notifications using TE_V1_NOTIF_* (whom to notify when)
594 */
595struct iwl_time_event_cmd_v1 {
596 /* COMMON_INDEX_HDR_API_S_VER_1 */
597 __le32 id_and_color;
598 __le32 action;
599 __le32 id;
600 /* MAC_TIME_EVENT_DATA_API_S_VER_1 */
601 __le32 apply_time;
602 __le32 max_delay;
603 __le32 dep_policy;
604 __le32 depends_on;
605 __le32 is_present;
606 __le32 max_frags;
607 __le32 interval;
608 __le32 interval_reciprocal;
609 __le32 duration;
610 __le32 repeat;
611 __le32 notify;
612} __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_1 */
613
614
615/* Time event - defines for command API v2 */
616
538/* 617/*
539 * @TE_FRAG_NONE: fragmentation of the time event is NOT allowed. 618 * @TE_V2_FRAG_NONE: fragmentation of the time event is NOT allowed.
540 * @TE_FRAG_SINGLE: fragmentation of the time event is allowed, but only 619 * @TE_V2_FRAG_SINGLE: fragmentation of the time event is allowed, but only
541 * the first fragment is scheduled. 620 * the first fragment is scheduled.
542 * @TE_FRAG_DUAL: fragmentation of the time event is allowed, but only 621 * @TE_V2_FRAG_DUAL: fragmentation of the time event is allowed, but only
543 * the first 2 fragments are scheduled. 622 * the first 2 fragments are scheduled.
544 * @TE_FRAG_ENDLESS: fragmentation of the time event is allowed, and any number 623 * @TE_V2_FRAG_ENDLESS: fragmentation of the time event is allowed, and any
545 * of fragments are valid. 624 * number of fragments are valid.
546 * 625 *
547 * Other than the constant defined above, specifying a fragmentation value 'x' 626 * Other than the constant defined above, specifying a fragmentation value 'x'
548 * means that the event can be fragmented but only the first 'x' will be 627 * means that the event can be fragmented but only the first 'x' will be
549 * scheduled. 628 * scheduled.
550 */ 629 */
551enum { 630enum {
552 TE_FRAG_NONE = 0, 631 TE_V2_FRAG_NONE = 0,
553 TE_FRAG_SINGLE = 1, 632 TE_V2_FRAG_SINGLE = 1,
554 TE_FRAG_DUAL = 2, 633 TE_V2_FRAG_DUAL = 2,
555 TE_FRAG_ENDLESS = 0xffffffff 634 TE_V2_FRAG_MAX = 0xfe,
635 TE_V2_FRAG_ENDLESS = 0xff
556}; 636};
557 637
558/* Repeat the time event endlessly (until removed) */ 638/* Repeat the time event endlessly (until removed) */
559#define TE_REPEAT_ENDLESS (0xffffffff) 639#define TE_V2_REPEAT_ENDLESS 0xff
560/* If a Time Event has bounded repetitions, this is the maximal value */ 640/* If a Time Event has bounded repetitions, this is the maximal value */
561#define TE_REPEAT_MAX_MSK (0x0fffffff) 641#define TE_V2_REPEAT_MAX 0xfe
562/* If a Time Event can be fragmented, this is the max number of fragments */ 642
563#define TE_FRAG_MAX_MSK (0x0fffffff) 643#define TE_V2_PLACEMENT_POS 12
644#define TE_V2_ABSENCE_POS 15
645
646/* Time event policy values (for time event cmd api v2)
647 * A notification (both event and fragment) includes a status indicating weather
648 * the FW was able to schedule the event or not. For fragment start/end
649 * notification the status is always success. There is no start/end fragment
650 * notification for monolithic events.
651 *
652 * @TE_V2_DEFAULT_POLICY: independent, social, present, unoticable
653 * @TE_V2_NOTIF_HOST_EVENT_START: request/receive notification on event start
654 * @TE_V2_NOTIF_HOST_EVENT_END:request/receive notification on event end
655 * @TE_V2_NOTIF_INTERNAL_EVENT_START: internal FW use
656 * @TE_V2_NOTIF_INTERNAL_EVENT_END: internal FW use.
657 * @TE_V2_NOTIF_HOST_FRAG_START: request/receive notification on frag start
658 * @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end
659 * @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use.
660 * @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use.
661 * @TE_V2_DEP_OTHER: depends on another time event
662 * @TE_V2_DEP_TSF: depends on a specific time
663 * @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC
664 * @TE_V2_ABSENCE: are we present or absent during the Time Event.
665 */
666enum {
667 TE_V2_DEFAULT_POLICY = 0x0,
668
669 /* notifications (event start/stop, fragment start/stop) */
670 TE_V2_NOTIF_HOST_EVENT_START = BIT(0),
671 TE_V2_NOTIF_HOST_EVENT_END = BIT(1),
672 TE_V2_NOTIF_INTERNAL_EVENT_START = BIT(2),
673 TE_V2_NOTIF_INTERNAL_EVENT_END = BIT(3),
674
675 TE_V2_NOTIF_HOST_FRAG_START = BIT(4),
676 TE_V2_NOTIF_HOST_FRAG_END = BIT(5),
677 TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6),
678 TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7),
679
680 TE_V2_NOTIF_MSK = 0xff,
681
682 /* placement characteristics */
683 TE_V2_DEP_OTHER = BIT(TE_V2_PLACEMENT_POS),
684 TE_V2_DEP_TSF = BIT(TE_V2_PLACEMENT_POS + 1),
685 TE_V2_EVENT_SOCIOPATHIC = BIT(TE_V2_PLACEMENT_POS + 2),
686
687 /* are we present or absent during the Time Event. */
688 TE_V2_ABSENCE = BIT(TE_V2_ABSENCE_POS),
689};
564 690
565/** 691/**
566 * struct iwl_time_event_cmd - configuring Time Events 692 * struct iwl_time_event_cmd_api_v2 - configuring Time Events
693 * with struct MAC_TIME_EVENT_DATA_API_S_VER_2 (see also
694 * with version 1. determined by IWL_UCODE_TLV_FLAGS)
567 * ( TIME_EVENT_CMD = 0x29 ) 695 * ( TIME_EVENT_CMD = 0x29 )
568 * @id_and_color: ID and color of the relevant MAC 696 * @id_and_color: ID and color of the relevant MAC
569 * @action: action to perform, one of FW_CTXT_ACTION_* 697 * @action: action to perform, one of FW_CTXT_ACTION_*
@@ -575,32 +703,30 @@ enum {
575 * @max_delay: maximum delay to event's start (apply time), in TU 703 * @max_delay: maximum delay to event's start (apply time), in TU
576 * @depends_on: the unique ID of the event we depend on (if any) 704 * @depends_on: the unique ID of the event we depend on (if any)
577 * @interval: interval between repetitions, in TU 705 * @interval: interval between repetitions, in TU
578 * @interval_reciprocal: 2^32 / interval
579 * @duration: duration of event in TU 706 * @duration: duration of event in TU
580 * @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS 707 * @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS
581 * @dep_policy: one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF
582 * @is_present: 0 or 1, are we present or absent during the Time Event
583 * @max_frags: maximal number of fragments the Time Event can be divided to 708 * @max_frags: maximal number of fragments the Time Event can be divided to
584 * @notify: notifications using TE_NOTIF_* (whom to notify when) 709 * @policy: defines whether uCode shall notify the host or other uCode modules
710 * on event and/or fragment start and/or end
711 * using one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF
712 * TE_EVENT_SOCIOPATHIC
713 * using TE_ABSENCE and using TE_NOTIF_*
585 */ 714 */
586struct iwl_time_event_cmd { 715struct iwl_time_event_cmd_v2 {
587 /* COMMON_INDEX_HDR_API_S_VER_1 */ 716 /* COMMON_INDEX_HDR_API_S_VER_1 */
588 __le32 id_and_color; 717 __le32 id_and_color;
589 __le32 action; 718 __le32 action;
590 __le32 id; 719 __le32 id;
591 /* MAC_TIME_EVENT_DATA_API_S_VER_1 */ 720 /* MAC_TIME_EVENT_DATA_API_S_VER_2 */
592 __le32 apply_time; 721 __le32 apply_time;
593 __le32 max_delay; 722 __le32 max_delay;
594 __le32 dep_policy;
595 __le32 depends_on; 723 __le32 depends_on;
596 __le32 is_present;
597 __le32 max_frags;
598 __le32 interval; 724 __le32 interval;
599 __le32 interval_reciprocal;
600 __le32 duration; 725 __le32 duration;
601 __le32 repeat; 726 u8 repeat;
602 __le32 notify; 727 u8 max_frags;
603} __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_1 */ 728 __le16 policy;
729} __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_2 */
604 730
605/** 731/**
606 * struct iwl_time_event_resp - response structure to iwl_time_event_cmd 732 * struct iwl_time_event_resp - response structure to iwl_time_event_cmd
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index ad9bbca99213..7ed94a089d5e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -166,7 +166,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
166 WARN_ONCE(!le32_to_cpu(notif->status), 166 WARN_ONCE(!le32_to_cpu(notif->status),
167 "Failed to schedule time event\n"); 167 "Failed to schedule time event\n");
168 168
169 if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_END) { 169 if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_END) {
170 IWL_DEBUG_TE(mvm, 170 IWL_DEBUG_TE(mvm,
171 "TE ended - current time %lu, estimated end %lu\n", 171 "TE ended - current time %lu, estimated end %lu\n",
172 jiffies, te_data->end_jiffies); 172 jiffies, te_data->end_jiffies);
@@ -189,7 +189,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
189 } 189 }
190 190
191 iwl_mvm_te_clear_data(mvm, te_data); 191 iwl_mvm_te_clear_data(mvm, te_data);
192 } else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) { 192 } else if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_START) {
193 te_data->running = true; 193 te_data->running = true;
194 te_data->end_jiffies = jiffies + 194 te_data->end_jiffies = jiffies +
195 TU_TO_JIFFIES(te_data->duration); 195 TU_TO_JIFFIES(te_data->duration);
@@ -257,10 +257,67 @@ static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait,
257 return true; 257 return true;
258} 258}
259 259
260/* used to convert from time event API v2 to v1 */
261#define TE_V2_DEP_POLICY_MSK (TE_V2_DEP_OTHER | TE_V2_DEP_TSF |\
262 TE_V2_EVENT_SOCIOPATHIC)
263static inline u16 te_v2_get_notify(__le16 policy)
264{
265 return le16_to_cpu(policy) & TE_V2_NOTIF_MSK;
266}
267
268static inline u16 te_v2_get_dep_policy(__le16 policy)
269{
270 return (le16_to_cpu(policy) & TE_V2_DEP_POLICY_MSK) >>
271 TE_V2_PLACEMENT_POS;
272}
273
274static inline u16 te_v2_get_absence(__le16 policy)
275{
276 return (le16_to_cpu(policy) & TE_V2_ABSENCE) >> TE_V2_ABSENCE_POS;
277}
278
279static void iwl_mvm_te_v2_to_v1(const struct iwl_time_event_cmd_v2 *cmd_v2,
280 struct iwl_time_event_cmd_v1 *cmd_v1)
281{
282 cmd_v1->id_and_color = cmd_v2->id_and_color;
283 cmd_v1->action = cmd_v2->action;
284 cmd_v1->id = cmd_v2->id;
285 cmd_v1->apply_time = cmd_v2->apply_time;
286 cmd_v1->max_delay = cmd_v2->max_delay;
287 cmd_v1->depends_on = cmd_v2->depends_on;
288 cmd_v1->interval = cmd_v2->interval;
289 cmd_v1->duration = cmd_v2->duration;
290 if (cmd_v2->repeat == TE_V2_REPEAT_ENDLESS)
291 cmd_v1->repeat = cpu_to_le32(TE_V1_REPEAT_ENDLESS);
292 else
293 cmd_v1->repeat = cpu_to_le32(cmd_v2->repeat);
294 cmd_v1->max_frags = cpu_to_le32(cmd_v2->max_frags);
295 cmd_v1->interval_reciprocal = 0; /* unused */
296
297 cmd_v1->dep_policy = cpu_to_le32(te_v2_get_dep_policy(cmd_v2->policy));
298 cmd_v1->is_present = cpu_to_le32(!te_v2_get_absence(cmd_v2->policy));
299 cmd_v1->notify = cpu_to_le32(te_v2_get_notify(cmd_v2->policy));
300}
301
302static int iwl_mvm_send_time_event_cmd(struct iwl_mvm *mvm,
303 const struct iwl_time_event_cmd_v2 *cmd)
304{
305 struct iwl_time_event_cmd_v1 cmd_v1;
306
307 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2)
308 return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
309 sizeof(*cmd), cmd);
310
311 iwl_mvm_te_v2_to_v1(cmd, &cmd_v1);
312 return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
313 sizeof(cmd_v1), &cmd_v1);
314}
315
316
260static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, 317static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
261 struct ieee80211_vif *vif, 318 struct ieee80211_vif *vif,
262 struct iwl_mvm_time_event_data *te_data, 319 struct iwl_mvm_time_event_data *te_data,
263 struct iwl_time_event_cmd *te_cmd) 320 struct iwl_time_event_cmd_v2 *te_cmd)
264{ 321{
265 static const u8 time_event_response[] = { TIME_EVENT_CMD }; 322 static const u8 time_event_response[] = { TIME_EVENT_CMD };
266 struct iwl_notification_wait wait_time_event; 323 struct iwl_notification_wait wait_time_event;
@@ -296,8 +353,7 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
296 ARRAY_SIZE(time_event_response), 353 ARRAY_SIZE(time_event_response),
297 iwl_mvm_time_event_response, te_data); 354 iwl_mvm_time_event_response, te_data);
298 355
299 ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, 356 ret = iwl_mvm_send_time_event_cmd(mvm, te_cmd);
300 sizeof(*te_cmd), te_cmd);
301 if (ret) { 357 if (ret) {
302 IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); 358 IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);
303 iwl_remove_notification(&mvm->notif_wait, &wait_time_event); 359 iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
@@ -324,7 +380,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
324{ 380{
325 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 381 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
326 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 382 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
327 struct iwl_time_event_cmd time_cmd = {}; 383 struct iwl_time_event_cmd_v2 time_cmd = {};
328 384
329 lockdep_assert_held(&mvm->mutex); 385 lockdep_assert_held(&mvm->mutex);
330 386
@@ -359,17 +415,14 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
359 time_cmd.apply_time = 415 time_cmd.apply_time =
360 cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); 416 cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG));
361 417
362 time_cmd.dep_policy = TE_INDEPENDENT; 418 time_cmd.max_frags = TE_V2_FRAG_NONE;
363 time_cmd.is_present = cpu_to_le32(1);
364 time_cmd.max_frags = cpu_to_le32(TE_FRAG_NONE);
365 time_cmd.max_delay = cpu_to_le32(500); 419 time_cmd.max_delay = cpu_to_le32(500);
366 /* TODO: why do we need to interval = bi if it is not periodic? */ 420 /* TODO: why do we need to interval = bi if it is not periodic? */
367 time_cmd.interval = cpu_to_le32(1); 421 time_cmd.interval = cpu_to_le32(1);
368 time_cmd.interval_reciprocal = cpu_to_le32(iwl_mvm_reciprocal(1));
369 time_cmd.duration = cpu_to_le32(duration); 422 time_cmd.duration = cpu_to_le32(duration);
370 time_cmd.repeat = cpu_to_le32(1); 423 time_cmd.repeat = 1;
371 time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START | 424 time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
372 TE_NOTIF_HOST_EVENT_END); 425 TE_V2_NOTIF_HOST_EVENT_END);
373 426
374 iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); 427 iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
375} 428}
@@ -383,7 +436,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
383 struct iwl_mvm_vif *mvmvif, 436 struct iwl_mvm_vif *mvmvif,
384 struct iwl_mvm_time_event_data *te_data) 437 struct iwl_mvm_time_event_data *te_data)
385{ 438{
386 struct iwl_time_event_cmd time_cmd = {}; 439 struct iwl_time_event_cmd_v2 time_cmd = {};
387 u32 id, uid; 440 u32 id, uid;
388 int ret; 441 int ret;
389 442
@@ -420,8 +473,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
420 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); 473 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
421 474
422 IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); 475 IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id));
423 ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, 476 ret = iwl_mvm_send_time_event_cmd(mvm, &time_cmd);
424 sizeof(time_cmd), &time_cmd);
425 if (WARN_ON(ret)) 477 if (WARN_ON(ret))
426 return; 478 return;
427} 479}
@@ -441,7 +493,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
441{ 493{
442 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 494 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
443 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 495 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
444 struct iwl_time_event_cmd time_cmd = {}; 496 struct iwl_time_event_cmd_v2 time_cmd = {};
445 497
446 lockdep_assert_held(&mvm->mutex); 498 lockdep_assert_held(&mvm->mutex);
447 if (te_data->running) { 499 if (te_data->running) {
@@ -472,8 +524,6 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
472 } 524 }
473 525
474 time_cmd.apply_time = cpu_to_le32(0); 526 time_cmd.apply_time = cpu_to_le32(0);
475 time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT);
476 time_cmd.is_present = cpu_to_le32(1);
477 time_cmd.interval = cpu_to_le32(1); 527 time_cmd.interval = cpu_to_le32(1);
478 528
479 /* 529 /*
@@ -482,12 +532,12 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
482 * scheduled. To improve the chances of it being scheduled, allow them 532 * scheduled. To improve the chances of it being scheduled, allow them
483 * to be fragmented, and in addition allow them to be delayed. 533 * to be fragmented, and in addition allow them to be delayed.
484 */ 534 */
485 time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20); 535 time_cmd.max_frags = min(MSEC_TO_TU(duration)/50, TE_V2_FRAG_ENDLESS);
486 time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); 536 time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2));
487 time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); 537 time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration));
488 time_cmd.repeat = cpu_to_le32(1); 538 time_cmd.repeat = 1;
489 time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START | 539 time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
490 TE_NOTIF_HOST_EVENT_END); 540 TE_V2_NOTIF_HOST_EVENT_END);
491 541
492 return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); 542 return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
493} 543}