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