@@ -4317,6 +4317,40 @@ static int ath11k_clear_peer_keys(struct ath11k_vif *arvif,
4317
4317
return first_errno ;
4318
4318
}
4319
4319
4320
+ static int ath11k_set_group_keys (struct ath11k_vif * arvif )
4321
+ {
4322
+ struct ath11k * ar = arvif -> ar ;
4323
+ struct ath11k_base * ab = ar -> ab ;
4324
+ const u8 * addr = arvif -> bssid ;
4325
+ int i , ret , first_errno = 0 ;
4326
+ struct ath11k_peer * peer ;
4327
+
4328
+ spin_lock_bh (& ab -> base_lock );
4329
+ peer = ath11k_peer_find (ab , arvif -> vdev_id , addr );
4330
+ spin_unlock_bh (& ab -> base_lock );
4331
+
4332
+ if (!peer )
4333
+ return - ENOENT ;
4334
+
4335
+ for (i = 0 ; i < ARRAY_SIZE (peer -> keys ); i ++ ) {
4336
+ struct ieee80211_key_conf * key = peer -> keys [i ];
4337
+
4338
+ if (!key || (key -> flags & IEEE80211_KEY_FLAG_PAIRWISE ))
4339
+ continue ;
4340
+
4341
+ ret = ath11k_install_key (arvif , key , SET_KEY , addr ,
4342
+ WMI_KEY_GROUP );
4343
+ if (ret < 0 && first_errno == 0 )
4344
+ first_errno = ret ;
4345
+
4346
+ if (ret < 0 )
4347
+ ath11k_warn (ab , "failed to set group key of idx %d for vdev %d: %d\n" ,
4348
+ i , arvif -> vdev_id , ret );
4349
+ }
4350
+
4351
+ return first_errno ;
4352
+ }
4353
+
4320
4354
static int ath11k_mac_op_set_key (struct ieee80211_hw * hw , enum set_key_cmd cmd ,
4321
4355
struct ieee80211_vif * vif , struct ieee80211_sta * sta ,
4322
4356
struct ieee80211_key_conf * key )
@@ -4326,6 +4360,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
4326
4360
struct ath11k_vif * arvif = ath11k_vif_to_arvif (vif );
4327
4361
struct ath11k_peer * peer ;
4328
4362
struct ath11k_sta * arsta ;
4363
+ bool is_ap_with_no_sta ;
4329
4364
const u8 * peer_addr ;
4330
4365
int ret = 0 ;
4331
4366
u32 flags = 0 ;
@@ -4386,16 +4421,57 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
4386
4421
else
4387
4422
flags |= WMI_KEY_GROUP ;
4388
4423
4389
- ret = ath11k_install_key (arvif , key , cmd , peer_addr , flags );
4390
- if (ret ) {
4391
- ath11k_warn (ab , "ath11k_install_key failed (%d)\n" , ret );
4392
- goto exit ;
4393
- }
4424
+ ath11k_dbg (ar -> ab , ATH11K_DBG_MAC ,
4425
+ "%s for peer %pM on vdev %d flags 0x%X, type = %d, num_sta %d\n" ,
4426
+ cmd == SET_KEY ? "SET_KEY" : "DEL_KEY" , peer_addr , arvif -> vdev_id ,
4427
+ flags , arvif -> vdev_type , arvif -> num_stations );
4428
+
4429
+ /* Allow group key clearing only in AP mode when no stations are
4430
+ * associated. There is a known race condition in firmware where
4431
+ * group addressed packets may be dropped if the key is cleared
4432
+ * and immediately set again during rekey.
4433
+ *
4434
+ * During GTK rekey, mac80211 issues a clear key (if the old key
4435
+ * exists) followed by an install key operation for same key
4436
+ * index. This causes ath11k to send two WMI commands in quick
4437
+ * succession: one to clear the old key and another to install the
4438
+ * new key in the same slot.
4439
+ *
4440
+ * Under certain conditions—especially under high load or time
4441
+ * sensitive scenarios, firmware may process these commands
4442
+ * asynchronously in a way that firmware assumes the key is
4443
+ * cleared whereas hardware has a valid key. This inconsistency
4444
+ * between hardware and firmware leads to group addressed packet
4445
+ * drops after rekey.
4446
+ * Only setting the same key again can restore a valid key in
4447
+ * firmware and allow packets to be transmitted.
4448
+ *
4449
+ * There is a use case where an AP can transition from Secure mode
4450
+ * to open mode without a vdev restart by just deleting all
4451
+ * associated peers and clearing key, Hence allow clear key for
4452
+ * that case alone. Mark arvif->reinstall_group_keys in such cases
4453
+ * and reinstall the same key when the first peer is added,
4454
+ * allowing firmware to recover from the race if it had occurred.
4455
+ */
4394
4456
4395
- ret = ath11k_dp_peer_rx_pn_replay_config (arvif , peer_addr , cmd , key );
4396
- if (ret ) {
4397
- ath11k_warn (ab , "failed to offload PN replay detection %d\n" , ret );
4398
- goto exit ;
4457
+ is_ap_with_no_sta = (vif -> type == NL80211_IFTYPE_AP &&
4458
+ !arvif -> num_stations );
4459
+ if ((flags & WMI_KEY_PAIRWISE ) || cmd == SET_KEY || is_ap_with_no_sta ) {
4460
+ ret = ath11k_install_key (arvif , key , cmd , peer_addr , flags );
4461
+ if (ret ) {
4462
+ ath11k_warn (ab , "ath11k_install_key failed (%d)\n" , ret );
4463
+ goto exit ;
4464
+ }
4465
+
4466
+ ret = ath11k_dp_peer_rx_pn_replay_config (arvif , peer_addr , cmd , key );
4467
+ if (ret ) {
4468
+ ath11k_warn (ab , "failed to offload PN replay detection %d\n" ,
4469
+ ret );
4470
+ goto exit ;
4471
+ }
4472
+
4473
+ if ((flags & WMI_KEY_GROUP ) && cmd == SET_KEY && is_ap_with_no_sta )
4474
+ arvif -> reinstall_group_keys = true;
4399
4475
}
4400
4476
4401
4477
spin_lock_bh (& ab -> base_lock );
@@ -4994,6 +5070,7 @@ static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif,
4994
5070
return - ENOBUFS ;
4995
5071
4996
5072
ar -> num_stations ++ ;
5073
+ arvif -> num_stations ++ ;
4997
5074
4998
5075
return 0 ;
4999
5076
}
@@ -5009,6 +5086,7 @@ static void ath11k_mac_dec_num_stations(struct ath11k_vif *arvif,
5009
5086
return ;
5010
5087
5011
5088
ar -> num_stations -- ;
5089
+ arvif -> num_stations -- ;
5012
5090
}
5013
5091
5014
5092
static u32 ath11k_mac_ieee80211_sta_bw_to_wmi (struct ath11k * ar ,
@@ -9540,6 +9618,21 @@ static int ath11k_mac_station_add(struct ath11k *ar,
9540
9618
goto exit ;
9541
9619
}
9542
9620
9621
+ /* Driver allows the DEL KEY followed by SET KEY sequence for
9622
+ * group keys for only when there is no clients associated, if at
9623
+ * all firmware has entered the race during that window,
9624
+ * reinstalling the same key when the first sta connects will allow
9625
+ * firmware to recover from the race.
9626
+ */
9627
+ if (arvif -> num_stations == 1 && arvif -> reinstall_group_keys ) {
9628
+ ath11k_dbg (ab , ATH11K_DBG_MAC , "set group keys on 1st station add for vdev %d\n" ,
9629
+ arvif -> vdev_id );
9630
+ ret = ath11k_set_group_keys (arvif );
9631
+ if (ret )
9632
+ goto dec_num_station ;
9633
+ arvif -> reinstall_group_keys = false;
9634
+ }
9635
+
9543
9636
arsta -> rx_stats = kzalloc (sizeof (* arsta -> rx_stats ), GFP_KERNEL );
9544
9637
if (!arsta -> rx_stats ) {
9545
9638
ret = - ENOMEM ;
0 commit comments