Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 1 | /****************************************************************************** |
| 2 | * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. |
| 3 | * |
| 4 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 5 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 6 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 7 | * more details. |
| 8 | * |
| 9 | * You should have received a copy of the GNU General Public License along with |
| 10 | * this program; if not, write to the Free Software Foundation, Inc., |
| 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA |
| 12 | * |
| 13 | * The full GNU General Public License is included in this distribution in the |
| 14 | * file called LICENSE. |
| 15 | * |
| 16 | * Contact Information: |
| 17 | * wlanfae <wlanfae@realtek.com> |
| 18 | ******************************************************************************/ |
| 19 | #include "rtllib.h" |
| 20 | #include "rtl819x_BA.h" |
| 21 | #include "rtl_core.h" |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 22 | |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 23 | void ActivateBAEntry(struct rtllib_device* ieee, struct ba_record *pBA, u16 Time) |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 24 | { |
| 25 | pBA->bValid = true; |
| 26 | if (Time != 0) |
| 27 | mod_timer(&pBA->Timer, jiffies + MSECS(Time)); |
| 28 | } |
| 29 | |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 30 | void DeActivateBAEntry( struct rtllib_device* ieee, struct ba_record *pBA) |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 31 | { |
| 32 | pBA->bValid = false; |
| 33 | del_timer_sync(&pBA->Timer); |
| 34 | } |
Larry Finger | 60554f2 | 2011-07-18 20:10:03 -0500 | [diff] [blame] | 35 | u8 TxTsDeleteBA( struct rtllib_device* ieee, struct tx_ts_record *pTxTs) |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 36 | { |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 37 | struct ba_record *pAdmittedBa = &pTxTs->TxAdmittedBARecord; |
| 38 | struct ba_record *pPendingBa = &pTxTs->TxPendingBARecord; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 39 | u8 bSendDELBA = false; |
| 40 | |
| 41 | if (pPendingBa->bValid) |
| 42 | { |
| 43 | DeActivateBAEntry(ieee, pPendingBa); |
| 44 | bSendDELBA = true; |
| 45 | } |
| 46 | |
| 47 | if (pAdmittedBa->bValid) |
| 48 | { |
| 49 | DeActivateBAEntry(ieee, pAdmittedBa); |
| 50 | bSendDELBA = true; |
| 51 | } |
| 52 | |
| 53 | return bSendDELBA; |
| 54 | } |
| 55 | |
Larry Finger | 2c47ae2 | 2011-07-18 20:11:56 -0500 | [diff] [blame] | 56 | u8 RxTsDeleteBA( struct rtllib_device* ieee, struct rx_ts_record *pRxTs) |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 57 | { |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 58 | struct ba_record *pBa = &pRxTs->RxAdmittedBARecord; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 59 | u8 bSendDELBA = false; |
| 60 | |
| 61 | if (pBa->bValid) |
| 62 | { |
| 63 | DeActivateBAEntry(ieee, pBa); |
| 64 | bSendDELBA = true; |
| 65 | } |
| 66 | |
| 67 | return bSendDELBA; |
| 68 | } |
| 69 | |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 70 | void ResetBaEntry( struct ba_record *pBA) |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 71 | { |
| 72 | pBA->bValid = false; |
| 73 | pBA->BaParamSet.shortData = 0; |
| 74 | pBA->BaTimeoutValue = 0; |
| 75 | pBA->DialogToken = 0; |
| 76 | pBA->BaStartSeqCtrl.ShortData = 0; |
| 77 | } |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 78 | static struct sk_buff* rtllib_ADDBA(struct rtllib_device* ieee, u8* Dst, struct ba_record *pBA, u16 StatusCode, u8 type) |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 79 | { |
| 80 | struct sk_buff *skb = NULL; |
| 81 | struct rtllib_hdr_3addr* BAReq = NULL; |
| 82 | u8* tag = NULL; |
| 83 | u16 tmp = 0; |
| 84 | u16 len = ieee->tx_headroom + 9; |
| 85 | RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __func__, type, MAC_ARG(Dst), ieee->dev); |
| 86 | if (pBA == NULL||ieee == NULL) |
| 87 | { |
| 88 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee); |
| 89 | return NULL; |
| 90 | } |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 91 | skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr)); |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 92 | if (skb == NULL) |
| 93 | { |
| 94 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n"); |
| 95 | return NULL; |
| 96 | } |
| 97 | |
| 98 | memset(skb->data, 0, sizeof( struct rtllib_hdr_3addr)); |
| 99 | |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 100 | skb_reserve(skb, ieee->tx_headroom); |
| 101 | |
| 102 | BAReq = ( struct rtllib_hdr_3addr *) skb_put(skb,sizeof( struct rtllib_hdr_3addr)); |
| 103 | |
| 104 | memcpy(BAReq->addr1, Dst, ETH_ALEN); |
| 105 | memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN); |
| 106 | |
| 107 | memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN); |
| 108 | BAReq->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT); |
| 109 | |
| 110 | tag = (u8*)skb_put(skb, 9); |
| 111 | *tag ++= ACT_CAT_BA; |
| 112 | *tag ++= type; |
| 113 | *tag ++= pBA->DialogToken; |
| 114 | |
| 115 | if (ACT_ADDBARSP == type) |
| 116 | { |
| 117 | RT_TRACE(COMP_DBG, "====>to send ADDBARSP\n"); |
| 118 | tmp = cpu_to_le16(StatusCode); |
| 119 | memcpy(tag, (u8*)&tmp, 2); |
| 120 | tag += 2; |
| 121 | } |
| 122 | tmp = cpu_to_le16(pBA->BaParamSet.shortData); |
| 123 | memcpy(tag, (u8*)&tmp, 2); |
| 124 | tag += 2; |
| 125 | tmp = cpu_to_le16(pBA->BaTimeoutValue); |
| 126 | memcpy(tag, (u8*)&tmp, 2); |
| 127 | tag += 2; |
| 128 | |
| 129 | if (ACT_ADDBAREQ == type) |
| 130 | { |
| 131 | memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2); |
| 132 | tag += 2; |
| 133 | } |
| 134 | |
| 135 | RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); |
| 136 | return skb; |
| 137 | } |
| 138 | |
| 139 | static struct sk_buff* rtllib_DELBA( |
| 140 | struct rtllib_device* ieee, |
| 141 | u8* dst, |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 142 | struct ba_record *pBA, |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 143 | TR_SELECT TxRxSelect, |
| 144 | u16 ReasonCode |
| 145 | ) |
| 146 | { |
| 147 | DELBA_PARAM_SET DelbaParamSet; |
| 148 | struct sk_buff *skb = NULL; |
| 149 | struct rtllib_hdr_3addr* Delba = NULL; |
| 150 | u8* tag = NULL; |
| 151 | u16 tmp = 0; |
| 152 | u16 len = 6 + ieee->tx_headroom; |
| 153 | |
| 154 | if (net_ratelimit()) |
| 155 | RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __func__, ReasonCode, MAC_ARG(dst)); |
| 156 | |
| 157 | memset(&DelbaParamSet, 0, 2); |
| 158 | |
| 159 | DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0; |
| 160 | DelbaParamSet.field.TID = pBA->BaParamSet.field.TID; |
| 161 | |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 162 | skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr)); |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 163 | if (skb == NULL) |
| 164 | { |
| 165 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n"); |
| 166 | return NULL; |
| 167 | } |
| 168 | |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 169 | skb_reserve(skb, ieee->tx_headroom); |
| 170 | |
| 171 | Delba = ( struct rtllib_hdr_3addr *) skb_put(skb,sizeof( struct rtllib_hdr_3addr)); |
| 172 | |
| 173 | memcpy(Delba->addr1, dst, ETH_ALEN); |
| 174 | memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN); |
| 175 | memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN); |
| 176 | Delba->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT); |
| 177 | |
| 178 | tag = (u8*)skb_put(skb, 6); |
| 179 | |
| 180 | *tag ++= ACT_CAT_BA; |
| 181 | *tag ++= ACT_DELBA; |
| 182 | |
| 183 | tmp = cpu_to_le16(DelbaParamSet.shortData); |
| 184 | memcpy(tag, (u8*)&tmp, 2); |
| 185 | tag += 2; |
| 186 | tmp = cpu_to_le16(ReasonCode); |
| 187 | memcpy(tag, (u8*)&tmp, 2); |
| 188 | tag += 2; |
| 189 | |
| 190 | RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); |
| 191 | if (net_ratelimit()) |
| 192 | RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "<=====%s()\n", __func__); |
| 193 | return skb; |
| 194 | } |
| 195 | |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 196 | void rtllib_send_ADDBAReq(struct rtllib_device* ieee, u8* dst, struct ba_record *pBA) |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 197 | { |
| 198 | struct sk_buff *skb = NULL; |
| 199 | skb = rtllib_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); |
| 200 | |
| 201 | if (skb) { |
| 202 | RT_TRACE(COMP_DBG, "====>to send ADDBAREQ!!!!!\n"); |
| 203 | softmac_mgmt_xmit(skb, ieee); |
| 204 | } else { |
| 205 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __func__); |
| 206 | } |
| 207 | return; |
| 208 | } |
| 209 | |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 210 | void rtllib_send_ADDBARsp(struct rtllib_device* ieee, u8* dst, struct ba_record *pBA, u16 StatusCode) |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 211 | { |
| 212 | struct sk_buff *skb = NULL; |
| 213 | skb = rtllib_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); |
| 214 | if (skb) |
| 215 | softmac_mgmt_xmit(skb, ieee); |
| 216 | else |
| 217 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __func__); |
| 218 | |
| 219 | return; |
| 220 | |
| 221 | } |
| 222 | |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 223 | void rtllib_send_DELBA(struct rtllib_device* ieee, u8* dst, struct ba_record *pBA, TR_SELECT TxRxSelect, u16 ReasonCode) |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 224 | { |
| 225 | struct sk_buff *skb = NULL; |
| 226 | skb = rtllib_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); |
| 227 | if (skb) |
| 228 | { |
| 229 | softmac_mgmt_xmit(skb, ieee); |
| 230 | } |
| 231 | else |
| 232 | { |
| 233 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __func__); |
| 234 | } |
| 235 | return ; |
| 236 | } |
| 237 | |
| 238 | int rtllib_rx_ADDBAReq( struct rtllib_device* ieee, struct sk_buff *skb) |
| 239 | { |
| 240 | struct rtllib_hdr_3addr* req = NULL; |
| 241 | u16 rc = 0; |
| 242 | u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL; |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 243 | struct ba_record *pBA = NULL; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 244 | PBA_PARAM_SET pBaParamSet = NULL; |
| 245 | u16* pBaTimeoutVal = NULL; |
| 246 | PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL; |
Larry Finger | 2c47ae2 | 2011-07-18 20:11:56 -0500 | [diff] [blame] | 247 | struct rx_ts_record *pTS = NULL; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 248 | |
| 249 | if (skb->len < sizeof( struct rtllib_hdr_3addr) + 9) |
| 250 | { |
| 251 | RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n",(int)skb->len, (int)(sizeof( struct rtllib_hdr_3addr) + 9)); |
| 252 | return -1; |
| 253 | } |
| 254 | |
| 255 | RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); |
| 256 | |
| 257 | req = ( struct rtllib_hdr_3addr*) skb->data; |
| 258 | tag = (u8*)req; |
| 259 | dst = (u8*)(&req->addr2[0]); |
| 260 | tag += sizeof( struct rtllib_hdr_3addr); |
| 261 | pDialogToken = tag + 2; |
| 262 | pBaParamSet = (PBA_PARAM_SET)(tag + 3); |
| 263 | pBaTimeoutVal = (u16*)(tag + 5); |
| 264 | pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7); |
| 265 | |
| 266 | RT_TRACE(COMP_DBG, "====>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst)); |
| 267 | if (ieee->current_network.qos_data.active == 0 || |
| 268 | (ieee->pHTInfo->bCurrentHTSupport == false) || |
| 269 | (ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ)) { |
| 270 | rc = ADDBA_STATUS_REFUSED; |
| 271 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); |
| 272 | goto OnADDBAReq_Fail; |
| 273 | } |
| 274 | if (!GetTs( |
| 275 | ieee, |
Larry Finger | 74724de | 2011-07-18 20:19:19 -0500 | [diff] [blame] | 276 | (struct ts_common_info **)(&pTS), |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 277 | dst, |
| 278 | (u8)(pBaParamSet->field.TID), |
| 279 | RX_DIR, |
| 280 | true) ) |
| 281 | { |
| 282 | rc = ADDBA_STATUS_REFUSED; |
| 283 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __func__); |
| 284 | goto OnADDBAReq_Fail; |
| 285 | } |
| 286 | pBA = &pTS->RxAdmittedBARecord; |
| 287 | |
| 288 | if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) |
| 289 | { |
| 290 | rc = ADDBA_STATUS_INVALID_PARAM; |
| 291 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "BA Policy is not correct in %s()\n", __func__); |
| 292 | goto OnADDBAReq_Fail; |
| 293 | } |
| 294 | |
| 295 | |
| 296 | rtllib_FlushRxTsPendingPkts(ieee, pTS); |
| 297 | |
| 298 | DeActivateBAEntry(ieee, pBA); |
| 299 | pBA->DialogToken = *pDialogToken; |
| 300 | pBA->BaParamSet = *pBaParamSet; |
| 301 | pBA->BaTimeoutValue = *pBaTimeoutVal; |
| 302 | pBA->BaStartSeqCtrl = *pBaStartSeqCtrl; |
| 303 | |
| 304 | if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)|| |
| 305 | (ieee->pHTInfo->IOTAction & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT)) |
| 306 | pBA->BaParamSet.field.BufferSize = 1; |
| 307 | else |
| 308 | pBA->BaParamSet.field.BufferSize = 32; |
| 309 | |
| 310 | ActivateBAEntry(ieee, pBA, 0); |
| 311 | rtllib_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS); |
| 312 | |
| 313 | return 0; |
| 314 | |
| 315 | OnADDBAReq_Fail: |
| 316 | { |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 317 | struct ba_record BA; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 318 | BA.BaParamSet = *pBaParamSet; |
| 319 | BA.BaTimeoutValue = *pBaTimeoutVal; |
| 320 | BA.DialogToken = *pDialogToken; |
| 321 | BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE; |
| 322 | rtllib_send_ADDBARsp(ieee, dst, &BA, rc); |
| 323 | return 0; |
| 324 | } |
| 325 | |
| 326 | } |
| 327 | |
| 328 | int rtllib_rx_ADDBARsp( struct rtllib_device* ieee, struct sk_buff *skb) |
| 329 | { |
| 330 | struct rtllib_hdr_3addr* rsp = NULL; |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 331 | struct ba_record *pPendingBA, *pAdmittedBA; |
Larry Finger | 60554f2 | 2011-07-18 20:10:03 -0500 | [diff] [blame] | 332 | struct tx_ts_record *pTS = NULL; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 333 | u8* dst = NULL, *pDialogToken = NULL, *tag = NULL; |
| 334 | u16* pStatusCode = NULL, *pBaTimeoutVal = NULL; |
| 335 | PBA_PARAM_SET pBaParamSet = NULL; |
| 336 | u16 ReasonCode; |
| 337 | |
| 338 | if (skb->len < sizeof( struct rtllib_hdr_3addr) + 9) |
| 339 | { |
| 340 | RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", (int)skb->len, (int)(sizeof( struct rtllib_hdr_3addr) + 9)); |
| 341 | return -1; |
| 342 | } |
| 343 | rsp = ( struct rtllib_hdr_3addr*)skb->data; |
| 344 | tag = (u8*)rsp; |
| 345 | dst = (u8*)(&rsp->addr2[0]); |
| 346 | tag += sizeof( struct rtllib_hdr_3addr); |
| 347 | pDialogToken = tag + 2; |
| 348 | pStatusCode = (u16*)(tag + 3); |
| 349 | pBaParamSet = (PBA_PARAM_SET)(tag + 5); |
| 350 | pBaTimeoutVal = (u16*)(tag + 7); |
| 351 | |
| 352 | RT_TRACE(COMP_DBG, "====>rx ADDBARSP from :"MAC_FMT"\n", MAC_ARG(dst)); |
| 353 | if ( |
| 354 | ieee->current_network.qos_data.active == 0 || |
| 355 | ieee->pHTInfo->bCurrentHTSupport == false || |
| 356 | ieee->pHTInfo->bCurrentAMPDUEnable == false ) |
| 357 | { |
| 358 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable); |
| 359 | ReasonCode = DELBA_REASON_UNKNOWN_BA; |
| 360 | goto OnADDBARsp_Reject; |
| 361 | } |
| 362 | |
| 363 | |
Larry Finger | 74724de | 2011-07-18 20:19:19 -0500 | [diff] [blame] | 364 | if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 365 | (u8)(pBaParamSet->field.TID), TX_DIR, false)) { |
| 366 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __func__); |
| 367 | ReasonCode = DELBA_REASON_UNKNOWN_BA; |
| 368 | goto OnADDBARsp_Reject; |
| 369 | } |
| 370 | |
| 371 | pTS->bAddBaReqInProgress = false; |
| 372 | pPendingBA = &pTS->TxPendingBARecord; |
| 373 | pAdmittedBA = &pTS->TxAdmittedBARecord; |
| 374 | |
| 375 | |
| 376 | if ((pAdmittedBA->bValid==true)) |
| 377 | { |
| 378 | RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n"); |
| 379 | return -1; |
| 380 | } |
| 381 | else if ((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken)) |
| 382 | { |
| 383 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n"); |
| 384 | ReasonCode = DELBA_REASON_UNKNOWN_BA; |
| 385 | goto OnADDBARsp_Reject; |
| 386 | } |
| 387 | else |
| 388 | { |
| 389 | RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode); |
| 390 | DeActivateBAEntry(ieee, pPendingBA); |
| 391 | } |
| 392 | |
| 393 | |
| 394 | if (*pStatusCode == ADDBA_STATUS_SUCCESS) |
| 395 | { |
| 396 | if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) |
| 397 | { |
| 398 | pTS->bAddBaReqDelayed = true; |
| 399 | DeActivateBAEntry(ieee, pAdmittedBA); |
| 400 | ReasonCode = DELBA_REASON_END_BA; |
| 401 | goto OnADDBARsp_Reject; |
| 402 | } |
| 403 | |
| 404 | |
| 405 | pAdmittedBA->DialogToken = *pDialogToken; |
| 406 | pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal; |
| 407 | pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl; |
| 408 | pAdmittedBA->BaParamSet = *pBaParamSet; |
| 409 | DeActivateBAEntry(ieee, pAdmittedBA); |
| 410 | ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal); |
| 411 | } else { |
| 412 | pTS->bAddBaReqDelayed = true; |
| 413 | pTS->bDisable_AddBa = true; |
| 414 | ReasonCode = DELBA_REASON_END_BA; |
| 415 | goto OnADDBARsp_Reject; |
| 416 | } |
| 417 | |
| 418 | return 0; |
| 419 | |
| 420 | OnADDBARsp_Reject: |
| 421 | { |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 422 | struct ba_record BA; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 423 | BA.BaParamSet = *pBaParamSet; |
| 424 | rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode); |
| 425 | return 0; |
| 426 | } |
| 427 | |
| 428 | } |
| 429 | |
| 430 | int rtllib_rx_DELBA(struct rtllib_device* ieee,struct sk_buff *skb) |
| 431 | { |
| 432 | struct rtllib_hdr_3addr* delba = NULL; |
| 433 | PDELBA_PARAM_SET pDelBaParamSet = NULL; |
| 434 | u16* pReasonCode = NULL; |
| 435 | u8* dst = NULL; |
| 436 | |
| 437 | if (skb->len < sizeof( struct rtllib_hdr_3addr) + 6) |
| 438 | { |
| 439 | RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", (int)skb->len, (int)(sizeof( struct rtllib_hdr_3addr) + 6)); |
| 440 | return -1; |
| 441 | } |
| 442 | |
| 443 | if ( |
| 444 | ieee->current_network.qos_data.active == 0 || |
| 445 | ieee->pHTInfo->bCurrentHTSupport == false ) |
| 446 | { |
| 447 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); |
| 448 | return -1; |
| 449 | } |
| 450 | |
| 451 | RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); |
| 452 | delba = ( struct rtllib_hdr_3addr*)skb->data; |
| 453 | dst = (u8*)(&delba->addr2[0]); |
| 454 | delba += sizeof( struct rtllib_hdr_3addr); |
| 455 | pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2); |
| 456 | pReasonCode = (u16*)(delba+4); |
| 457 | |
| 458 | if (pDelBaParamSet->field.Initiator == 1) |
| 459 | { |
Larry Finger | 2c47ae2 | 2011-07-18 20:11:56 -0500 | [diff] [blame] | 460 | struct rx_ts_record *pRxTs; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 461 | |
| 462 | if ( !GetTs( |
| 463 | ieee, |
Larry Finger | 74724de | 2011-07-18 20:19:19 -0500 | [diff] [blame] | 464 | (struct ts_common_info **)&pRxTs, |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 465 | dst, |
| 466 | (u8)pDelBaParamSet->field.TID, |
| 467 | RX_DIR, |
| 468 | false) ) |
| 469 | { |
| 470 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS for RXTS in %s().dst:"MAC_FMT" TID:%d\n", __func__, MAC_ARG(dst), (u8)pDelBaParamSet->field.TID); |
| 471 | return -1; |
| 472 | } |
| 473 | |
| 474 | RxTsDeleteBA(ieee, pRxTs); |
| 475 | } |
| 476 | else |
| 477 | { |
Larry Finger | 60554f2 | 2011-07-18 20:10:03 -0500 | [diff] [blame] | 478 | struct tx_ts_record *pTxTs; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 479 | |
| 480 | if (!GetTs( |
| 481 | ieee, |
Larry Finger | 74724de | 2011-07-18 20:19:19 -0500 | [diff] [blame] | 482 | (struct ts_common_info **)&pTxTs, |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 483 | dst, |
| 484 | (u8)pDelBaParamSet->field.TID, |
| 485 | TX_DIR, |
| 486 | false) ) |
| 487 | { |
| 488 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS for TXTS in %s()\n", __func__); |
| 489 | return -1; |
| 490 | } |
| 491 | |
| 492 | pTxTs->bUsingBa = false; |
| 493 | pTxTs->bAddBaReqInProgress = false; |
| 494 | pTxTs->bAddBaReqDelayed = false; |
| 495 | del_timer_sync(&pTxTs->TsAddBaTimer); |
| 496 | TxTsDeleteBA(ieee, pTxTs); |
| 497 | } |
| 498 | return 0; |
| 499 | } |
| 500 | |
| 501 | void |
| 502 | TsInitAddBA( |
| 503 | struct rtllib_device* ieee, |
Larry Finger | 60554f2 | 2011-07-18 20:10:03 -0500 | [diff] [blame] | 504 | struct tx_ts_record *pTS, |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 505 | u8 Policy, |
| 506 | u8 bOverwritePending |
| 507 | ) |
| 508 | { |
Larry Finger | 8cf3331 | 2011-07-18 21:03:22 -0500 | [diff] [blame^] | 509 | struct ba_record *pBA = &pTS->TxPendingBARecord; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 510 | |
| 511 | if (pBA->bValid==true && bOverwritePending==false) |
| 512 | return; |
| 513 | |
| 514 | DeActivateBAEntry(ieee, pBA); |
| 515 | |
| 516 | pBA->DialogToken++; |
| 517 | pBA->BaParamSet.field.AMSDU_Support = 0; |
| 518 | pBA->BaParamSet.field.BAPolicy = Policy; |
| 519 | pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID; |
| 520 | pBA->BaParamSet.field.BufferSize = 32; |
| 521 | pBA->BaTimeoutValue = 0; |
| 522 | pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; |
| 523 | |
| 524 | ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT); |
| 525 | |
| 526 | rtllib_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA); |
| 527 | } |
| 528 | |
| 529 | void |
Larry Finger | 74724de | 2011-07-18 20:19:19 -0500 | [diff] [blame] | 530 | TsInitDelBA( struct rtllib_device* ieee, struct ts_common_info *pTsCommonInfo, TR_SELECT TxRxSelect) |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 531 | { |
| 532 | |
| 533 | if (TxRxSelect == TX_DIR) |
| 534 | { |
Larry Finger | 60554f2 | 2011-07-18 20:10:03 -0500 | [diff] [blame] | 535 | struct tx_ts_record *pTxTs = (struct tx_ts_record *)pTsCommonInfo; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 536 | |
| 537 | if (TxTsDeleteBA(ieee, pTxTs)) |
| 538 | rtllib_send_DELBA( |
| 539 | ieee, |
| 540 | pTsCommonInfo->Addr, |
| 541 | (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord), |
| 542 | TxRxSelect, |
| 543 | DELBA_REASON_END_BA); |
| 544 | } |
| 545 | else if (TxRxSelect == RX_DIR) |
| 546 | { |
Larry Finger | 2c47ae2 | 2011-07-18 20:11:56 -0500 | [diff] [blame] | 547 | struct rx_ts_record *pRxTs = (struct rx_ts_record *)pTsCommonInfo; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 548 | if (RxTsDeleteBA(ieee, pRxTs)) |
| 549 | rtllib_send_DELBA( |
| 550 | ieee, |
| 551 | pTsCommonInfo->Addr, |
| 552 | &pRxTs->RxAdmittedBARecord, |
| 553 | TxRxSelect, |
| 554 | DELBA_REASON_END_BA ); |
| 555 | } |
| 556 | } |
| 557 | void BaSetupTimeOut(unsigned long data) |
| 558 | { |
Larry Finger | 60554f2 | 2011-07-18 20:10:03 -0500 | [diff] [blame] | 559 | struct tx_ts_record *pTxTs = (struct tx_ts_record *)data; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 560 | |
| 561 | pTxTs->bAddBaReqInProgress = false; |
| 562 | pTxTs->bAddBaReqDelayed = true; |
| 563 | pTxTs->TxPendingBARecord.bValid = false; |
| 564 | } |
| 565 | |
| 566 | void TxBaInactTimeout(unsigned long data) |
| 567 | { |
Larry Finger | 60554f2 | 2011-07-18 20:10:03 -0500 | [diff] [blame] | 568 | struct tx_ts_record *pTxTs = (struct tx_ts_record *)data; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 569 | struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device, TxTsRecord[pTxTs->num]); |
| 570 | TxTsDeleteBA(ieee, pTxTs); |
| 571 | rtllib_send_DELBA( |
| 572 | ieee, |
| 573 | pTxTs->TsCommonInfo.Addr, |
| 574 | &pTxTs->TxAdmittedBARecord, |
| 575 | TX_DIR, |
| 576 | DELBA_REASON_TIMEOUT); |
| 577 | } |
| 578 | |
| 579 | void RxBaInactTimeout(unsigned long data) |
| 580 | { |
Larry Finger | 2c47ae2 | 2011-07-18 20:11:56 -0500 | [diff] [blame] | 581 | struct rx_ts_record *pRxTs = (struct rx_ts_record *)data; |
Larry Finger | 94a7994 | 2011-08-23 19:00:42 -0500 | [diff] [blame] | 582 | struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device, RxTsRecord[pRxTs->num]); |
| 583 | |
| 584 | RxTsDeleteBA(ieee, pRxTs); |
| 585 | rtllib_send_DELBA( |
| 586 | ieee, |
| 587 | pRxTs->TsCommonInfo.Addr, |
| 588 | &pRxTs->RxAdmittedBARecord, |
| 589 | RX_DIR, |
| 590 | DELBA_REASON_TIMEOUT); |
| 591 | return ; |
| 592 | } |