1 /* 2 * This file is part of wl18xx 3 * 4 * Copyright (C) 2011 Texas Instruments Inc. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * version 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18 * 02110-1301 USA 19 * 20 */ 21 22 #include "../wlcore/wlcore.h" 23 #include "../wlcore/cmd.h" 24 #include "../wlcore/debug.h" 25 #include "../wlcore/acx.h" 26 #include "../wlcore/tx.h" 27 28 #include "wl18xx.h" 29 #include "tx.h" 30 31 static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte) 32 { 33 struct ieee80211_tx_info *info; 34 struct sk_buff *skb; 35 int id = tx_stat_byte & WL18XX_TX_STATUS_DESC_ID_MASK; 36 bool tx_success; 37 38 /* check for id legality */ 39 if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) { 40 wl1271_warning("illegal id in tx completion: %d", id); 41 return; 42 } 43 44 /* a zero bit indicates Tx success */ 45 tx_success = !(tx_stat_byte & BIT(WL18XX_TX_STATUS_STAT_BIT_IDX)); 46 47 48 skb = wl->tx_frames[id]; 49 info = IEEE80211_SKB_CB(skb); 50 51 if (wl12xx_is_dummy_packet(wl, skb)) { 52 wl1271_free_tx_id(wl, id); 53 return; 54 } 55 56 /* update the TX status info */ 57 if (tx_success && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) 58 info->flags |= IEEE80211_TX_STAT_ACK; 59 60 /* no real data about Tx completion */ 61 info->status.rates[0].idx = -1; 62 info->status.rates[0].count = 0; 63 info->status.rates[0].flags = 0; 64 info->status.ack_signal = -1; 65 66 if (!tx_success) 67 wl->stats.retry_count++; 68 69 /* 70 * TODO: update sequence number for encryption? seems to be 71 * unsupported for now. needed for recovery with encryption. 72 */ 73 74 /* remove private header from packet */ 75 skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); 76 77 /* remove TKIP header space if present */ 78 if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) && 79 info->control.hw_key && 80 info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { 81 int hdrlen = ieee80211_get_hdrlen_from_skb(skb); 82 memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, hdrlen); 83 skb_pull(skb, WL1271_EXTRA_SPACE_TKIP); 84 } 85 86 wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p success %d", 87 id, skb, tx_success); 88 89 /* return the packet to the stack */ 90 skb_queue_tail(&wl->deferred_tx_queue, skb); 91 queue_work(wl->freezable_wq, &wl->netstack_work); 92 wl1271_free_tx_id(wl, id); 93 } 94 95 void wl18xx_tx_immediate_complete(struct wl1271 *wl) 96 { 97 struct wl18xx_fw_status_priv *status_priv = 98 (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; 99 struct wl18xx_priv *priv = wl->priv; 100 u8 i; 101 102 /* nothing to do here */ 103 if (priv->last_fw_rls_idx == status_priv->fw_release_idx) 104 return; 105 106 /* freed Tx descriptors */ 107 wl1271_debug(DEBUG_TX, "last released desc = %d, current idx = %d", 108 priv->last_fw_rls_idx, status_priv->fw_release_idx); 109 110 if (status_priv->fw_release_idx >= WL18XX_FW_MAX_TX_STATUS_DESC) { 111 wl1271_error("invalid desc release index %d", 112 status_priv->fw_release_idx); 113 WARN_ON(1); 114 return; 115 } 116 117 for (i = priv->last_fw_rls_idx; 118 i != status_priv->fw_release_idx; 119 i = (i + 1) % WL18XX_FW_MAX_TX_STATUS_DESC) { 120 wl18xx_tx_complete_packet(wl, 121 status_priv->released_tx_desc[i]); 122 123 wl->tx_results_count++; 124 } 125 126 priv->last_fw_rls_idx = status_priv->fw_release_idx; 127 } 128