rsi_91x_core.c (13084B)
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#include "rsi_common.h" 19#include "rsi_hal.h" 20#include "rsi_coex.h" 21 22/** 23 * rsi_determine_min_weight_queue() - This function determines the queue with 24 * the min weight. 25 * @common: Pointer to the driver private structure. 26 * 27 * Return: q_num: Corresponding queue number. 28 */ 29static u8 rsi_determine_min_weight_queue(struct rsi_common *common) 30{ 31 struct wmm_qinfo *tx_qinfo = common->tx_qinfo; 32 u32 q_len = 0; 33 u8 ii = 0; 34 35 for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) { 36 q_len = skb_queue_len(&common->tx_queue[ii]); 37 if ((tx_qinfo[ii].pkt_contended) && q_len) { 38 common->min_weight = tx_qinfo[ii].weight; 39 break; 40 } 41 } 42 return ii; 43} 44 45/** 46 * rsi_recalculate_weights() - This function recalculates the weights 47 * corresponding to each queue. 48 * @common: Pointer to the driver private structure. 49 * 50 * Return: recontend_queue bool variable 51 */ 52static bool rsi_recalculate_weights(struct rsi_common *common) 53{ 54 struct wmm_qinfo *tx_qinfo = common->tx_qinfo; 55 bool recontend_queue = false; 56 u8 ii = 0; 57 u32 q_len = 0; 58 59 for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) { 60 q_len = skb_queue_len(&common->tx_queue[ii]); 61 /* Check for the need of contention */ 62 if (q_len) { 63 if (tx_qinfo[ii].pkt_contended) { 64 tx_qinfo[ii].weight = 65 ((tx_qinfo[ii].weight > common->min_weight) ? 66 tx_qinfo[ii].weight - common->min_weight : 0); 67 } else { 68 tx_qinfo[ii].pkt_contended = 1; 69 tx_qinfo[ii].weight = tx_qinfo[ii].wme_params; 70 recontend_queue = true; 71 } 72 } else { /* No packets so no contention */ 73 tx_qinfo[ii].weight = 0; 74 tx_qinfo[ii].pkt_contended = 0; 75 } 76 } 77 78 return recontend_queue; 79} 80 81/** 82 * rsi_get_num_pkts_dequeue() - This function determines the number of 83 * packets to be dequeued based on the number 84 * of bytes calculated using txop. 85 * 86 * @common: Pointer to the driver private structure. 87 * @q_num: the queue from which pkts have to be dequeued 88 * 89 * Return: pkt_num: Number of pkts to be dequeued. 90 */ 91static u32 rsi_get_num_pkts_dequeue(struct rsi_common *common, u8 q_num) 92{ 93 struct rsi_hw *adapter = common->priv; 94 struct sk_buff *skb; 95 u32 pkt_cnt = 0; 96 s16 txop = common->tx_qinfo[q_num].txop * 32; 97 __le16 r_txop; 98 struct ieee80211_rate rate; 99 struct ieee80211_hdr *wh; 100 struct ieee80211_vif *vif; 101 102 rate.bitrate = RSI_RATE_MCS0 * 5 * 10; /* Convert to Kbps */ 103 if (q_num == VI_Q) 104 txop = ((txop << 5) / 80); 105 106 if (skb_queue_len(&common->tx_queue[q_num])) 107 skb = skb_peek(&common->tx_queue[q_num]); 108 else 109 return 0; 110 111 do { 112 wh = (struct ieee80211_hdr *)skb->data; 113 vif = rsi_get_vif(adapter, wh->addr2); 114 r_txop = ieee80211_generic_frame_duration(adapter->hw, 115 vif, 116 common->band, 117 skb->len, &rate); 118 txop -= le16_to_cpu(r_txop); 119 pkt_cnt += 1; 120 /*checking if pkts are still there*/ 121 if (skb_queue_len(&common->tx_queue[q_num]) - pkt_cnt) 122 skb = skb->next; 123 else 124 break; 125 126 } while (txop > 0); 127 128 return pkt_cnt; 129} 130 131/** 132 * rsi_core_determine_hal_queue() - This function determines the queue from 133 * which packet has to be dequeued. 134 * @common: Pointer to the driver private structure. 135 * 136 * Return: q_num: Corresponding queue number on success. 137 */ 138static u8 rsi_core_determine_hal_queue(struct rsi_common *common) 139{ 140 bool recontend_queue = false; 141 u32 q_len = 0; 142 u8 q_num = INVALID_QUEUE; 143 u8 ii = 0; 144 145 if (skb_queue_len(&common->tx_queue[MGMT_BEACON_Q])) { 146 q_num = MGMT_BEACON_Q; 147 return q_num; 148 } 149 if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) { 150 if (!common->mgmt_q_block) 151 q_num = MGMT_SOFT_Q; 152 return q_num; 153 } 154 155 if (common->hw_data_qs_blocked) 156 return q_num; 157 158 if (common->pkt_cnt != 0) { 159 --common->pkt_cnt; 160 return common->selected_qnum; 161 } 162 163get_queue_num: 164 recontend_queue = false; 165 166 q_num = rsi_determine_min_weight_queue(common); 167 168 ii = q_num; 169 170 /* Selecting the queue with least back off */ 171 for (; ii < NUM_EDCA_QUEUES; ii++) { 172 q_len = skb_queue_len(&common->tx_queue[ii]); 173 if (((common->tx_qinfo[ii].pkt_contended) && 174 (common->tx_qinfo[ii].weight < common->min_weight)) && 175 q_len) { 176 common->min_weight = common->tx_qinfo[ii].weight; 177 q_num = ii; 178 } 179 } 180 181 if (q_num < NUM_EDCA_QUEUES) 182 common->tx_qinfo[q_num].pkt_contended = 0; 183 184 /* Adjust the back off values for all queues again */ 185 recontend_queue = rsi_recalculate_weights(common); 186 187 q_len = skb_queue_len(&common->tx_queue[q_num]); 188 if (!q_len) { 189 /* If any queues are freshly contended and the selected queue 190 * doesn't have any packets 191 * then get the queue number again with fresh values 192 */ 193 if (recontend_queue) 194 goto get_queue_num; 195 196 return INVALID_QUEUE; 197 } 198 199 common->selected_qnum = q_num; 200 q_len = skb_queue_len(&common->tx_queue[q_num]); 201 202 if (q_num == VO_Q || q_num == VI_Q) { 203 common->pkt_cnt = rsi_get_num_pkts_dequeue(common, q_num); 204 common->pkt_cnt -= 1; 205 } 206 207 return q_num; 208} 209 210/** 211 * rsi_core_queue_pkt() - This functions enqueues the packet to the queue 212 * specified by the queue number. 213 * @common: Pointer to the driver private structure. 214 * @skb: Pointer to the socket buffer structure. 215 * 216 * Return: None. 217 */ 218static void rsi_core_queue_pkt(struct rsi_common *common, 219 struct sk_buff *skb) 220{ 221 u8 q_num = skb->priority; 222 if (q_num >= NUM_SOFT_QUEUES) { 223 rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n", 224 __func__, q_num); 225 dev_kfree_skb(skb); 226 return; 227 } 228 229 skb_queue_tail(&common->tx_queue[q_num], skb); 230} 231 232/** 233 * rsi_core_dequeue_pkt() - This functions dequeues the packet from the queue 234 * specified by the queue number. 235 * @common: Pointer to the driver private structure. 236 * @q_num: Queue number. 237 * 238 * Return: Pointer to sk_buff structure. 239 */ 240static struct sk_buff *rsi_core_dequeue_pkt(struct rsi_common *common, 241 u8 q_num) 242{ 243 if (q_num >= NUM_SOFT_QUEUES) { 244 rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n", 245 __func__, q_num); 246 return NULL; 247 } 248 249 return skb_dequeue(&common->tx_queue[q_num]); 250} 251 252/** 253 * rsi_core_qos_processor() - This function is used to determine the wmm queue 254 * based on the backoff procedure. Data packets are 255 * dequeued from the selected hal queue and sent to 256 * the below layers. 257 * @common: Pointer to the driver private structure. 258 * 259 * Return: None. 260 */ 261void rsi_core_qos_processor(struct rsi_common *common) 262{ 263 struct rsi_hw *adapter = common->priv; 264 struct sk_buff *skb; 265 unsigned long tstamp_1, tstamp_2; 266 u8 q_num; 267 int status; 268 269 tstamp_1 = jiffies; 270 while (1) { 271 q_num = rsi_core_determine_hal_queue(common); 272 rsi_dbg(DATA_TX_ZONE, 273 "%s: Queue number = %d\n", __func__, q_num); 274 275 if (q_num == INVALID_QUEUE) { 276 rsi_dbg(DATA_TX_ZONE, "%s: No More Pkt\n", __func__); 277 break; 278 } 279 if (common->hibernate_resume) 280 break; 281 282 mutex_lock(&common->tx_lock); 283 284 status = adapter->check_hw_queue_status(adapter, q_num); 285 if ((status <= 0)) { 286 mutex_unlock(&common->tx_lock); 287 break; 288 } 289 290 if ((q_num < MGMT_SOFT_Q) && 291 ((skb_queue_len(&common->tx_queue[q_num])) <= 292 MIN_DATA_QUEUE_WATER_MARK)) { 293 if (ieee80211_queue_stopped(adapter->hw, WME_AC(q_num))) 294 ieee80211_wake_queue(adapter->hw, 295 WME_AC(q_num)); 296 } 297 298 skb = rsi_core_dequeue_pkt(common, q_num); 299 if (skb == NULL) { 300 rsi_dbg(ERR_ZONE, "skb null\n"); 301 mutex_unlock(&common->tx_lock); 302 break; 303 } 304 if (q_num == MGMT_BEACON_Q) { 305 status = rsi_send_pkt_to_bus(common, skb); 306 dev_kfree_skb(skb); 307 } else { 308#ifdef CONFIG_RSI_COEX 309 if (common->coex_mode > 1) { 310 status = rsi_coex_send_pkt(common, skb, 311 RSI_WLAN_Q); 312 } else { 313#endif 314 if (q_num == MGMT_SOFT_Q) 315 status = rsi_send_mgmt_pkt(common, skb); 316 else 317 status = rsi_send_data_pkt(common, skb); 318#ifdef CONFIG_RSI_COEX 319 } 320#endif 321 } 322 323 if (status) { 324 mutex_unlock(&common->tx_lock); 325 break; 326 } 327 328 common->tx_stats.total_tx_pkt_send[q_num]++; 329 330 tstamp_2 = jiffies; 331 mutex_unlock(&common->tx_lock); 332 333 if (time_after(tstamp_2, tstamp_1 + (300 * HZ) / 1000)) 334 schedule(); 335 } 336} 337 338struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr) 339{ 340 int i; 341 342 for (i = 0; i < common->max_stations; i++) { 343 if (!common->stations[i].sta) 344 continue; 345 if (!(memcmp(common->stations[i].sta->addr, 346 mac_addr, ETH_ALEN))) 347 return &common->stations[i]; 348 } 349 return NULL; 350} 351 352struct ieee80211_vif *rsi_get_vif(struct rsi_hw *adapter, u8 *mac) 353{ 354 struct ieee80211_vif *vif; 355 int i; 356 357 for (i = 0; i < RSI_MAX_VIFS; i++) { 358 vif = adapter->vifs[i]; 359 if (!vif) 360 continue; 361 if (!memcmp(vif->addr, mac, ETH_ALEN)) 362 return vif; 363 } 364 return NULL; 365} 366 367/** 368 * rsi_core_xmit() - This function transmits the packets received from mac80211 369 * @common: Pointer to the driver private structure. 370 * @skb: Pointer to the socket buffer structure. 371 * 372 * Return: None. 373 */ 374void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb) 375{ 376 struct rsi_hw *adapter = common->priv; 377 struct ieee80211_tx_info *info; 378 struct skb_info *tx_params; 379 struct ieee80211_hdr *wh = NULL; 380 struct ieee80211_vif *vif; 381 u8 q_num, tid = 0; 382 struct rsi_sta *rsta = NULL; 383 384 if ((!skb) || (!skb->len)) { 385 rsi_dbg(ERR_ZONE, "%s: Null skb/zero Length packet\n", 386 __func__); 387 goto xmit_fail; 388 } 389 if (common->fsm_state != FSM_MAC_INIT_DONE) { 390 rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__); 391 goto xmit_fail; 392 } 393 if (common->wow_flags & RSI_WOW_ENABLED) { 394 rsi_dbg(ERR_ZONE, 395 "%s: Blocking Tx_packets when WOWLAN is enabled\n", 396 __func__); 397 goto xmit_fail; 398 } 399 400 info = IEEE80211_SKB_CB(skb); 401 tx_params = (struct skb_info *)info->driver_data; 402 /* info->driver_data and info->control part of union so make copy */ 403 tx_params->have_key = !!info->control.hw_key; 404 wh = (struct ieee80211_hdr *)&skb->data[0]; 405 tx_params->sta_id = 0; 406 407 vif = rsi_get_vif(adapter, wh->addr2); 408 if (!vif) 409 goto xmit_fail; 410 tx_params->vif = vif; 411 tx_params->vap_id = ((struct vif_priv *)vif->drv_priv)->vap_id; 412 if ((ieee80211_is_mgmt(wh->frame_control)) || 413 (ieee80211_is_ctl(wh->frame_control)) || 414 (ieee80211_is_qos_nullfunc(wh->frame_control))) { 415 if (ieee80211_is_assoc_req(wh->frame_control) || 416 ieee80211_is_reassoc_req(wh->frame_control)) { 417 struct ieee80211_bss_conf *bss = &vif->bss_conf; 418 419 common->eapol4_confirm = false; 420 rsi_hal_send_sta_notify_frame(common, 421 RSI_IFTYPE_STATION, 422 STA_CONNECTED, bss->bssid, 423 bss->qos, bss->aid, 0, 424 vif); 425 } 426 427 q_num = MGMT_SOFT_Q; 428 skb->priority = q_num; 429 430 if (rsi_prepare_mgmt_desc(common, skb)) { 431 rsi_dbg(ERR_ZONE, "Failed to prepare desc\n"); 432 goto xmit_fail; 433 } 434 } else { 435 if (ieee80211_is_data_qos(wh->frame_control)) { 436 u8 *qos = ieee80211_get_qos_ctl(wh); 437 438 tid = *qos & IEEE80211_QOS_CTL_TID_MASK; 439 skb->priority = TID_TO_WME_AC(tid); 440 } else { 441 tid = IEEE80211_NONQOS_TID; 442 skb->priority = BE_Q; 443 } 444 445 q_num = skb->priority; 446 tx_params->tid = tid; 447 448 if (((vif->type == NL80211_IFTYPE_AP) || 449 (vif->type == NL80211_IFTYPE_P2P_GO)) && 450 (!is_broadcast_ether_addr(wh->addr1)) && 451 (!is_multicast_ether_addr(wh->addr1))) { 452 rsta = rsi_find_sta(common, wh->addr1); 453 if (!rsta) 454 goto xmit_fail; 455 tx_params->sta_id = rsta->sta_id; 456 } else { 457 tx_params->sta_id = 0; 458 } 459 460 if (rsta) { 461 /* Start aggregation if not done for this tid */ 462 if (!rsta->start_tx_aggr[tid]) { 463 rsta->start_tx_aggr[tid] = true; 464 ieee80211_start_tx_ba_session(rsta->sta, 465 tid, 0); 466 } 467 } 468 if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { 469 q_num = MGMT_SOFT_Q; 470 skb->priority = q_num; 471 } 472 if (rsi_prepare_data_desc(common, skb)) { 473 rsi_dbg(ERR_ZONE, "Failed to prepare data desc\n"); 474 goto xmit_fail; 475 } 476 } 477 478 if ((q_num < MGMT_SOFT_Q) && 479 ((skb_queue_len(&common->tx_queue[q_num]) + 1) >= 480 DATA_QUEUE_WATER_MARK)) { 481 rsi_dbg(ERR_ZONE, "%s: sw queue full\n", __func__); 482 if (!ieee80211_queue_stopped(adapter->hw, WME_AC(q_num))) 483 ieee80211_stop_queue(adapter->hw, WME_AC(q_num)); 484 rsi_set_event(&common->tx_thread.event); 485 goto xmit_fail; 486 } 487 488 rsi_core_queue_pkt(common, skb); 489 rsi_dbg(DATA_TX_ZONE, "%s: ===> Scheduling TX thread <===\n", __func__); 490 rsi_set_event(&common->tx_thread.event); 491 492 return; 493 494xmit_fail: 495 rsi_dbg(ERR_ZONE, "%s: Failed to queue packet\n", __func__); 496 /* Dropping pkt here */ 497 ieee80211_free_txskb(common->priv->hw, skb); 498}