1 /* 2 * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. 3 * 4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc. 5 * 6 * 7 * Permission to use, copy, modify, and/or distribute this software for 8 * any purpose with or without fee is hereby granted, provided that the 9 * above copyright notice and this permission notice appear in all 10 * copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 19 * PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 /* 23 * This file was originally distributed by Qualcomm Atheros, Inc. 24 * under proprietary terms before Copyright ownership was assigned 25 * to the Linux Foundation. 26 */ 27 28 /* 29 * 30 * Permission to use, copy, modify, and/or distribute this software for any 31 * purpose with or without fee is hereby granted, provided that the above 32 * copyright notice and this permission notice appear in all copies. 33 * 34 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 35 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 36 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 37 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 38 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 39 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 40 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 41 */ 42 43 #ifndef REMOVE_PKT_LOG 44 #include "ol_txrx_types.h" 45 #include "ol_htt_tx_api.h" 46 #include "ol_tx_desc.h" 47 #include "qdf_mem.h" 48 #include "htt.h" 49 #include "htt_internal.h" 50 #include "pktlog_ac_i.h" 51 #include "wma_api.h" 52 #include "wlan_logging_sock_svc.h" 53 54 #define TX_DESC_ID_LOW_MASK 0xffff 55 #define TX_DESC_ID_LOW_SHIFT 0 56 #define TX_DESC_ID_HIGH_MASK 0xffff0000 57 #define TX_DESC_ID_HIGH_SHIFT 16 58 59 void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg) 60 { 61 struct ath_pktlog_buf *log_buf; 62 int32_t buf_size; 63 struct ath_pktlog_hdr *log_hdr; 64 int32_t cur_wr_offset; 65 char *log_ptr; 66 struct ath_pktlog_info *pl_info; 67 uint16_t log_type; 68 size_t log_size; 69 uint32_t flags; 70 #ifdef HELIUMPLUS 71 uint8_t mac_id; 72 #endif 73 74 if (!plarg) { 75 printk("Invalid parg in %s\n", __func__); 76 return; 77 } 78 79 pl_info = plarg->pl_info; 80 #ifdef HELIUMPLUS 81 mac_id = plarg->macId; 82 log_type = plarg->log_type; 83 #else 84 log_type = plarg->log_type; 85 #endif 86 log_size = plarg->log_size; 87 log_buf = pl_info->buf; 88 flags = plarg->flags; 89 90 if (!log_buf) { 91 printk("Invalid log_buf in %s\n", __func__); 92 return; 93 } 94 95 96 buf_size = pl_info->buf_size; 97 cur_wr_offset = log_buf->wr_offset; 98 /* Move read offset to the next entry if there is a buffer overlap */ 99 if (log_buf->rd_offset >= 0) { 100 if ((cur_wr_offset <= log_buf->rd_offset) 101 && (cur_wr_offset + sizeof(struct ath_pktlog_hdr)) > 102 log_buf->rd_offset) { 103 PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, 104 buf_size); 105 } 106 } else { 107 log_buf->rd_offset = cur_wr_offset; 108 } 109 110 log_hdr = (struct ath_pktlog_hdr *)(log_buf->log_data + cur_wr_offset); 111 112 log_hdr->flags = flags; 113 #ifdef HELIUMPLUS 114 log_hdr->macId = mac_id; 115 log_hdr->log_type = log_type; 116 #else 117 log_hdr->log_type = log_type; 118 #endif 119 log_hdr->size = (uint16_t) log_size; 120 log_hdr->missed_cnt = plarg->missed_cnt; 121 log_hdr->timestamp = plarg->timestamp; 122 #ifdef HELIUMPLUS 123 log_hdr->type_specific_data = plarg->type_specific_data; 124 #endif 125 cur_wr_offset += sizeof(*log_hdr); 126 127 if ((buf_size - cur_wr_offset) < log_size) { 128 while ((cur_wr_offset <= log_buf->rd_offset) 129 && (log_buf->rd_offset < buf_size)) { 130 PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, 131 buf_size); 132 } 133 cur_wr_offset = 0; 134 } 135 136 while ((cur_wr_offset <= log_buf->rd_offset) 137 && (cur_wr_offset + log_size) > log_buf->rd_offset) { 138 PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, buf_size); 139 } 140 141 log_ptr = &(log_buf->log_data[cur_wr_offset]); 142 cur_wr_offset += log_hdr->size; 143 144 log_buf->wr_offset = ((buf_size - cur_wr_offset) >= 145 sizeof(struct ath_pktlog_hdr)) ? cur_wr_offset : 146 0; 147 148 plarg->buf = log_ptr; 149 } 150 151 char *pktlog_getbuf(struct pktlog_dev_t *pl_dev, 152 struct ath_pktlog_info *pl_info, 153 size_t log_size, struct ath_pktlog_hdr *pl_hdr) 154 { 155 struct ath_pktlog_arg plarg = { 0, }; 156 uint8_t flags = 0; 157 158 plarg.pl_info = pl_info; 159 #ifdef HELIUMPLUS 160 plarg.macId = pl_hdr->macId; 161 plarg.log_type = pl_hdr->log_type; 162 #else 163 plarg.log_type = pl_hdr->log_type; 164 #endif 165 plarg.log_size = log_size; 166 plarg.flags = pl_hdr->flags; 167 plarg.missed_cnt = pl_hdr->missed_cnt; 168 plarg.timestamp = pl_hdr->timestamp; 169 #ifdef HELIUMPLUS 170 plarg.type_specific_data = pl_hdr->type_specific_data; 171 #endif 172 if (flags & PHFLAGS_INTERRUPT_CONTEXT) { 173 /* 174 * We are already in interupt context, no need to make it 175 * intsafe. call the function directly. 176 */ 177 pktlog_getbuf_intsafe(&plarg); 178 } else { 179 PKTLOG_LOCK(pl_info); 180 pktlog_getbuf_intsafe(&plarg); 181 PKTLOG_UNLOCK(pl_info); 182 } 183 184 return plarg.buf; 185 } 186 187 static struct txctl_frm_hdr frm_hdr; 188 189 #ifndef HELIUMPLUS 190 static void process_ieee_hdr(void *data) 191 { 192 uint8_t dir; 193 struct ieee80211_frame *wh = (struct ieee80211_frame *)(data); 194 195 frm_hdr.framectrl = *(uint16_t *) (wh->i_fc); 196 frm_hdr.seqctrl = *(uint16_t *) (wh->i_seq); 197 dir = (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK); 198 199 if (dir == IEEE80211_FC1_DIR_TODS) { 200 frm_hdr.bssid_tail = 201 (wh->i_addr1[IEEE80211_ADDR_LEN - 2] << 8) | (wh-> 202 i_addr1 203 [IEEE80211_ADDR_LEN 204 - 1]); 205 frm_hdr.sa_tail = 206 (wh->i_addr2[IEEE80211_ADDR_LEN - 2] << 8) | (wh-> 207 i_addr2 208 [IEEE80211_ADDR_LEN 209 - 1]); 210 frm_hdr.da_tail = 211 (wh->i_addr3[IEEE80211_ADDR_LEN - 2] << 8) | (wh-> 212 i_addr3 213 [IEEE80211_ADDR_LEN 214 - 1]); 215 } else if (dir == IEEE80211_FC1_DIR_FROMDS) { 216 frm_hdr.bssid_tail = 217 (wh->i_addr2[IEEE80211_ADDR_LEN - 2] << 8) | (wh-> 218 i_addr2 219 [IEEE80211_ADDR_LEN 220 - 1]); 221 frm_hdr.sa_tail = 222 (wh->i_addr3[IEEE80211_ADDR_LEN - 2] << 8) | (wh-> 223 i_addr3 224 [IEEE80211_ADDR_LEN 225 - 1]); 226 frm_hdr.da_tail = 227 (wh->i_addr1[IEEE80211_ADDR_LEN - 2] << 8) | (wh-> 228 i_addr1 229 [IEEE80211_ADDR_LEN 230 - 1]); 231 } else { 232 frm_hdr.bssid_tail = 233 (wh->i_addr3[IEEE80211_ADDR_LEN - 2] << 8) | (wh-> 234 i_addr3 235 [IEEE80211_ADDR_LEN 236 - 1]); 237 frm_hdr.sa_tail = 238 (wh->i_addr2[IEEE80211_ADDR_LEN - 2] << 8) | (wh-> 239 i_addr2 240 [IEEE80211_ADDR_LEN 241 - 1]); 242 frm_hdr.da_tail = 243 (wh->i_addr1[IEEE80211_ADDR_LEN - 2] << 8) | (wh-> 244 i_addr1 245 [IEEE80211_ADDR_LEN 246 - 1]); 247 } 248 } 249 250 /** 251 * fill_ieee80211_hdr_data() - fill ieee802.11 data header 252 * @txrx_pdev: txrx pdev 253 * @pl_msdu_info: msdu info 254 * @data: data received from event 255 * 256 * Return: none 257 */ 258 /* TODO: Platform specific function */ 259 static void 260 fill_ieee80211_hdr_data(struct cdp_pdev *pdev, 261 struct ath_pktlog_msdu_info *pl_msdu_info, void *data) 262 { 263 uint32_t i; 264 uint32_t *htt_tx_desc; 265 struct ol_tx_desc_t *tx_desc; 266 uint8_t msdu_id_offset = MSDU_ID_INFO_ID_OFFSET; 267 uint16_t tx_desc_id; 268 uint32_t *msdu_id_info = (uint32_t *) 269 ((void *)data + sizeof(struct ath_pktlog_hdr)); 270 uint32_t *msdu_id = (uint32_t *) ((char *)msdu_id_info + 271 msdu_id_offset); 272 uint8_t *addr, *vap_addr; 273 uint8_t vdev_id; 274 qdf_nbuf_t netbuf; 275 uint32_t len; 276 struct ol_txrx_pdev_t *txrx_pdev = (struct ol_txrx_pdev_t *)pdev; 277 278 279 pl_msdu_info->num_msdu = *msdu_id_info; 280 pl_msdu_info->priv_size = sizeof(uint32_t) * 281 pl_msdu_info->num_msdu + sizeof(uint32_t); 282 283 if (pl_msdu_info->num_msdu > MAX_PKT_INFO_MSDU_ID) { 284 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 285 "%s: Invalid num_msdu count", 286 __func__); 287 qdf_assert(0); 288 return; 289 } 290 for (i = 0; i < pl_msdu_info->num_msdu; i++) { 291 /* 292 * Handle big endianness 293 * Increment msdu_id once after retrieving 294 * lower 16 bits and uppper 16 bits 295 */ 296 if (!(i % 2)) { 297 tx_desc_id = ((*msdu_id & TX_DESC_ID_LOW_MASK) 298 >> TX_DESC_ID_LOW_SHIFT); 299 } else { 300 tx_desc_id = ((*msdu_id & TX_DESC_ID_HIGH_MASK) 301 >> TX_DESC_ID_HIGH_SHIFT); 302 msdu_id += 1; 303 } 304 if (tx_desc_id >= txrx_pdev->tx_desc.pool_size) { 305 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, 306 "%s: drop due to invalid msdu id = %x\n", 307 __func__, tx_desc_id); 308 return; 309 } 310 tx_desc = ol_tx_desc_find(txrx_pdev, tx_desc_id); 311 qdf_assert(tx_desc); 312 netbuf = tx_desc->netbuf; 313 htt_tx_desc = (uint32_t *) tx_desc->htt_tx_desc; 314 qdf_assert(htt_tx_desc); 315 316 qdf_nbuf_peek_header(netbuf, &addr, &len); 317 318 if (len < (2 * IEEE80211_ADDR_LEN)) { 319 qdf_print("TX frame does not have a valid address\n"); 320 return; 321 } 322 /* Adding header information for the TX data frames */ 323 vdev_id = (uint8_t) (*(htt_tx_desc + 324 HTT_TX_VDEV_ID_WORD) >> 325 HTT_TX_VDEV_ID_SHIFT) & 326 HTT_TX_VDEV_ID_MASK; 327 328 vap_addr = wma_get_vdev_address_by_vdev_id(vdev_id); 329 330 frm_hdr.da_tail = (addr[IEEE80211_ADDR_LEN - 2] << 8) | 331 (addr[IEEE80211_ADDR_LEN - 1]); 332 frm_hdr.sa_tail = 333 (addr[2 * IEEE80211_ADDR_LEN - 2] << 8) | 334 (addr[2 * IEEE80211_ADDR_LEN - 1]); 335 if (vap_addr) { 336 frm_hdr.bssid_tail = 337 (vap_addr[IEEE80211_ADDR_LEN - 2] << 8) | 338 (vap_addr[IEEE80211_ADDR_LEN - 1]); 339 } else { 340 frm_hdr.bssid_tail = 0x0000; 341 } 342 pl_msdu_info->priv.msdu_len[i] = *(htt_tx_desc + 343 HTT_TX_MSDU_LEN_DWORD) 344 & HTT_TX_MSDU_LEN_MASK; 345 /* 346 * Add more information per MSDU 347 * e.g., protocol information 348 */ 349 } 350 351 } 352 #endif 353 354 #ifdef HELIUMPLUS 355 A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data) 356 { 357 /* 358 * Must include to process different types 359 * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR 360 */ 361 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 362 struct ath_pktlog_hdr pl_hdr; 363 struct ath_pktlog_info *pl_info; 364 uint32_t *pl_tgt_hdr; 365 struct ol_fw_data *fw_data; 366 uint32_t len; 367 368 if (!txrx_pdev) { 369 printk("Invalid pdev in %s\n", __func__); 370 return A_ERROR; 371 } 372 373 if (!pl_dev) { 374 pr_err("Invalid pktlog handle in %s\n", __func__); 375 qdf_assert(pl_dev); 376 return A_ERROR; 377 } 378 379 qdf_assert(data); 380 381 fw_data = (struct ol_fw_data *)data; 382 len = fw_data->len; 383 if (len < (sizeof(uint32_t) * 384 (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || 385 len < (sizeof(uint32_t) * 386 (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || 387 len < (sizeof(uint32_t) * 388 (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || 389 len < (sizeof(uint32_t) * 390 (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || 391 len < (sizeof(uint32_t) * 392 (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || 393 len < (sizeof(uint32_t) * 394 (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { 395 qdf_print("Invalid msdu len in %s\n", __func__); 396 qdf_assert(0); 397 return A_ERROR; 398 } 399 400 pl_tgt_hdr = (uint32_t *)fw_data->data; 401 /* 402 * Makes the short words (16 bits) portable b/w little endian 403 * and big endian 404 */ 405 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 406 ATH_PKTLOG_HDR_FLAGS_MASK) >> 407 ATH_PKTLOG_HDR_FLAGS_SHIFT; 408 pl_hdr.flags |= PKTLOG_HDR_SIZE_16; 409 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 410 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 411 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 412 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 413 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 414 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 415 pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & 416 ATH_PKTLOG_HDR_MAC_ID_MASK) >> 417 ATH_PKTLOG_HDR_MAC_ID_SHIFT; 418 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 419 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 420 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 421 pl_hdr.type_specific_data = 422 *(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET); 423 pl_info = pl_dev->pl_info; 424 425 if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { 426 qdf_assert(0); 427 return A_ERROR; 428 } 429 430 if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) { 431 size_t log_size = sizeof(frm_hdr) + pl_hdr.size; 432 void *txdesc_hdr_ctl = (void *) 433 pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); 434 qdf_assert(txdesc_hdr_ctl); 435 qdf_assert(pl_hdr.size < (370 * sizeof(u_int32_t))); 436 437 qdf_mem_copy(txdesc_hdr_ctl, &frm_hdr, sizeof(frm_hdr)); 438 qdf_mem_copy((char *)txdesc_hdr_ctl + sizeof(frm_hdr), 439 ((void *)fw_data->data + 440 sizeof(struct ath_pktlog_hdr)), 441 pl_hdr.size); 442 pl_hdr.size = log_size; 443 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 444 txdesc_hdr_ctl); 445 } 446 447 if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) { 448 struct ath_pktlog_tx_status txstat_log; 449 size_t log_size = pl_hdr.size; 450 451 txstat_log.ds_status = (void *) 452 pktlog_getbuf(pl_dev, pl_info, 453 log_size, &pl_hdr); 454 qdf_assert(txstat_log.ds_status); 455 qdf_mem_copy(txstat_log.ds_status, 456 ((void *)fw_data->data + 457 sizeof(struct ath_pktlog_hdr)), 458 pl_hdr.size); 459 /* TODO: MCL specific API */ 460 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 461 txstat_log.ds_status); 462 } 463 return A_OK; 464 } 465 466 #else 467 A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data) 468 { 469 /* 470 * Must include to process different types 471 * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR 472 */ 473 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 474 struct ath_pktlog_hdr pl_hdr; 475 struct ath_pktlog_info *pl_info; 476 uint32_t *pl_tgt_hdr; 477 struct ol_fw_data *fw_data; 478 uint32_t len; 479 480 if (!txrx_pdev) { 481 qdf_print("Invalid pdev in %s\n", __func__); 482 return A_ERROR; 483 } 484 485 qdf_assert(pl_dev); 486 qdf_assert(data); 487 488 fw_data = (struct ol_fw_data *)data; 489 len = fw_data->len; 490 if (len < (sizeof(uint32_t) * 491 (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || 492 len < (sizeof(uint32_t) * 493 (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || 494 len < (sizeof(uint32_t) * 495 (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || 496 len < (sizeof(uint32_t) * 497 (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || 498 len < (sizeof(uint32_t) * 499 (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { 500 qdf_print("Invalid msdu len in %s\n", __func__); 501 qdf_assert(0); 502 return A_ERROR; 503 } 504 505 pl_tgt_hdr = (uint32_t *)fw_data->data; 506 /* 507 * Makes the short words (16 bits) portable b/w little endian 508 * and big endian 509 */ 510 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 511 ATH_PKTLOG_HDR_FLAGS_MASK) >> 512 ATH_PKTLOG_HDR_FLAGS_SHIFT; 513 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 514 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 515 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 516 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 517 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 518 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 519 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 520 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 521 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 522 523 pl_info = pl_dev->pl_info; 524 525 if (pl_hdr.log_type == PKTLOG_TYPE_TX_FRM_HDR) { 526 /* Valid only for the TX CTL */ 527 process_ieee_hdr(fw_data->data + sizeof(pl_hdr)); 528 } 529 530 if (pl_hdr.log_type == PKTLOG_TYPE_TX_VIRT_ADDR) { 531 uint32_t desc_id = (uint32_t) *((uint32_t *)(fw_data->data + 532 sizeof(pl_hdr))); 533 uint32_t vdev_id = desc_id; 534 535 /* if the pkt log msg is for the bcn frame the vdev id 536 * is piggybacked in desc_id and the MSB of the desc ID 537 * would be set to FF 538 */ 539 #define BCN_DESC_ID 0xFF 540 if ((desc_id >> 24) == BCN_DESC_ID) { 541 void *data; 542 uint32_t buf_size; 543 544 vdev_id &= 0x00FFFFFF; 545 /* TODO: MCL specific API */ 546 data = wma_get_beacon_buffer_by_vdev_id(vdev_id, 547 &buf_size); 548 if (data) { 549 /* TODO: platform specific API */ 550 process_ieee_hdr(data); 551 qdf_mem_free(data); 552 } 553 } else { 554 /* 555 * TODO: get the hdr content for mgmt frames from 556 * Tx mgmt desc pool 557 */ 558 } 559 } 560 561 if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) { 562 struct ath_pktlog_txctl txctl_log; 563 size_t log_size = sizeof(txctl_log.priv); 564 565 txctl_log.txdesc_hdr_ctl = (void *)pktlog_getbuf(pl_dev, 566 pl_info, 567 log_size, 568 &pl_hdr); 569 570 if (!txctl_log.txdesc_hdr_ctl) { 571 printk 572 ("failed to get buf for txctl_log.txdesc_hdr_ctl\n"); 573 return A_ERROR; 574 } 575 576 /* 577 * frm hdr is currently Valid only for local frames 578 * Add capability to include the fmr hdr for remote frames 579 */ 580 txctl_log.priv.frm_hdr = frm_hdr; 581 qdf_assert(txctl_log.priv.txdesc_ctl); 582 qdf_assert(pl_hdr.size < sizeof(txctl_log.priv.txdesc_ctl)); 583 pl_hdr.size = (pl_hdr.size > sizeof(txctl_log.priv.txdesc_ctl)) 584 ? sizeof(txctl_log.priv.txdesc_ctl) : 585 pl_hdr.size; 586 587 if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { 588 qdf_assert(0); 589 return A_ERROR; 590 } 591 qdf_mem_copy((void *)&txctl_log.priv.txdesc_ctl, 592 ((void *)fw_data->data + 593 sizeof(struct ath_pktlog_hdr)), 594 pl_hdr.size); 595 qdf_assert(txctl_log.txdesc_hdr_ctl); 596 qdf_mem_copy(txctl_log.txdesc_hdr_ctl, &txctl_log.priv, 597 sizeof(txctl_log.priv)); 598 pl_hdr.size = log_size; 599 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 600 txctl_log.txdesc_hdr_ctl); 601 /* Add Protocol information and HT specific information */ 602 } 603 604 if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) { 605 struct ath_pktlog_tx_status txstat_log; 606 size_t log_size = pl_hdr.size; 607 608 txstat_log.ds_status = (void *) 609 pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); 610 qdf_assert(txstat_log.ds_status); 611 qdf_mem_copy(txstat_log.ds_status, 612 ((void *)fw_data->data + 613 sizeof(struct ath_pktlog_hdr)), 614 pl_hdr.size); 615 616 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 617 txstat_log.ds_status); 618 } 619 620 if (pl_hdr.log_type == PKTLOG_TYPE_TX_MSDU_ID) { 621 struct ath_pktlog_msdu_info pl_msdu_info; 622 size_t log_size; 623 624 qdf_mem_set(&pl_msdu_info, sizeof(pl_msdu_info), 0); 625 log_size = sizeof(pl_msdu_info.priv); 626 627 if (pl_dev->mt_pktlog_enabled == false) 628 fill_ieee80211_hdr_data(txrx_pdev, 629 &pl_msdu_info, fw_data->data); 630 631 pl_msdu_info.ath_msdu_info = pktlog_getbuf(pl_dev, pl_info, 632 log_size, &pl_hdr); 633 qdf_mem_copy((void *)&pl_msdu_info.priv.msdu_id_info, 634 ((void *)fw_data->data + 635 sizeof(struct ath_pktlog_hdr)), 636 sizeof(pl_msdu_info.priv.msdu_id_info)); 637 qdf_mem_copy(pl_msdu_info.ath_msdu_info, &pl_msdu_info.priv, 638 sizeof(pl_msdu_info.priv)); 639 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 640 pl_msdu_info.ath_msdu_info); 641 } 642 643 return A_OK; 644 } 645 #endif 646 647 /* TODO: hardware dependent function */ 648 A_STATUS process_rx_info_remote(void *pdev, void *data) 649 { 650 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 651 struct ath_pktlog_info *pl_info; 652 struct htt_host_rx_desc_base *rx_desc; 653 struct ath_pktlog_hdr pl_hdr; 654 struct ath_pktlog_rx_info rxstat_log; 655 size_t log_size; 656 struct ol_rx_remote_data *r_data = (struct ol_rx_remote_data *)data; 657 qdf_nbuf_t msdu; 658 659 if (!pdev || !r_data || !pl_dev) { 660 qdf_print("%s: Invalid handle", __func__); 661 return A_ERROR; 662 } 663 664 pl_info = pl_dev->pl_info; 665 msdu = r_data->msdu; 666 667 while (msdu) { 668 rx_desc = 669 (struct htt_host_rx_desc_base *)(qdf_nbuf_data(msdu)) - 1; 670 log_size = 671 sizeof(*rx_desc) - sizeof(struct htt_host_fw_desc_base); 672 673 /* 674 * Construct the pktlog header pl_hdr 675 * Because desc is DMA'd to the host memory 676 */ 677 pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); 678 pl_hdr.missed_cnt = 0; 679 #if defined(HELIUMPLUS) 680 pl_hdr.macId = r_data->mac_id; 681 pl_hdr.log_type = PKTLOG_TYPE_RX_STAT; 682 pl_hdr.flags |= PKTLOG_HDR_SIZE_16; 683 #else 684 pl_hdr.log_type = PKTLOG_TYPE_RX_STAT; 685 #endif 686 pl_hdr.size = sizeof(*rx_desc) - 687 sizeof(struct htt_host_fw_desc_base); 688 #if defined(HELIUMPLUS) 689 pl_hdr.timestamp = 690 rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32; 691 pl_hdr.type_specific_data = 0xDEADAA; 692 #else 693 pl_hdr.timestamp = rx_desc->ppdu_end.tsf_timestamp; 694 #endif /* !defined(HELIUMPLUS) */ 695 rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, 696 log_size, &pl_hdr); 697 qdf_mem_copy(rxstat_log.rx_desc, (void *)rx_desc + 698 sizeof(struct htt_host_fw_desc_base), pl_hdr.size); 699 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 700 rxstat_log.rx_desc); 701 msdu = qdf_nbuf_next(msdu); 702 } 703 return A_OK; 704 } 705 706 #ifdef HELIUMPLUS 707 A_STATUS process_rx_info(void *pdev, void *data) 708 { 709 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 710 struct ath_pktlog_info *pl_info; 711 struct ath_pktlog_rx_info rxstat_log; 712 struct ath_pktlog_hdr pl_hdr; 713 size_t log_size; 714 uint32_t *pl_tgt_hdr; 715 struct ol_fw_data *fw_data; 716 uint32_t len; 717 718 if (!pdev) { 719 printk("Invalid pdev in %s", __func__); 720 return A_ERROR; 721 } 722 723 pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev; 724 if (!pl_dev) { 725 printk("Invalid pl_dev in %s", __func__); 726 return A_ERROR; 727 } 728 729 fw_data = (struct ol_fw_data *)data; 730 len = fw_data->len; 731 if (len < (sizeof(uint32_t) * 732 (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || 733 len < (sizeof(uint32_t) * 734 (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || 735 len < (sizeof(uint32_t) * 736 (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || 737 len < (sizeof(uint32_t) * 738 (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || 739 len < (sizeof(uint32_t) * 740 (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || 741 len < (sizeof(uint32_t) * 742 (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { 743 qdf_print("Invalid msdu len in %s\n", __func__); 744 qdf_assert(0); 745 return A_ERROR; 746 } 747 748 pl_info = pl_dev->pl_info; 749 pl_tgt_hdr = (uint32_t *)fw_data->data; 750 751 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 752 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 753 ATH_PKTLOG_HDR_FLAGS_MASK) >> 754 ATH_PKTLOG_HDR_FLAGS_SHIFT; 755 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 756 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 757 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 758 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 759 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 760 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 761 pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & 762 ATH_PKTLOG_HDR_MAC_ID_MASK) >> 763 ATH_PKTLOG_HDR_MAC_ID_SHIFT; 764 pl_hdr.flags |= PKTLOG_HDR_SIZE_16; 765 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 766 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 767 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 768 if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { 769 qdf_assert(0); 770 return A_ERROR; 771 } 772 773 log_size = pl_hdr.size; 774 rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, 775 log_size, &pl_hdr); 776 qdf_mem_copy(rxstat_log.rx_desc, 777 (void *)fw_data->data + sizeof(struct ath_pktlog_hdr), 778 pl_hdr.size); 779 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); 780 781 return A_OK; 782 } 783 784 #else 785 A_STATUS process_rx_info(void *pdev, void *data) 786 { 787 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 788 struct ath_pktlog_info *pl_info; 789 struct ath_pktlog_rx_info rxstat_log; 790 struct ath_pktlog_hdr pl_hdr; 791 size_t log_size; 792 uint32_t *pl_tgt_hdr; 793 struct ol_fw_data *fw_data; 794 uint32_t len; 795 796 if (!pdev) { 797 printk("Invalid pdev in %s", __func__); 798 return A_ERROR; 799 } 800 801 pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev; 802 if (!pl_dev) { 803 printk("Invalid pl_dev in %s", __func__); 804 return A_ERROR; 805 } 806 807 fw_data = (struct ol_fw_data *)data; 808 len = fw_data->len; 809 if (len < (sizeof(uint32_t) * 810 (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || 811 len < (sizeof(uint32_t) * 812 (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || 813 len < (sizeof(uint32_t) * 814 (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || 815 len < (sizeof(uint32_t) * 816 (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || 817 len < (sizeof(uint32_t) * 818 (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { 819 qdf_print("Invalid msdu len in %s\n", __func__); 820 qdf_assert(0); 821 return A_ERROR; 822 } 823 824 pl_info = pl_dev->pl_info; 825 pl_tgt_hdr = (uint32_t *)fw_data->data; 826 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 827 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 828 ATH_PKTLOG_HDR_FLAGS_MASK) >> 829 ATH_PKTLOG_HDR_FLAGS_SHIFT; 830 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 831 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 832 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 833 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 834 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 835 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 836 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 837 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 838 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 839 if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { 840 qdf_assert(0); 841 return A_ERROR; 842 } 843 844 log_size = pl_hdr.size; 845 rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, 846 log_size, &pl_hdr); 847 qdf_mem_copy(rxstat_log.rx_desc, 848 (void *)fw_data->data + sizeof(struct ath_pktlog_hdr), 849 pl_hdr.size); 850 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); 851 852 return A_OK; 853 } 854 #endif 855 856 #ifdef HELIUMPLUS 857 A_STATUS process_rate_find(void *pdev, void *data) 858 { 859 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 860 struct ath_pktlog_hdr pl_hdr; 861 struct ath_pktlog_info *pl_info; 862 size_t log_size; 863 uint32_t len; 864 struct ol_fw_data *fw_data; 865 866 /* 867 * Will be uncommented when the rate control find 868 * for pktlog is implemented in the firmware. 869 * Currently derived from the TX PPDU status 870 */ 871 struct ath_pktlog_rc_find rcf_log; 872 uint32_t *pl_tgt_hdr; 873 874 if (!pdev || !data || !pl_dev) { 875 qdf_print("%s: Invalid handle", __func__); 876 return A_ERROR; 877 } 878 879 fw_data = (struct ol_fw_data *)data; 880 len = fw_data->len; 881 if (len < (sizeof(uint32_t) * 882 (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || 883 len < (sizeof(uint32_t) * 884 (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || 885 len < (sizeof(uint32_t) * 886 (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || 887 len < (sizeof(uint32_t) * 888 (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || 889 len < (sizeof(uint32_t) * 890 (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || 891 len < (sizeof(uint32_t) * 892 (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { 893 qdf_print("Invalid msdu len in %s\n", __func__); 894 qdf_assert(0); 895 return A_ERROR; 896 } 897 898 pl_tgt_hdr = (uint32_t *)fw_data->data; 899 /* 900 * Makes the short words (16 bits) portable b/w little endian 901 * and big endian 902 */ 903 904 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 905 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 906 ATH_PKTLOG_HDR_FLAGS_MASK) >> 907 ATH_PKTLOG_HDR_FLAGS_SHIFT; 908 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 909 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 910 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 911 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 912 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 913 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 914 pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & 915 ATH_PKTLOG_HDR_MAC_ID_MASK) >> 916 ATH_PKTLOG_HDR_MAC_ID_SHIFT; 917 pl_hdr.flags |= PKTLOG_HDR_SIZE_16; 918 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 919 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 920 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 921 pl_info = pl_dev->pl_info; 922 log_size = pl_hdr.size; 923 rcf_log.rcFind = (void *)pktlog_getbuf(pl_dev, pl_info, 924 log_size, &pl_hdr); 925 926 if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { 927 qdf_assert(0); 928 return A_ERROR; 929 } 930 qdf_mem_copy(rcf_log.rcFind, 931 ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), 932 pl_hdr.size); 933 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind); 934 935 return A_OK; 936 } 937 938 #else 939 A_STATUS process_rate_find(void *pdev, void *data) 940 { 941 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 942 struct ath_pktlog_hdr pl_hdr; 943 struct ath_pktlog_info *pl_info; 944 size_t log_size; 945 uint32_t len; 946 struct ol_fw_data *fw_data; 947 948 /* 949 * Will be uncommented when the rate control find 950 * for pktlog is implemented in the firmware. 951 * Currently derived from the TX PPDU status 952 */ 953 struct ath_pktlog_rc_find rcf_log; 954 uint32_t *pl_tgt_hdr; 955 956 if (!pdev || !data || !pl_dev) { 957 qdf_print("%s: Invalid handle", __func__); 958 return A_ERROR; 959 } 960 961 fw_data = (struct ol_fw_data *)data; 962 len = fw_data->len; 963 if (len < (sizeof(uint32_t) * 964 (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || 965 len < (sizeof(uint32_t) * 966 (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || 967 len < (sizeof(uint32_t) * 968 (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || 969 len < (sizeof(uint32_t) * 970 (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || 971 len < (sizeof(uint32_t) * 972 (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { 973 qdf_print("Invalid msdu len in %s\n", __func__); 974 qdf_assert(0); 975 return A_ERROR; 976 } 977 978 pl_tgt_hdr = (uint32_t *)fw_data->data; 979 /* 980 * Makes the short words (16 bits) portable b/w little endian 981 * and big endian 982 */ 983 984 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 985 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 986 ATH_PKTLOG_HDR_FLAGS_MASK) >> 987 ATH_PKTLOG_HDR_FLAGS_SHIFT; 988 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 989 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 990 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 991 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 992 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 993 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 994 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 995 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 996 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 997 pl_info = pl_dev->pl_info; 998 log_size = pl_hdr.size; 999 rcf_log.rcFind = (void *)pktlog_getbuf(pl_dev, pl_info, 1000 log_size, &pl_hdr); 1001 1002 if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { 1003 qdf_assert(0); 1004 return A_ERROR; 1005 } 1006 qdf_mem_copy(rcf_log.rcFind, 1007 ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), 1008 pl_hdr.size); 1009 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind); 1010 1011 return A_OK; 1012 } 1013 #endif 1014 1015 #ifdef HELIUMPLUS 1016 A_STATUS process_sw_event(void *pdev, void *data) 1017 { 1018 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 1019 struct ath_pktlog_hdr pl_hdr; 1020 struct ath_pktlog_info *pl_info; 1021 size_t log_size; 1022 uint32_t len; 1023 struct ol_fw_data *fw_data; 1024 1025 /* 1026 * Will be uncommented when the rate control find 1027 * for pktlog is implemented in the firmware. 1028 * Currently derived from the TX PPDU status 1029 */ 1030 struct ath_pktlog_sw_event sw_event; 1031 uint32_t *pl_tgt_hdr; 1032 1033 if (!pdev) { 1034 qdf_print("Invalid pdev in %s\n", __func__); 1035 return A_ERROR; 1036 } 1037 if (!data) { 1038 qdf_print("Invalid data in %s\n", __func__); 1039 return A_ERROR; 1040 } 1041 if (!pl_dev) { 1042 qdf_print("Invalid pl_dev in %s", __func__); 1043 return A_ERROR; 1044 } 1045 1046 fw_data = (struct ol_fw_data *)data; 1047 len = fw_data->len; 1048 if (len < (sizeof(uint32_t) * 1049 (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || 1050 len < (sizeof(uint32_t) * 1051 (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || 1052 len < (sizeof(uint32_t) * 1053 (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || 1054 len < (sizeof(uint32_t) * 1055 (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || 1056 len < (sizeof(uint32_t) * 1057 (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || 1058 len < (sizeof(uint32_t) * 1059 (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { 1060 qdf_print("Invalid msdu len in %s\n", __func__); 1061 qdf_assert(0); 1062 return A_ERROR; 1063 } 1064 1065 pl_tgt_hdr = (uint32_t *)fw_data->data; 1066 /* 1067 * Makes the short words (16 bits) portable b/w little endian 1068 * and big endian 1069 */ 1070 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 1071 ATH_PKTLOG_HDR_FLAGS_MASK) >> 1072 ATH_PKTLOG_HDR_FLAGS_SHIFT; 1073 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 1074 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 1075 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 1076 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 1077 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 1078 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 1079 pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & 1080 ATH_PKTLOG_HDR_MAC_ID_MASK) >> 1081 ATH_PKTLOG_HDR_MAC_ID_SHIFT; 1082 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 1083 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 1084 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 1085 1086 pl_hdr.type_specific_data = 1087 *(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET); 1088 pl_info = pl_dev->pl_info; 1089 log_size = pl_hdr.size; 1090 sw_event.sw_event = (void *)pktlog_getbuf(pl_dev, pl_info, 1091 log_size, &pl_hdr); 1092 if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { 1093 qdf_assert(0); 1094 return A_ERROR; 1095 } 1096 qdf_mem_copy(sw_event.sw_event, 1097 ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), 1098 pl_hdr.size); 1099 1100 return A_OK; 1101 } 1102 1103 #else 1104 A_STATUS process_sw_event(void *pdev, void *data) 1105 { 1106 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 1107 struct ath_pktlog_hdr pl_hdr; 1108 struct ath_pktlog_info *pl_info; 1109 size_t log_size; 1110 uint32_t len; 1111 struct ol_fw_data *fw_data; 1112 1113 /* 1114 * Will be uncommented when the rate control find 1115 * for pktlog is implemented in the firmware. 1116 * Currently derived from the TX PPDU status 1117 */ 1118 struct ath_pktlog_sw_event sw_event; 1119 uint32_t *pl_tgt_hdr; 1120 1121 if (!pdev) { 1122 qdf_print("Invalid pdev in %s\n", __func__); 1123 return A_ERROR; 1124 } 1125 if (!data) { 1126 qdf_print("Invalid data in %s\n", __func__); 1127 return A_ERROR; 1128 } 1129 if (!pl_dev) { 1130 qdf_print("Invalid pl_dev in %s", __func__); 1131 return A_ERROR; 1132 } 1133 1134 fw_data = (struct ol_fw_data *)data; 1135 len = fw_data->len; 1136 if (len < (sizeof(uint32_t) * 1137 (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || 1138 len < (sizeof(uint32_t) * 1139 (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || 1140 len < (sizeof(uint32_t) * 1141 (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || 1142 len < (sizeof(uint32_t) * 1143 (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || 1144 len < (sizeof(uint32_t) * 1145 (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { 1146 qdf_print("Invalid msdu len in %s\n", __func__); 1147 qdf_assert(0); 1148 return A_ERROR; 1149 } 1150 1151 pl_tgt_hdr = (uint32_t *)fw_data->data; 1152 /* 1153 * Makes the short words (16 bits) portable b/w little endian 1154 * and big endian 1155 */ 1156 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 1157 ATH_PKTLOG_HDR_FLAGS_MASK) >> 1158 ATH_PKTLOG_HDR_FLAGS_SHIFT; 1159 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 1160 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 1161 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 1162 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 1163 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 1164 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 1165 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 1166 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 1167 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 1168 pl_info = pl_dev->pl_info; 1169 log_size = pl_hdr.size; 1170 sw_event.sw_event = (void *)pktlog_getbuf(pl_dev, pl_info, 1171 log_size, &pl_hdr); 1172 if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { 1173 qdf_assert(0); 1174 return A_ERROR; 1175 } 1176 qdf_mem_copy(sw_event.sw_event, 1177 ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), 1178 pl_hdr.size); 1179 1180 return A_OK; 1181 } 1182 #endif 1183 1184 #ifdef HELIUMPLUS 1185 A_STATUS process_rate_update(void *pdev, void *data) 1186 { 1187 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 1188 struct ath_pktlog_hdr pl_hdr; 1189 size_t log_size; 1190 struct ath_pktlog_info *pl_info; 1191 struct ath_pktlog_rc_update rcu_log; 1192 uint32_t *pl_tgt_hdr; 1193 struct ol_fw_data *fw_data; 1194 uint32_t len; 1195 1196 if (!pdev || !data || !pl_dev) { 1197 qdf_print("%s: Invalid handle", __func__); 1198 return A_ERROR; 1199 } 1200 1201 fw_data = (struct ol_fw_data *)data; 1202 len = fw_data->len; 1203 if (len < (sizeof(uint32_t) * 1204 (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || 1205 len < (sizeof(uint32_t) * 1206 (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || 1207 len < (sizeof(uint32_t) * 1208 (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || 1209 len < (sizeof(uint32_t) * 1210 (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || 1211 len < (sizeof(uint32_t) * 1212 (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || 1213 len < (sizeof(uint32_t) * 1214 (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { 1215 qdf_print("Invalid msdu len in %s\n", __func__); 1216 qdf_assert(0); 1217 return A_ERROR; 1218 } 1219 1220 pl_tgt_hdr = (uint32_t *)fw_data->data; 1221 /* 1222 * Makes the short words (16 bits) portable b/w little endian 1223 * and big endian 1224 */ 1225 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 1226 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 1227 ATH_PKTLOG_HDR_FLAGS_MASK) >> 1228 ATH_PKTLOG_HDR_FLAGS_SHIFT; 1229 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 1230 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 1231 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 1232 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 1233 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 1234 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 1235 pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & 1236 ATH_PKTLOG_HDR_MAC_ID_MASK) >> 1237 ATH_PKTLOG_HDR_MAC_ID_SHIFT; 1238 pl_hdr.flags |= PKTLOG_HDR_SIZE_16; 1239 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 1240 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 1241 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 1242 log_size = pl_hdr.size; 1243 pl_info = pl_dev->pl_info; 1244 1245 /* 1246 * Will be uncommented when the rate control update 1247 * for pktlog is implemented in the firmware. 1248 * Currently derived from the TX PPDU status 1249 */ 1250 rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info, 1251 log_size, &pl_hdr); 1252 if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { 1253 qdf_assert(0); 1254 return A_ERROR; 1255 } 1256 qdf_mem_copy(rcu_log.txRateCtrl, 1257 ((char *)fw_data->data + 1258 sizeof(struct ath_pktlog_hdr)), 1259 pl_hdr.size); 1260 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl); 1261 return A_OK; 1262 } 1263 1264 #else 1265 A_STATUS process_rate_update(void *pdev, void *data) 1266 { 1267 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 1268 struct ath_pktlog_hdr pl_hdr; 1269 size_t log_size; 1270 struct ath_pktlog_info *pl_info; 1271 struct ath_pktlog_rc_update rcu_log; 1272 uint32_t *pl_tgt_hdr; 1273 struct ol_fw_data *fw_data; 1274 uint32_t len; 1275 1276 if (!pdev || !data || !pl_dev) { 1277 qdf_print("%s: Invalid handle", __func__); 1278 return A_ERROR; 1279 } 1280 1281 fw_data = (struct ol_fw_data *)data; 1282 len = fw_data->len; 1283 if (len < (sizeof(uint32_t) * 1284 (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || 1285 len < (sizeof(uint32_t) * 1286 (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || 1287 len < (sizeof(uint32_t) * 1288 (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || 1289 len < (sizeof(uint32_t) * 1290 (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || 1291 len < (sizeof(uint32_t) * 1292 (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { 1293 qdf_print("Invalid msdu len in %s\n", __func__); 1294 qdf_assert(0); 1295 return A_ERROR; 1296 } 1297 1298 pl_tgt_hdr = (uint32_t *)fw_data->data; 1299 /* 1300 * Makes the short words (16 bits) portable b/w little endian 1301 * and big endian 1302 */ 1303 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 1304 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 1305 ATH_PKTLOG_HDR_FLAGS_MASK) >> 1306 ATH_PKTLOG_HDR_FLAGS_SHIFT; 1307 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 1308 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 1309 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 1310 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 1311 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 1312 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 1313 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 1314 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 1315 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 1316 log_size = pl_hdr.size; 1317 pl_info = pl_dev->pl_info; 1318 1319 /* 1320 * Will be uncommented when the rate control update 1321 * for pktlog is implemented in the firmware. 1322 * Currently derived from the TX PPDU status 1323 */ 1324 rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info, 1325 log_size, &pl_hdr); 1326 if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { 1327 qdf_assert(0); 1328 return A_ERROR; 1329 } 1330 qdf_mem_copy(rcu_log.txRateCtrl, 1331 ((char *)fw_data->data + 1332 sizeof(struct ath_pktlog_hdr)), 1333 pl_hdr.size); 1334 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl); 1335 return A_OK; 1336 } 1337 #endif 1338 1339 #ifdef QCA_WIFI_QCA6290 1340 int process_rx_desc_remote(void *pdev, void *data) 1341 { 1342 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 1343 struct ath_pktlog_hdr pl_hdr; 1344 struct ath_pktlog_rx_info rxstat_log; 1345 size_t log_size; 1346 struct ath_pktlog_info *pl_info; 1347 qdf_nbuf_t log_nbuf = (qdf_nbuf_t)data; 1348 1349 pl_info = pl_dev->pl_info; 1350 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 1351 pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); 1352 pl_hdr.missed_cnt = 0; 1353 pl_hdr.log_type = 22; /*PKTLOG_TYPE_RX_STATBUF*/ 1354 pl_hdr.size = qdf_nbuf_len(log_nbuf); 1355 pl_hdr.timestamp = 0; 1356 log_size = pl_hdr.size; 1357 rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, 1358 log_size, &pl_hdr); 1359 1360 if (rxstat_log.rx_desc == NULL) { 1361 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 1362 "%s: Rx descriptor is NULL", __func__); 1363 return -EFAULT; 1364 } 1365 1366 qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size); 1367 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 1368 rxstat_log.rx_desc); 1369 return 0; 1370 } 1371 1372 int 1373 process_pktlog_lite(void *context, void *log_data, uint16_t log_type) 1374 { 1375 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 1376 struct ath_pktlog_info *pl_info; 1377 struct ath_pktlog_hdr pl_hdr; 1378 struct ath_pktlog_rx_info rxstat_log; 1379 size_t log_size; 1380 qdf_nbuf_t log_nbuf = (qdf_nbuf_t)log_data; 1381 1382 pl_info = pl_dev->pl_info; 1383 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 1384 pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); 1385 pl_hdr.missed_cnt = 0; 1386 pl_hdr.log_type = log_type; 1387 pl_hdr.size = qdf_nbuf_len(log_nbuf); 1388 pl_hdr.timestamp = 0; 1389 log_size = pl_hdr.size; 1390 rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, 1391 log_size, &pl_hdr); 1392 1393 if (rxstat_log.rx_desc == NULL) { 1394 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 1395 "%s: Rx descriptor is NULL", __func__); 1396 return -EFAULT; 1397 } 1398 1399 qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size); 1400 1401 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); 1402 return 0; 1403 } 1404 #else 1405 int process_rx_desc_remote(void *pdev, void *data) 1406 { 1407 return 0; 1408 } 1409 int 1410 process_pktlog_lite(void *context, void *log_data, uint16_t log_type) 1411 { 1412 return 0; 1413 } 1414 #endif 1415 #endif /*REMOVE_PKT_LOG */ 1416