1/** 2 * Copyright (c) 2014 Redpine Signals Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#include "rsi_mgmt.h" 18 19/** 20 * rsi_send_data_pkt() - This function sends the recieved data packet from 21 * driver to device. 22 * @common: Pointer to the driver private structure. 23 * @skb: Pointer to the socket buffer structure. 24 * 25 * Return: status: 0 on success, -1 on failure. 26 */ 27int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb) 28{ 29 struct rsi_hw *adapter = common->priv; 30 struct ieee80211_hdr *tmp_hdr = NULL; 31 struct ieee80211_tx_info *info; 32 struct skb_info *tx_params; 33 struct ieee80211_bss_conf *bss = NULL; 34 int status = -EINVAL; 35 u8 ieee80211_size = MIN_802_11_HDR_LEN; 36 u8 extnd_size = 0; 37 __le16 *frame_desc; 38 u16 seq_num = 0; 39 40 info = IEEE80211_SKB_CB(skb); 41 bss = &info->control.vif->bss_conf; 42 tx_params = (struct skb_info *)info->driver_data; 43 44 if (!bss->assoc) 45 goto err; 46 47 tmp_hdr = (struct ieee80211_hdr *)&skb->data[0]; 48 seq_num = (le16_to_cpu(tmp_hdr->seq_ctrl) >> 4); 49 50 extnd_size = ((uintptr_t)skb->data & 0x3); 51 52 if ((FRAME_DESC_SZ + extnd_size) > skb_headroom(skb)) { 53 rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__); 54 status = -ENOSPC; 55 goto err; 56 } 57 58 skb_push(skb, (FRAME_DESC_SZ + extnd_size)); 59 frame_desc = (__le16 *)&skb->data[0]; 60 memset((u8 *)frame_desc, 0, FRAME_DESC_SZ); 61 62 if (ieee80211_is_data_qos(tmp_hdr->frame_control)) { 63 ieee80211_size += 2; 64 frame_desc[6] |= cpu_to_le16(BIT(12)); 65 } 66 67 if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) && 68 (common->secinfo.security_enable)) { 69 if (rsi_is_cipher_wep(common)) 70 ieee80211_size += 4; 71 else 72 ieee80211_size += 8; 73 frame_desc[6] |= cpu_to_le16(BIT(15)); 74 } 75 76 frame_desc[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) | 77 (RSI_WIFI_DATA_Q << 12)); 78 frame_desc[2] = cpu_to_le16((extnd_size) | (ieee80211_size) << 8); 79 80 if (common->min_rate != 0xffff) { 81 /* Send fixed rate */ 82 frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE); 83 frame_desc[4] = cpu_to_le16(common->min_rate); 84 85 if (conf_is_ht40(&common->priv->hw->conf)) 86 frame_desc[5] = cpu_to_le16(FULL40M_ENABLE); 87 88 if (common->vif_info[0].sgi) { 89 if (common->min_rate & 0x100) /* Only MCS rates */ 90 frame_desc[4] |= 91 cpu_to_le16(ENABLE_SHORTGI_RATE); 92 } 93 94 } 95 96 frame_desc[6] |= cpu_to_le16(seq_num & 0xfff); 97 frame_desc[7] = cpu_to_le16(((tx_params->tid & 0xf) << 4) | 98 (skb->priority & 0xf) | 99 (tx_params->sta_id << 8)); 100 101 status = adapter->host_intf_write_pkt(common->priv, 102 skb->data, 103 skb->len); 104 if (status) 105 rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n", 106 __func__); 107 108err: 109 ++common->tx_stats.total_tx_pkt_freed[skb->priority]; 110 rsi_indicate_tx_status(common->priv, skb, status); 111 return status; 112} 113 114/** 115 * rsi_send_mgmt_pkt() - This functions sends the received management packet 116 * from driver to device. 117 * @common: Pointer to the driver private structure. 118 * @skb: Pointer to the socket buffer structure. 119 * 120 * Return: status: 0 on success, -1 on failure. 121 */ 122int rsi_send_mgmt_pkt(struct rsi_common *common, 123 struct sk_buff *skb) 124{ 125 struct rsi_hw *adapter = common->priv; 126 struct ieee80211_hdr *wh = NULL; 127 struct ieee80211_tx_info *info; 128 struct ieee80211_bss_conf *bss = NULL; 129 struct ieee80211_hw *hw = adapter->hw; 130 struct ieee80211_conf *conf = &hw->conf; 131 struct skb_info *tx_params; 132 int status = -E2BIG; 133 __le16 *msg = NULL; 134 u8 extnd_size = 0; 135 u8 vap_id = 0; 136 137 info = IEEE80211_SKB_CB(skb); 138 tx_params = (struct skb_info *)info->driver_data; 139 extnd_size = ((uintptr_t)skb->data & 0x3); 140 141 if (tx_params->flags & INTERNAL_MGMT_PKT) { 142 if ((extnd_size) > skb_headroom(skb)) { 143 rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__); 144 dev_kfree_skb(skb); 145 return -ENOSPC; 146 } 147 skb_push(skb, extnd_size); 148 skb->data[extnd_size + 4] = extnd_size; 149 status = adapter->host_intf_write_pkt(common->priv, 150 (u8 *)skb->data, 151 skb->len); 152 if (status) { 153 rsi_dbg(ERR_ZONE, 154 "%s: Failed to write the packet\n", __func__); 155 } 156 dev_kfree_skb(skb); 157 return status; 158 } 159 160 bss = &info->control.vif->bss_conf; 161 wh = (struct ieee80211_hdr *)&skb->data[0]; 162 163 if (FRAME_DESC_SZ > skb_headroom(skb)) 164 goto err; 165 166 skb_push(skb, FRAME_DESC_SZ); 167 memset(skb->data, 0, FRAME_DESC_SZ); 168 msg = (__le16 *)skb->data; 169 170 if (skb->len > MAX_MGMT_PKT_SIZE) { 171 rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__); 172 goto err; 173 } 174 175 msg[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) | 176 (RSI_WIFI_MGMT_Q << 12)); 177 msg[1] = cpu_to_le16(TX_DOT11_MGMT); 178 msg[2] = cpu_to_le16(MIN_802_11_HDR_LEN << 8); 179 msg[3] = cpu_to_le16(RATE_INFO_ENABLE); 180 msg[6] = cpu_to_le16(le16_to_cpu(wh->seq_ctrl) >> 4); 181 182 if (wh->addr1[0] & BIT(0)) 183 msg[3] |= cpu_to_le16(RSI_BROADCAST_PKT); 184 185 if (common->band == IEEE80211_BAND_2GHZ) 186 msg[4] = cpu_to_le16(RSI_11B_MODE); 187 else 188 msg[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE); 189 190 if (conf_is_ht40(conf)) { 191 msg[4] = cpu_to_le16(0xB | RSI_11G_MODE); 192 msg[5] = cpu_to_le16(0x6); 193 } 194 195 /* Indicate to firmware to give cfm */ 196 if ((skb->data[16] == IEEE80211_STYPE_PROBE_REQ) && (!bss->assoc)) { 197 msg[1] |= cpu_to_le16(BIT(10)); 198 msg[7] = cpu_to_le16(PROBEREQ_CONFIRM); 199 common->mgmt_q_block = true; 200 } 201 202 msg[7] |= cpu_to_le16(vap_id << 8); 203 204 status = adapter->host_intf_write_pkt(common->priv, 205 (u8 *)msg, 206 skb->len); 207 if (status) 208 rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__); 209 210err: 211 rsi_indicate_tx_status(common->priv, skb, status); 212 return status; 213} 214