@@ -7765,6 +7765,56 @@ static void ath11k_wmi_twt_add_dialog_event(struct ath11k_base *ab,
77657765 kfree (tb );
77667766}
77677767
7768+ static void ath11k_wmi_gtk_offload_status_event (struct ath11k_base * ab ,
7769+ struct sk_buff * skb )
7770+ {
7771+ const void * * tb ;
7772+ const struct wmi_gtk_offload_status_event * ev ;
7773+ struct ath11k_vif * arvif ;
7774+ __be64 replay_ctr_be ;
7775+ u64 replay_ctr ;
7776+ int ret ;
7777+
7778+ tb = ath11k_wmi_tlv_parse_alloc (ab , skb -> data , skb -> len , GFP_ATOMIC );
7779+ if (IS_ERR (tb )) {
7780+ ret = PTR_ERR (tb );
7781+ ath11k_warn (ab , "failed to parse tlv: %d\n" , ret );
7782+ return ;
7783+ }
7784+
7785+ ev = tb [WMI_TAG_GTK_OFFLOAD_STATUS_EVENT ];
7786+ if (!ev ) {
7787+ ath11k_warn (ab , "failed to fetch gtk offload status ev" );
7788+ kfree (tb );
7789+ return ;
7790+ }
7791+
7792+ arvif = ath11k_mac_get_arvif_by_vdev_id (ab , ev -> vdev_id );
7793+ if (!arvif ) {
7794+ ath11k_warn (ab , "failed to get arvif for vdev_id:%d\n" ,
7795+ ev -> vdev_id );
7796+ kfree (tb );
7797+ return ;
7798+ }
7799+
7800+ ath11k_dbg (ab , ATH11K_DBG_WMI , "wmi gtk offload event refresh_cnt %d\n" ,
7801+ ev -> refresh_cnt );
7802+ ath11k_dbg_dump (ab , ATH11K_DBG_WMI , "replay_cnt" ,
7803+ NULL , ev -> replay_ctr .counter , GTK_REPLAY_COUNTER_BYTES );
7804+
7805+ replay_ctr = ev -> replay_ctr .word1 ;
7806+ replay_ctr = (replay_ctr << 32 ) | ev -> replay_ctr .word0 ;
7807+ arvif -> rekey_data .replay_ctr = replay_ctr ;
7808+
7809+ /* supplicant expects big-endian replay counter */
7810+ replay_ctr_be = cpu_to_be64 (replay_ctr );
7811+
7812+ ieee80211_gtk_rekey_notify (arvif -> vif , arvif -> bssid ,
7813+ (void * )& replay_ctr_be , GFP_KERNEL );
7814+
7815+ kfree (tb );
7816+ }
7817+
77687818static void ath11k_wmi_tlv_op_rx (struct ath11k_base * ab , struct sk_buff * skb )
77697819{
77707820 struct wmi_cmd_hdr * cmd_hdr ;
@@ -7896,6 +7946,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
78967946 case WMI_DIAG_EVENTID :
78977947 ath11k_wmi_diag_event (ab , skb );
78987948 break ;
7949+ case WMI_GTK_OFFLOAD_STATUS_EVENTID :
7950+ ath11k_wmi_gtk_offload_status_event (ab , skb );
7951+ break ;
78997952 /* TODO: Add remaining events */
79007953 default :
79017954 ath11k_dbg (ab , ATH11K_DBG_WMI , "Unknown eventid: 0x%x\n" , id );
@@ -8735,3 +8788,69 @@ int ath11k_wmi_arp_ns_offload(struct ath11k *ar,
87358788
87368789 return ath11k_wmi_cmd_send (ar -> wmi , skb , WMI_SET_ARP_NS_OFFLOAD_CMDID );
87378790}
8791+
8792+ int ath11k_wmi_gtk_rekey_offload (struct ath11k * ar ,
8793+ struct ath11k_vif * arvif , bool enable )
8794+ {
8795+ struct wmi_gtk_rekey_offload_cmd * cmd ;
8796+ struct ath11k_rekey_data * rekey_data = & arvif -> rekey_data ;
8797+ int len ;
8798+ struct sk_buff * skb ;
8799+ __le64 replay_ctr ;
8800+
8801+ len = sizeof (* cmd );
8802+ skb = ath11k_wmi_alloc_skb (ar -> wmi -> wmi_ab , len );
8803+ if (!skb )
8804+ return - ENOMEM ;
8805+
8806+ cmd = (struct wmi_gtk_rekey_offload_cmd * )skb -> data ;
8807+ cmd -> tlv_header = FIELD_PREP (WMI_TLV_TAG , WMI_TAG_GTK_OFFLOAD_CMD ) |
8808+ FIELD_PREP (WMI_TLV_LEN , sizeof (* cmd ) - TLV_HDR_SIZE );
8809+
8810+ cmd -> vdev_id = arvif -> vdev_id ;
8811+
8812+ if (enable ) {
8813+ cmd -> flags = GTK_OFFLOAD_ENABLE_OPCODE ;
8814+
8815+ /* the length in rekey_data and cmd is equal */
8816+ memcpy (cmd -> kck , rekey_data -> kck , sizeof (cmd -> kck ));
8817+ ath11k_ce_byte_swap (cmd -> kck , GTK_OFFLOAD_KEK_BYTES );
8818+ memcpy (cmd -> kek , rekey_data -> kek , sizeof (cmd -> kek ));
8819+ ath11k_ce_byte_swap (cmd -> kek , GTK_OFFLOAD_KEK_BYTES );
8820+
8821+ replay_ctr = cpu_to_le64 (rekey_data -> replay_ctr );
8822+ memcpy (cmd -> replay_ctr , & replay_ctr ,
8823+ sizeof (replay_ctr ));
8824+ ath11k_ce_byte_swap (cmd -> replay_ctr , GTK_REPLAY_COUNTER_BYTES );
8825+ } else {
8826+ cmd -> flags = GTK_OFFLOAD_DISABLE_OPCODE ;
8827+ }
8828+
8829+ ath11k_dbg (ar -> ab , ATH11K_DBG_WMI , "offload gtk rekey vdev: %d %d\n" ,
8830+ arvif -> vdev_id , enable );
8831+ return ath11k_wmi_cmd_send (ar -> wmi , skb , WMI_GTK_OFFLOAD_CMDID );
8832+ }
8833+
8834+ int ath11k_wmi_gtk_rekey_getinfo (struct ath11k * ar ,
8835+ struct ath11k_vif * arvif )
8836+ {
8837+ struct wmi_gtk_rekey_offload_cmd * cmd ;
8838+ int len ;
8839+ struct sk_buff * skb ;
8840+
8841+ len = sizeof (* cmd );
8842+ skb = ath11k_wmi_alloc_skb (ar -> wmi -> wmi_ab , len );
8843+ if (!skb )
8844+ return - ENOMEM ;
8845+
8846+ cmd = (struct wmi_gtk_rekey_offload_cmd * )skb -> data ;
8847+ cmd -> tlv_header = FIELD_PREP (WMI_TLV_TAG , WMI_TAG_GTK_OFFLOAD_CMD ) |
8848+ FIELD_PREP (WMI_TLV_LEN , sizeof (* cmd ) - TLV_HDR_SIZE );
8849+
8850+ cmd -> vdev_id = arvif -> vdev_id ;
8851+ cmd -> flags = GTK_OFFLOAD_REQUEST_STATUS_OPCODE ;
8852+
8853+ ath11k_dbg (ar -> ab , ATH11K_DBG_WMI , "get gtk rekey vdev_id: %d\n" ,
8854+ arvif -> vdev_id );
8855+ return ath11k_wmi_cmd_send (ar -> wmi , skb , WMI_GTK_OFFLOAD_CMDID );
8856+ }
0 commit comments