/** * rsi_core_xmit() - This function transmits the packets received from mac80211 * @common: Pointer to the driver private structure. * @skb: Pointer to the socket buffer structure. * * Return: None. */ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb) { struct rsi_hw *adapter = common->priv; struct ieee80211_tx_info *info; struct skb_info *tx_params; struct ieee80211_hdr *wh = NULL; struct ieee80211_vif *vif; u8 q_num, tid = 0; struct rsi_sta *rsta = NULL; if ((!skb) || (!skb->len)) { rsi_dbg(ERR_ZONE, "%s: Null skb/zero Length packet\n", __func__); goto xmit_fail; } if (common->fsm_state != FSM_MAC_INIT_DONE) { rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__); goto xmit_fail; } if (common->wow_flags & RSI_WOW_ENABLED) { rsi_dbg(ERR_ZONE, "%s: Blocking Tx_packets when WOWLAN is enabled\n", __func__); goto xmit_fail; } info = IEEE80211_SKB_CB(skb); tx_params = (struct skb_info *)info->driver_data; wh = (struct ieee80211_hdr *)&skb->data[0]; tx_params->sta_id = 0; vif = rsi_get_vif(adapter, wh->addr2); if (!vif) goto xmit_fail; tx_params->vif = vif; tx_params->vap_id = ((struct vif_priv *)vif->drv_priv)->vap_id; if ((ieee80211_is_mgmt(wh->frame_control)) || (ieee80211_is_ctl(wh->frame_control)) || (ieee80211_is_qos_nullfunc(wh->frame_control))) { if (ieee80211_is_assoc_req(wh->frame_control) || ieee80211_is_reassoc_req(wh->frame_control)) { struct ieee80211_bss_conf *bss = &vif->bss_conf; common->eapol4_confirm = false; rsi_hal_send_sta_notify_frame(common, RSI_IFTYPE_STATION, STA_CONNECTED, bss->bssid, bss->qos, bss->aid, 0, vif); } q_num = MGMT_SOFT_Q; skb->priority = q_num; if (rsi_prepare_mgmt_desc(common, skb)) { rsi_dbg(ERR_ZONE, "Failed to prepare desc\n"); goto xmit_fail; } } else { if (ieee80211_is_data_qos(wh->frame_control)) { u8 *qos = ieee80211_get_qos_ctl(wh); tid = *qos & IEEE80211_QOS_CTL_TID_MASK; skb->priority = TID_TO_WME_AC(tid); } else { tid = IEEE80211_NONQOS_TID; skb->priority = BE_Q; } q_num = skb->priority; tx_params->tid = tid; if (((vif->type == NL80211_IFTYPE_AP) || (vif->type == NL80211_IFTYPE_P2P_GO)) && (!is_broadcast_ether_addr(wh->addr1)) && (!is_multicast_ether_addr(wh->addr1))) { rsta = rsi_find_sta(common, wh->addr1); if (!rsta) goto xmit_fail; tx_params->sta_id = rsta->sta_id; } else { tx_params->sta_id = 0; } if (rsta) { /* Start aggregation if not done for this tid */ if (!rsta->start_tx_aggr[tid]) { rsta->start_tx_aggr[tid] = true; ieee80211_start_tx_ba_session(rsta->sta, tid, 0); } } if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { q_num = MGMT_SOFT_Q; skb->priority = q_num; } if (rsi_prepare_data_desc(common, skb)) { rsi_dbg(ERR_ZONE, "Failed to prepare data desc\n"); goto xmit_fail; } } if ((q_num < MGMT_SOFT_Q) && ((skb_queue_len(&common->tx_queue[q_num]) + 1) >= DATA_QUEUE_WATER_MARK)) { rsi_dbg(ERR_ZONE, "%s: sw queue full\n", __func__); if (!ieee80211_queue_stopped(adapter->hw, WME_AC(q_num))) ieee80211_stop_queue(adapter->hw, WME_AC(q_num)); rsi_set_event(&common->tx_thread.event); goto xmit_fail; } rsi_core_queue_pkt(common, skb); rsi_dbg(DATA_TX_ZONE, "%s: ===> Scheduling TX thread <===\n", __func__); rsi_set_event(&common->tx_thread.event); return; xmit_fail: rsi_dbg(ERR_ZONE, "%s: Failed to queue packet\n", __func__); /* Dropping pkt here */ ieee80211_free_txskb(common->priv->hw, skb); }
/** * rsi_core_xmit() - This function transmits the packets received from mac80211 * @common: Pointer to the driver private structure. * @skb: Pointer to the socket buffer structure. * * Return: None. */ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb) { struct rsi_hw *adapter = common->priv; struct ieee80211_tx_info *info; struct skb_info *tx_params; struct ieee80211_hdr *tmp_hdr = NULL; u8 q_num, tid = 0; if ((!skb) || (!skb->len)) { rsi_dbg(ERR_ZONE, "%s: Null skb/zero Length packet\n", __func__); goto xmit_fail; } info = IEEE80211_SKB_CB(skb); tx_params = (struct skb_info *)info->driver_data; tmp_hdr = (struct ieee80211_hdr *)&skb->data[0]; if (common->fsm_state != FSM_MAC_INIT_DONE) { rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__); goto xmit_fail; } if ((ieee80211_is_mgmt(tmp_hdr->frame_control)) || (ieee80211_is_ctl(tmp_hdr->frame_control)) || (ieee80211_is_qos_nullfunc(tmp_hdr->frame_control))) { q_num = MGMT_SOFT_Q; skb->priority = q_num; } else { if (ieee80211_is_data_qos(tmp_hdr->frame_control)) { tid = (skb->data[24] & IEEE80211_QOS_TID); skb->priority = TID_TO_WME_AC(tid); } else { tid = IEEE80211_NONQOS_TID; skb->priority = BE_Q; } q_num = skb->priority; tx_params->tid = tid; tx_params->sta_id = 0; } if ((q_num != MGMT_SOFT_Q) && ((skb_queue_len(&common->tx_queue[q_num]) + 1) >= DATA_QUEUE_WATER_MARK)) { rsi_dbg(ERR_ZONE, "%s: sw queue full\n", __func__); if (!ieee80211_queue_stopped(adapter->hw, WME_AC(q_num))) ieee80211_stop_queue(adapter->hw, WME_AC(q_num)); rsi_set_event(&common->tx_thread.event); goto xmit_fail; } rsi_core_queue_pkt(common, skb); rsi_dbg(DATA_TX_ZONE, "%s: ===> Scheduling TX thead <===\n", __func__); rsi_set_event(&common->tx_thread.event); return; xmit_fail: rsi_dbg(ERR_ZONE, "%s: Failed to queue packet\n", __func__); /* Dropping pkt here */ ieee80211_free_txskb(common->priv->hw, skb); }