tx.c revision bd75eb854300c7e09eaf067572498abdeb9d3424
1/** 2 * This file contains the handling of TX in wlan driver. 3 */ 4#include <linux/netdevice.h> 5#include <linux/etherdevice.h> 6#include <linux/sched.h> 7#include <net/cfg80211.h> 8 9#include "host.h" 10#include "radiotap.h" 11#include "decl.h" 12#include "defs.h" 13#include "dev.h" 14 15/** 16 * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE 17 * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1) 18 * 19 * @param rate Input rate 20 * @return Output Rate (0 if invalid) 21 */ 22static u32 convert_radiotap_rate_to_mv(u8 rate) 23{ 24 switch (rate) { 25 case 2: /* 1 Mbps */ 26 return 0 | (1 << 4); 27 case 4: /* 2 Mbps */ 28 return 1 | (1 << 4); 29 case 11: /* 5.5 Mbps */ 30 return 2 | (1 << 4); 31 case 22: /* 11 Mbps */ 32 return 3 | (1 << 4); 33 case 12: /* 6 Mbps */ 34 return 4 | (1 << 4); 35 case 18: /* 9 Mbps */ 36 return 5 | (1 << 4); 37 case 24: /* 12 Mbps */ 38 return 6 | (1 << 4); 39 case 36: /* 18 Mbps */ 40 return 7 | (1 << 4); 41 case 48: /* 24 Mbps */ 42 return 8 | (1 << 4); 43 case 72: /* 36 Mbps */ 44 return 9 | (1 << 4); 45 case 96: /* 48 Mbps */ 46 return 10 | (1 << 4); 47 case 108: /* 54 Mbps */ 48 return 11 | (1 << 4); 49 } 50 return 0; 51} 52 53/** 54 * @brief This function checks the conditions and sends packet to IF 55 * layer if everything is ok. 56 * 57 * @param priv A pointer to struct lbs_private structure 58 * @param skb A pointer to skb which includes TX packet 59 * @return 0 or -1 60 */ 61netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) 62{ 63 unsigned long flags; 64 struct lbs_private *priv = dev->ml_priv; 65 struct txpd *txpd; 66 char *p802x_hdr; 67 uint16_t pkt_len; 68 netdev_tx_t ret = NETDEV_TX_OK; 69 70 lbs_deb_enter(LBS_DEB_TX); 71 72 /* We need to protect against the queues being restarted before 73 we get round to stopping them */ 74 spin_lock_irqsave(&priv->driver_lock, flags); 75 76 if (priv->surpriseremoved) 77 goto free; 78 79 if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) { 80 lbs_deb_tx("tx err: skb length %d 0 or > %zd\n", 81 skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE); 82 /* We'll never manage to send this one; drop it and return 'OK' */ 83 84 dev->stats.tx_dropped++; 85 dev->stats.tx_errors++; 86 goto free; 87 } 88 89 90 netif_stop_queue(priv->dev); 91 if (priv->mesh_dev) 92 netif_stop_queue(priv->mesh_dev); 93 94 if (priv->tx_pending_len) { 95 /* This can happen if packets come in on the mesh and eth 96 device simultaneously -- there's no mutual exclusion on 97 hard_start_xmit() calls between devices. */ 98 lbs_deb_tx("Packet on %s while busy\n", dev->name); 99 ret = NETDEV_TX_BUSY; 100 goto unlock; 101 } 102 103 priv->tx_pending_len = -1; 104 spin_unlock_irqrestore(&priv->driver_lock, flags); 105 106 lbs_deb_hex(LBS_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100)); 107 108 txpd = (void *)priv->tx_pending_buf; 109 memset(txpd, 0, sizeof(struct txpd)); 110 111 p802x_hdr = skb->data; 112 pkt_len = skb->len; 113 114 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { 115 struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data; 116 117 /* set txpd fields from the radiotap header */ 118 txpd->tx_control = cpu_to_le32(convert_radiotap_rate_to_mv(rtap_hdr->rate)); 119 120 /* skip the radiotap header */ 121 p802x_hdr += sizeof(*rtap_hdr); 122 pkt_len -= sizeof(*rtap_hdr); 123 124 /* copy destination address from 802.11 header */ 125 memcpy(txpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN); 126 } else { 127 /* copy destination address from 802.3 header */ 128 memcpy(txpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN); 129 } 130 131 txpd->tx_packet_length = cpu_to_le16(pkt_len); 132 txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); 133 134 lbs_mesh_set_txpd(priv, dev, txpd); 135 136 lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd)); 137 138 lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr, le16_to_cpu(txpd->tx_packet_length)); 139 140 memcpy(&txpd[1], p802x_hdr, le16_to_cpu(txpd->tx_packet_length)); 141 142 spin_lock_irqsave(&priv->driver_lock, flags); 143 priv->tx_pending_len = pkt_len + sizeof(struct txpd); 144 145 lbs_deb_tx("%s lined up packet\n", __func__); 146 147 dev->stats.tx_packets++; 148 dev->stats.tx_bytes += skb->len; 149 150 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { 151 /* Keep the skb to echo it back once Tx feedback is 152 received from FW */ 153 skb_orphan(skb); 154 155 /* Keep the skb around for when we get feedback */ 156 priv->currenttxskb = skb; 157 } else { 158 free: 159 dev_kfree_skb_any(skb); 160 } 161 162 unlock: 163 spin_unlock_irqrestore(&priv->driver_lock, flags); 164 wake_up(&priv->waitq); 165 166 lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret); 167 return ret; 168} 169 170/** 171 * @brief This function sends to the host the last transmitted packet, 172 * filling the radiotap headers with transmission information. 173 * 174 * @param priv A pointer to struct lbs_private structure 175 * @param status A 32 bit value containing transmission status. 176 * 177 * @returns void 178 */ 179void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) 180{ 181 struct tx_radiotap_hdr *radiotap_hdr; 182 183 if (priv->wdev->iftype != NL80211_IFTYPE_MONITOR || 184 priv->currenttxskb == NULL) 185 return; 186 187 radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; 188 189 radiotap_hdr->data_retries = try_count ? 190 (1 + priv->txretrycount - try_count) : 0; 191 192 priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, 193 priv->dev); 194 netif_rx(priv->currenttxskb); 195 196 priv->currenttxskb = NULL; 197 198 if (priv->connect_status == LBS_CONNECTED) 199 netif_wake_queue(priv->dev); 200 201 if (priv->mesh_dev && lbs_mesh_connected(priv)) 202 netif_wake_queue(priv->mesh_dev); 203} 204EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); 205