/** * rsi_rx_done_handler() - This function is called when a packet is received * from USB stack. This is callback to receive done. * @urb: Received URB. * * Return: None. */ static void rsi_rx_done_handler(struct urb *urb) { struct rx_usb_ctrl_block *rx_cb = urb->context; struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)rx_cb->data; int status = -EINVAL; if (urb->status) goto out; if (urb->actual_length <= 0 || urb->actual_length > rx_cb->rx_skb->len) { rsi_dbg(INFO_ZONE, "%s: Invalid packet length = %d\n", __func__, urb->actual_length); goto out; } if (skb_queue_len(&dev->rx_q) >= RSI_MAX_RX_PKTS) { rsi_dbg(INFO_ZONE, "Max RX packets reached\n"); goto out; } skb_trim(rx_cb->rx_skb, urb->actual_length); skb_queue_tail(&dev->rx_q, rx_cb->rx_skb); rsi_set_event(&dev->rx_thread.event); status = 0; out: if (rsi_rx_urb_submit(dev->priv, rx_cb->ep_num)) rsi_dbg(ERR_ZONE, "%s: Failed in urb submission", __func__); if (status) dev_kfree_skb(rx_cb->rx_skb); }
/** * rsi_rx_done_handler() - This function is called when a packet is received * from USB stack. This is callback to recieve done. * @urb: Received URB. * * Return: None. */ static void rsi_rx_done_handler(struct urb *urb) { struct rsi_hw *adapter = urb->context; struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; if (urb->status) return; rsi_set_event(&dev->rx_thread.event); }
/** * rsi_send_internal_mgmt_frame() - This function sends management frames to * firmware.Also schedules packet to queue * for transmission. * @common: Pointer to the driver private structure. * @skb: Pointer to the socket buffer structure. * * Return: 0 on success, -1 on failure. */ static int rsi_send_internal_mgmt_frame(struct rsi_common *common, struct sk_buff *skb) { struct skb_info *tx_params; if (skb == NULL) { rsi_dbg(ERR_ZONE, "%s: Unable to allocate skb\n", __func__); return -ENOMEM; } tx_params = (struct skb_info *)&IEEE80211_SKB_CB(skb)->driver_data; tx_params->flags |= INTERNAL_MGMT_PKT; skb_queue_tail(&common->tx_queue[MGMT_SOFT_Q], skb); rsi_set_event(&common->tx_thread.event); return 0; }
int rsi_coex_send_pkt(void *priv, struct sk_buff *skb, u8 hal_queue) { struct rsi_common *common = (struct rsi_common *)priv; struct rsi_coex_ctrl_block *coex_cb = (struct rsi_coex_ctrl_block *)common->coex_cb; struct skb_info *tx_params = NULL; enum rsi_coex_queues coex_q; int status; coex_q = rsi_map_coex_q(hal_queue); if (coex_q == RSI_COEX_Q_INVALID) { rsi_dbg(ERR_ZONE, "Invalid coex queue\n"); return -EINVAL; } if (coex_q != RSI_COEX_Q_COMMON && coex_q != RSI_COEX_Q_WLAN) { skb_queue_tail(&coex_cb->coex_tx_qs[coex_q], skb); rsi_set_event(&coex_cb->coex_tx_thread.event); return 0; } if (common->iface_down) { tx_params = (struct skb_info *)&IEEE80211_SKB_CB(skb)->driver_data; if (!(tx_params->flags & INTERNAL_MGMT_PKT)) { rsi_indicate_tx_status(common->priv, skb, -EINVAL); return 0; } } /* Send packet to hal */ if (skb->priority == MGMT_SOFT_Q) status = rsi_send_mgmt_pkt(common, skb); else status = rsi_send_data_pkt(common, skb); return status; }
/** * 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); }