// SPDX-License-Identifier: GPL-2.0 #include "softmac_core.h" void modify_beacon_params (struct umac_vif *uvif, struct ieee80211_bss_conf *bss_conf) { unsigned int bcn_int = 0; unsigned long bcn_tim_val = 0; int ret = 0; if (uvif->vif->bss_conf.enable_beacon == true) { bcn_int = bss_conf->beacon_int; bcn_tim_val = msecs_to_jiffies(bcn_int - 10); IMG_AP_DBG_PARAM_INCR(enable_beacon, 1); mod_timer(&uvif->bcn_timer, jiffies + bcn_tim_val); CALL_RPU(rpu_prog_vif_beacon_int, uvif->vif_index, uvif->vif->addr, bcn_int); } else { IMG_AP_DBG_PARAM_INCR(del_bcn_timer, 1); del_timer(&uvif->bcn_timer); } prog_rpu_fail: return; } void vif_bcn_timer_expiry(struct timer_list *t) { struct umac_vif *uvif = from_timer(uvif, t, bcn_timer); struct sk_buff *skb, *temp; struct sk_buff_head bcast_frames; IMG_AP_DBG_PARAM_INCR(bcn_timer_expiry, 1); if (uvif->vif->bss_conf.enable_beacon == false) return; if (uvif->vif->type == NL80211_IFTYPE_AP) { temp = skb = ieee80211_beacon_get(uvif->priv->hw, uvif->vif); if (!skb) { /* No beacon, so dont transmit braodcast frames*/ goto reschedule_timer; } skb_queue_head_init(&bcast_frames); skb->priority = 1; skb_queue_tail(&bcast_frames, skb); skb = ieee80211_get_buffered_bc(uvif->priv->hw, uvif->vif); while (skb) { /* Hack: skb->priority is used to indicate more * frames */ skb->priority = 1; skb_queue_tail(&bcast_frames, skb); temp = skb; skb = ieee80211_get_buffered_bc(uvif->priv->hw, uvif->vif); } if (temp) temp->priority = 0; spin_lock_bh(&uvif->priv->bcast_lock); while ((skb = skb_dequeue(&bcast_frames))) { /* For a Beacon queue we will let the frames pass * through irrespective of the current channel context. * The FW will take care of transmitting them in the * appropriate channel. Hence pass the interfaces * channel context instead of the actual current channel * context. */ rpu_tx_frame(skb, NULL, uvif->priv, true); } spin_unlock_bh(&uvif->priv->bcast_lock); } else { skb = ieee80211_beacon_get(uvif->priv->hw, uvif->vif); if (!skb) goto reschedule_timer; /* For a Beacon queue we will let the frames pass through * irrespective of the current channel context. The FW will take * care of transmitting them in the appropriate channel. Hence * pass the interfaces channel context instead of the actual * current channel context. */ rpu_tx_frame(skb, NULL, uvif->priv, true); } reschedule_timer: return; } void init_beacon(struct umac_vif *uvif) { timer_setup(&uvif->bcn_timer, vif_bcn_timer_expiry, 0); } void deinit_beacon(struct umac_vif *uvif) { del_timer(&uvif->bcn_timer); }