tx.c revision 01d77d8d4747d73cfb6daf35cdc906a2db8ded9d
1876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/** 2876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * This file contains the handling of TX in wlan driver. 3876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */ 4876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include <linux/netdevice.h> 5876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 6876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "hostcmd.h" 7876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "radiotap.h" 8876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "decl.h" 9876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "defs.h" 10876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "dev.h" 11876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "wext.h" 12876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 13876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/** 14876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE 15876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1) 16876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * 17876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @param rate Input rate 18876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @return Output Rate (0 if invalid) 19876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */ 20876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattistatic u32 convert_radiotap_rate_to_mv(u8 rate) 21876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 22876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti switch (rate) { 23876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 2: /* 1 Mbps */ 24876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 0 | (1 << 4); 25876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 4: /* 2 Mbps */ 26876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 1 | (1 << 4); 27876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 11: /* 5.5 Mbps */ 28876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 2 | (1 << 4); 29876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 22: /* 11 Mbps */ 30876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 3 | (1 << 4); 31876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 12: /* 6 Mbps */ 32876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 4 | (1 << 4); 33876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 18: /* 9 Mbps */ 34876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 5 | (1 << 4); 35876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 24: /* 12 Mbps */ 36876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 6 | (1 << 4); 37876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 36: /* 18 Mbps */ 38876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 7 | (1 << 4); 39876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 48: /* 24 Mbps */ 40876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 8 | (1 << 4); 41876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 72: /* 36 Mbps */ 42876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 9 | (1 << 4); 43876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 96: /* 48 Mbps */ 44876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 10 | (1 << 4); 45876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti case 108: /* 54 Mbps */ 46876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 11 | (1 << 4); 47876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 48876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 0; 49876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 50876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 51876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/** 52876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @brief This function processes a single packet and sends 53876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * to IF layer 54876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * 551007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig * @param priv A pointer to lbs_private structure 56876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @param skb A pointer to skb which includes TX packet 57876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @return 0 or -1 58876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */ 591007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic int SendSinglePacket(lbs_private *priv, struct sk_buff *skb) 60876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 61876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int ret = 0; 62876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti struct txpd localtxpd; 63876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti struct txpd *plocaltxpd = &localtxpd; 64876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti u8 *p802x_hdr; 65876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti struct tx_radiotap_hdr *pradiotap_hdr; 66876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti u32 new_rate; 67876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti u8 *ptr = priv->adapter->tmptxbuf; 68876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 699012b28a407511fb355f6d2176a12d4653489672Holger Schurig lbs_deb_enter(LBS_DEB_TX); 70876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 71876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (priv->adapter->surpriseremoved) 72876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return -1; 73876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 74876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) { 759012b28a407511fb355f6d2176a12d4653489672Holger Schurig lbs_deb_tx("tx err: skb length %d 0 or > %zd\n", 76876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE); 77876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ret = -1; 78876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto done; 79876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 80876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 81876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti memset(plocaltxpd, 0, sizeof(struct txpd)); 82876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 83981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse plocaltxpd->tx_packet_length = cpu_to_le16(skb->len); 84876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 85876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti /* offset of actual data */ 86981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse plocaltxpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); 87876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 88876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti p802x_hdr = skb->data; 891007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig if (priv->adapter->monitormode != LBS_MONITOR_OFF) { 90876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 91876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti /* locate radiotap header */ 92876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti pradiotap_hdr = (struct tx_radiotap_hdr *)skb->data; 93876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 94876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti /* set txpd fields from the radiotap header */ 95876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti new_rate = convert_radiotap_rate_to_mv(pradiotap_hdr->rate); 96876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (new_rate != 0) { 97981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse /* use new tx_control[4:0] */ 98981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse plocaltxpd->tx_control = cpu_to_le32(new_rate); 99876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 100876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 101876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti /* skip the radiotap header */ 102876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti p802x_hdr += sizeof(struct tx_radiotap_hdr); 103981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse plocaltxpd->tx_packet_length = 10486760088a7c51ccc263ec3b8039ec9a7400a6d70David Woodhouse cpu_to_le16(le16_to_cpu(plocaltxpd->tx_packet_length) 105981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse - sizeof(struct tx_radiotap_hdr)); 106876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 107876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 108876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti /* copy destination address from 802.3 or 802.11 header */ 1091007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig if (priv->adapter->monitormode != LBS_MONITOR_OFF) 110876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN); 111876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti else 112876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN); 113876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 114ece561919326236c7fb791a5e883f0eb76af029eHolger Schurig lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) plocaltxpd, sizeof(struct txpd)); 115876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 116876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (IS_MESH_FRAME(skb)) { 117981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse plocaltxpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); 118876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 119876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 120876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti memcpy(ptr, plocaltxpd, sizeof(struct txpd)); 121876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 122876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ptr += sizeof(struct txpd); 123876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 124ece561919326236c7fb791a5e883f0eb76af029eHolger Schurig lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length)); 12586760088a7c51ccc263ec3b8039ec9a7400a6d70David Woodhouse memcpy(ptr, p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length)); 126208fdd2f447899164bd139452c291b155e53cee9Holger Schurig ret = priv->hw_host_to_card(priv, MVMS_DAT, 127981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse priv->adapter->tmptxbuf, 12886760088a7c51ccc263ec3b8039ec9a7400a6d70David Woodhouse le16_to_cpu(plocaltxpd->tx_packet_length) + 129981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse sizeof(struct txpd)); 130876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 131876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (ret) { 132208fdd2f447899164bd139452c291b155e53cee9Holger Schurig lbs_deb_tx("tx err: hw_host_to_card returned 0x%X\n", ret); 133876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto done; 134876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 135876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1369012b28a407511fb355f6d2176a12d4653489672Holger Schurig lbs_deb_tx("SendSinglePacket succeeds\n"); 137876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1389012b28a407511fb355f6d2176a12d4653489672Holger Schurigdone: 139876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (!ret) { 140876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->stats.tx_packets++; 141876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->stats.tx_bytes += skb->len; 142876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } else { 143876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->stats.tx_dropped++; 144876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->stats.tx_errors++; 145876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 146876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1471007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig if (!ret && priv->adapter->monitormode != LBS_MONITOR_OFF) { 148876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti /* Keep the skb to echo it back once Tx feedback is 149876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti received from FW */ 150876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti skb_orphan(skb); 151876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti /* stop processing outgoing pkts */ 152634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig netif_stop_queue(priv->dev); 1533cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig if (priv->mesh_dev) 1543cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig netif_stop_queue(priv->mesh_dev); 155876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti /* freeze any packets already in our queues */ 156876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->adapter->TxLockFlag = 1; 157876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } else { 158876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti dev_kfree_skb_any(skb); 159876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->adapter->currenttxskb = NULL; 160876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 161876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1629012b28a407511fb355f6d2176a12d4653489672Holger Schurig lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret); 163876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return ret; 164876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 165876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 166876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1671007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigvoid lbs_tx_runqueue(lbs_private *priv) 168876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 1691007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_adapter *adapter = priv->adapter; 170876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int i; 171876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 172876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti spin_lock(&adapter->txqueue_lock); 173876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti for (i = 0; i < adapter->tx_queue_idx; i++) { 174876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti struct sk_buff *skb = adapter->tx_queue_ps[i]; 175876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti spin_unlock(&adapter->txqueue_lock); 176876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti SendSinglePacket(priv, skb); 177876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti spin_lock(&adapter->txqueue_lock); 178876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 179876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti adapter->tx_queue_idx = 0; 180876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti spin_unlock(&adapter->txqueue_lock); 181876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 182876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1831007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic void lbs_tx_queue(lbs_private *priv, struct sk_buff *skb) 184876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 1851007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_adapter *adapter = priv->adapter; 186876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 187876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti spin_lock(&adapter->txqueue_lock); 188876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 189876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti WARN_ON(priv->adapter->tx_queue_idx >= NR_TX_QUEUE); 190876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti adapter->tx_queue_ps[adapter->tx_queue_idx++] = skb; 19151d84f501684db22f5fcc30821cbbde2a0a2f264Javier Cardona if (adapter->tx_queue_idx == NR_TX_QUEUE) { 192634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig netif_stop_queue(priv->dev); 1933cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig if (priv->mesh_dev) 1943cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig netif_stop_queue(priv->mesh_dev); 19551d84f501684db22f5fcc30821cbbde2a0a2f264Javier Cardona } else { 196634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig netif_start_queue(priv->dev); 1973cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig if (priv->mesh_dev) 1983cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig netif_start_queue(priv->mesh_dev); 19951d84f501684db22f5fcc30821cbbde2a0a2f264Javier Cardona } 200876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 201876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti spin_unlock(&adapter->txqueue_lock); 202876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 203876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 204876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/** 205876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @brief This function checks the conditions and sends packet to IF 206876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * layer if everything is ok. 207876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * 2081007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig * @param priv A pointer to lbs_private structure 209876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @return n/a 210876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */ 2111007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigint lbs_process_tx(lbs_private *priv, struct sk_buff *skb) 212876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 213876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int ret = -1; 214876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2159012b28a407511fb355f6d2176a12d4653489672Holger Schurig lbs_deb_enter(LBS_DEB_TX); 216ece561919326236c7fb791a5e883f0eb76af029eHolger Schurig lbs_deb_hex(LBS_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100)); 217876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 218634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig if (priv->dnld_sent) { 219876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti lbs_pr_alert( "TX error: dnld_sent = %d, not sending\n", 220634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig priv->dnld_sent); 221876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto done; 222876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 223876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 224876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if ((priv->adapter->psstate == PS_STATE_SLEEP) || 225876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti (priv->adapter->psstate == PS_STATE_PRE_SLEEP)) { 2261007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_tx_queue(priv, skb); 227876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return ret; 228876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 229876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 230876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->adapter->currenttxskb = skb; 231876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 232876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ret = SendSinglePacket(priv, skb); 233876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattidone: 2349012b28a407511fb355f6d2176a12d4653489672Holger Schurig lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret); 235876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return ret; 236876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 237876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 238876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/** 239876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @brief This function sends to the host the last transmitted packet, 240876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * filling the radiotap headers with transmission information. 241876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * 2421007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig * @param priv A pointer to lbs_private structure 243876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @param status A 32 bit value containing transmission status. 244876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * 245876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * @returns void 246876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */ 2471007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigvoid lbs_send_tx_feedback(lbs_private *priv) 248876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 2491007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_adapter *adapter = priv->adapter; 250876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti struct tx_radiotap_hdr *radiotap_hdr; 251876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti u32 status = adapter->eventcause; 252876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int txfail; 253876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int try_count; 254876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2551007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig if (adapter->monitormode == LBS_MONITOR_OFF || 256876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti adapter->currenttxskb == NULL) 257876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return; 258876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 259876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti radiotap_hdr = (struct tx_radiotap_hdr *)adapter->currenttxskb->data; 260876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 261876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti txfail = (status >> 24); 262876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 263876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#if 0 264876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti /* The version of roofnet that we've tested does not use this yet 265876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * But it may be used in the future. 266876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */ 267876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (txfail) 268876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL; 269876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#endif 270876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti try_count = (status >> 16) & 0xff; 271876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti radiotap_hdr->data_retries = (try_count) ? 272876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti (1 + adapter->txretrycount - try_count) : 0; 2731007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_upload_rx_packet(priv, adapter->currenttxskb); 274876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti adapter->currenttxskb = NULL; 275876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->adapter->TxLockFlag = 0; 27601d77d8d4747d73cfb6daf35cdc906a2db8ded9dBrajesh Dave 27701d77d8d4747d73cfb6daf35cdc906a2db8ded9dBrajesh Dave if (adapter->connect_status == LBS_CONNECTED) 278634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig netif_wake_queue(priv->dev); 27901d77d8d4747d73cfb6daf35cdc906a2db8ded9dBrajesh Dave 28001d77d8d4747d73cfb6daf35cdc906a2db8ded9dBrajesh Dave if (priv->mesh_dev && (adapter->mesh_connect_status == LBS_CONNECTED)) 28101d77d8d4747d73cfb6daf35cdc906a2db8ded9dBrajesh Dave netif_wake_queue(priv->mesh_dev); 282876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 2831007832103d016d1563fab71d4cf2b057a0bccebHolger SchurigEXPORT_SYMBOL_GPL(lbs_send_tx_feedback); 284