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 366 if (!txrx_pdev) { 367 printk("Invalid pdev in %s\n", __func__); 368 return A_ERROR; 369 } 370 371 qdf_assert(pl_dev); 372 qdf_assert(data); 373 374 pl_tgt_hdr = (uint32_t *) data; 375 /* 376 * Makes the short words (16 bits) portable b/w little endian 377 * and big endian 378 */ 379 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 380 ATH_PKTLOG_HDR_FLAGS_MASK) >> 381 ATH_PKTLOG_HDR_FLAGS_SHIFT; 382 pl_hdr.flags |= PKTLOG_HDR_SIZE_16; 383 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 384 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 385 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 386 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 387 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 388 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 389 pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & 390 ATH_PKTLOG_HDR_MAC_ID_MASK) >> 391 ATH_PKTLOG_HDR_MAC_ID_SHIFT; 392 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 393 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 394 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 395 pl_hdr.type_specific_data = 396 *(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET); 397 pl_info = pl_dev->pl_info; 398 399 if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) { 400 size_t log_size = sizeof(frm_hdr) + pl_hdr.size; 401 void *txdesc_hdr_ctl = (void *) 402 pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); 403 qdf_assert(txdesc_hdr_ctl); 404 qdf_assert(pl_hdr.size < (370 * sizeof(u_int32_t))); 405 406 qdf_mem_copy(txdesc_hdr_ctl, &frm_hdr, sizeof(frm_hdr)); 407 qdf_mem_copy((char *)txdesc_hdr_ctl + sizeof(frm_hdr), 408 ((void *)data + 409 sizeof(struct ath_pktlog_hdr)), 410 pl_hdr.size); 411 pl_hdr.size = log_size; 412 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 413 txdesc_hdr_ctl); 414 } 415 416 if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) { 417 struct ath_pktlog_tx_status txstat_log; 418 size_t log_size = pl_hdr.size; 419 420 txstat_log.ds_status = (void *) 421 pktlog_getbuf(pl_dev, pl_info, 422 log_size, &pl_hdr); 423 qdf_assert(txstat_log.ds_status); 424 qdf_mem_copy(txstat_log.ds_status, 425 ((void *)data + sizeof(struct ath_pktlog_hdr)), 426 pl_hdr.size); 427 /* TODO: MCL specific API */ 428 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 429 txstat_log.ds_status); 430 } 431 return A_OK; 432 } 433 434 #else 435 A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data) 436 { 437 /* 438 * Must include to process different types 439 * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR 440 */ 441 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 442 struct ath_pktlog_hdr pl_hdr; 443 struct ath_pktlog_info *pl_info; 444 uint32_t *pl_tgt_hdr; 445 446 if (!txrx_pdev) { 447 qdf_print("Invalid pdev in %s\n", __func__); 448 return A_ERROR; 449 } 450 451 qdf_assert(pl_dev); 452 qdf_assert(data); 453 454 pl_tgt_hdr = (uint32_t *) data; 455 /* 456 * Makes the short words (16 bits) portable b/w little endian 457 * and big endian 458 */ 459 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 460 ATH_PKTLOG_HDR_FLAGS_MASK) >> 461 ATH_PKTLOG_HDR_FLAGS_SHIFT; 462 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 463 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 464 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 465 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 466 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 467 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 468 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 469 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 470 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 471 472 pl_info = pl_dev->pl_info; 473 474 if (pl_hdr.log_type == PKTLOG_TYPE_TX_FRM_HDR) { 475 /* Valid only for the TX CTL */ 476 process_ieee_hdr(data + sizeof(pl_hdr)); 477 } 478 479 if (pl_hdr.log_type == PKTLOG_TYPE_TX_VIRT_ADDR) { 480 A_UINT32 desc_id = (A_UINT32) 481 *((A_UINT32 *) (data + sizeof(pl_hdr))); 482 A_UINT32 vdev_id = desc_id; 483 484 /* if the pkt log msg is for the bcn frame the vdev id 485 * is piggybacked in desc_id and the MSB of the desc ID 486 * would be set to FF 487 */ 488 #define BCN_DESC_ID 0xFF 489 if ((desc_id >> 24) == BCN_DESC_ID) { 490 void *data; 491 A_UINT32 buf_size; 492 493 vdev_id &= 0x00FFFFFF; 494 /* TODO: MCL specific API */ 495 data = wma_get_beacon_buffer_by_vdev_id(vdev_id, 496 &buf_size); 497 if (data) { 498 /* TODO: platform specific API */ 499 process_ieee_hdr(data); 500 qdf_mem_free(data); 501 } 502 } else { 503 /* 504 * TODO: get the hdr content for mgmt frames from 505 * Tx mgmt desc pool 506 */ 507 } 508 } 509 510 if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) { 511 struct ath_pktlog_txctl txctl_log; 512 size_t log_size = sizeof(txctl_log.priv); 513 514 txctl_log.txdesc_hdr_ctl = (void *)pktlog_getbuf(pl_dev, 515 pl_info, 516 log_size, 517 &pl_hdr); 518 519 if (!txctl_log.txdesc_hdr_ctl) { 520 printk 521 ("failed to get buf for txctl_log.txdesc_hdr_ctl\n"); 522 return A_ERROR; 523 } 524 525 /* 526 * frm hdr is currently Valid only for local frames 527 * Add capability to include the fmr hdr for remote frames 528 */ 529 txctl_log.priv.frm_hdr = frm_hdr; 530 qdf_assert(txctl_log.priv.txdesc_ctl); 531 qdf_assert(pl_hdr.size < sizeof(txctl_log.priv.txdesc_ctl)); 532 pl_hdr.size = (pl_hdr.size > sizeof(txctl_log.priv.txdesc_ctl)) 533 ? sizeof(txctl_log.priv.txdesc_ctl) : 534 pl_hdr.size; 535 qdf_mem_copy((void *)&txctl_log.priv.txdesc_ctl, 536 ((void *)data + sizeof(struct ath_pktlog_hdr)), 537 pl_hdr.size); 538 qdf_assert(txctl_log.txdesc_hdr_ctl); 539 qdf_mem_copy(txctl_log.txdesc_hdr_ctl, &txctl_log.priv, 540 sizeof(txctl_log.priv)); 541 pl_hdr.size = log_size; 542 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 543 txctl_log.txdesc_hdr_ctl); 544 /* Add Protocol information and HT specific information */ 545 } 546 547 if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) { 548 struct ath_pktlog_tx_status txstat_log; 549 size_t log_size = pl_hdr.size; 550 551 txstat_log.ds_status = (void *) 552 pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); 553 qdf_assert(txstat_log.ds_status); 554 qdf_mem_copy(txstat_log.ds_status, 555 ((void *)data + sizeof(struct ath_pktlog_hdr)), 556 pl_hdr.size); 557 558 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 559 txstat_log.ds_status); 560 } 561 562 if (pl_hdr.log_type == PKTLOG_TYPE_TX_MSDU_ID) { 563 struct ath_pktlog_msdu_info pl_msdu_info; 564 size_t log_size; 565 566 qdf_mem_set(&pl_msdu_info, sizeof(pl_msdu_info), 0); 567 log_size = sizeof(pl_msdu_info.priv); 568 569 if (pl_dev->mt_pktlog_enabled == false) 570 fill_ieee80211_hdr_data(txrx_pdev, &pl_msdu_info, data); 571 572 pl_msdu_info.ath_msdu_info = pktlog_getbuf(pl_dev, pl_info, 573 log_size, &pl_hdr); 574 qdf_mem_copy((void *)&pl_msdu_info.priv.msdu_id_info, 575 ((void *)data + sizeof(struct ath_pktlog_hdr)), 576 sizeof(pl_msdu_info.priv.msdu_id_info)); 577 qdf_mem_copy(pl_msdu_info.ath_msdu_info, &pl_msdu_info.priv, 578 sizeof(pl_msdu_info.priv)); 579 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 580 pl_msdu_info.ath_msdu_info); 581 } 582 583 return A_OK; 584 } 585 #endif 586 587 /* TODO: hardware dependent function */ 588 A_STATUS process_rx_info_remote(void *pdev, void *data) 589 { 590 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 591 struct ath_pktlog_info *pl_info; 592 struct htt_host_rx_desc_base *rx_desc; 593 struct ath_pktlog_hdr pl_hdr; 594 struct ath_pktlog_rx_info rxstat_log; 595 size_t log_size; 596 struct ol_rx_remote_data *r_data = (struct ol_rx_remote_data *)data; 597 qdf_nbuf_t msdu; 598 599 if (!pdev || !r_data || !pl_dev) { 600 qdf_print("%s: Invalid handle", __func__); 601 return A_ERROR; 602 } 603 604 pl_info = pl_dev->pl_info; 605 msdu = r_data->msdu; 606 607 while (msdu) { 608 rx_desc = 609 (struct htt_host_rx_desc_base *)(qdf_nbuf_data(msdu)) - 1; 610 log_size = 611 sizeof(*rx_desc) - sizeof(struct htt_host_fw_desc_base); 612 613 /* 614 * Construct the pktlog header pl_hdr 615 * Because desc is DMA'd to the host memory 616 */ 617 pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); 618 pl_hdr.missed_cnt = 0; 619 #if defined(HELIUMPLUS) 620 pl_hdr.macId = r_data->mac_id; 621 pl_hdr.log_type = PKTLOG_TYPE_RX_STAT; 622 pl_hdr.flags |= PKTLOG_HDR_SIZE_16; 623 #else 624 pl_hdr.log_type = PKTLOG_TYPE_RX_STAT; 625 #endif 626 pl_hdr.size = sizeof(*rx_desc) - 627 sizeof(struct htt_host_fw_desc_base); 628 #if defined(HELIUMPLUS) 629 pl_hdr.timestamp = 630 rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32; 631 pl_hdr.type_specific_data = 0xDEADAA; 632 #else 633 pl_hdr.timestamp = rx_desc->ppdu_end.tsf_timestamp; 634 #endif /* !defined(HELIUMPLUS) */ 635 rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, 636 log_size, &pl_hdr); 637 qdf_mem_copy(rxstat_log.rx_desc, (void *)rx_desc + 638 sizeof(struct htt_host_fw_desc_base), pl_hdr.size); 639 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 640 rxstat_log.rx_desc); 641 msdu = qdf_nbuf_next(msdu); 642 } 643 return A_OK; 644 } 645 646 A_STATUS process_rx_info(void *pdev, void *data) 647 { 648 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 649 struct ath_pktlog_info *pl_info; 650 struct ath_pktlog_rx_info rxstat_log; 651 struct ath_pktlog_hdr pl_hdr; 652 size_t log_size; 653 uint32_t *pl_tgt_hdr; 654 655 if (!pdev) { 656 printk("Invalid pdev in %s", __func__); 657 return A_ERROR; 658 } 659 660 if (!pl_dev) { 661 printk("Invalid pl_dev in %s", __func__); 662 return A_ERROR; 663 } 664 665 pl_info = pl_dev->pl_info; 666 pl_tgt_hdr = (uint32_t *) data; 667 668 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 669 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 670 ATH_PKTLOG_HDR_FLAGS_MASK) >> 671 ATH_PKTLOG_HDR_FLAGS_SHIFT; 672 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 673 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 674 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 675 #ifdef HELIUMPLUS 676 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 677 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 678 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 679 pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & 680 ATH_PKTLOG_HDR_MAC_ID_MASK) >> 681 ATH_PKTLOG_HDR_MAC_ID_SHIFT; 682 pl_hdr.flags |= PKTLOG_HDR_SIZE_16; 683 #else 684 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 685 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 686 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 687 #endif 688 689 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 690 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 691 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 692 log_size = pl_hdr.size; 693 rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, 694 log_size, &pl_hdr); 695 696 qdf_mem_copy(rxstat_log.rx_desc, 697 (void *)data + sizeof(struct ath_pktlog_hdr), pl_hdr.size); 698 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); 699 700 return A_OK; 701 } 702 703 A_STATUS process_rate_find(void *pdev, void *data) 704 { 705 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 706 struct ath_pktlog_hdr pl_hdr; 707 struct ath_pktlog_info *pl_info; 708 size_t log_size; 709 710 /* 711 * Will be uncommented when the rate control find 712 * for pktlog is implemented in the firmware. 713 * Currently derived from the TX PPDU status 714 */ 715 struct ath_pktlog_rc_find rcf_log; 716 uint32_t *pl_tgt_hdr; 717 718 if (!pdev || !data || !pl_dev) { 719 qdf_print("%s: Invalid handle", __func__); 720 return A_ERROR; 721 } 722 723 pl_tgt_hdr = (uint32_t *) data; 724 /* 725 * Makes the short words (16 bits) portable b/w little endian 726 * and big endian 727 */ 728 729 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 730 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 731 ATH_PKTLOG_HDR_FLAGS_MASK) >> 732 ATH_PKTLOG_HDR_FLAGS_SHIFT; 733 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 734 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 735 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 736 #ifdef HELIUMPLUS 737 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 738 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 739 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 740 pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & 741 ATH_PKTLOG_HDR_MAC_ID_MASK) >> 742 ATH_PKTLOG_HDR_MAC_ID_SHIFT; 743 pl_hdr.flags |= PKTLOG_HDR_SIZE_16; 744 745 #else 746 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 747 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 748 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 749 #endif 750 751 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 752 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 753 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 754 pl_info = pl_dev->pl_info; 755 log_size = pl_hdr.size; 756 rcf_log.rcFind = (void *)pktlog_getbuf(pl_dev, pl_info, 757 log_size, &pl_hdr); 758 759 qdf_mem_copy(rcf_log.rcFind, 760 ((char *)data + sizeof(struct ath_pktlog_hdr)), 761 pl_hdr.size); 762 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind); 763 764 return A_OK; 765 } 766 767 A_STATUS process_sw_event(void *pdev, void *data) 768 { 769 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 770 struct ath_pktlog_hdr pl_hdr; 771 struct ath_pktlog_info *pl_info; 772 size_t log_size; 773 774 /* 775 * Will be uncommented when the rate control find 776 * for pktlog is implemented in the firmware. 777 * Currently derived from the TX PPDU status 778 */ 779 struct ath_pktlog_sw_event sw_event; 780 uint32_t *pl_tgt_hdr; 781 782 if (!pdev) { 783 qdf_print("Invalid pdev in %s\n", __func__); 784 return A_ERROR; 785 } 786 if (!data) { 787 qdf_print("Invalid data in %s\n", __func__); 788 return A_ERROR; 789 } 790 if (!pl_dev) { 791 qdf_print("Invalid pl_dev in %s", __func__); 792 return A_ERROR; 793 } 794 795 796 pl_tgt_hdr = (uint32_t *) data; 797 /* 798 * Makes the short words (16 bits) portable b/w little endian 799 * and big endian 800 */ 801 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 802 ATH_PKTLOG_HDR_FLAGS_MASK) >> 803 ATH_PKTLOG_HDR_FLAGS_SHIFT; 804 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 805 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 806 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 807 #ifdef HELIUMPLUS 808 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 809 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 810 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 811 pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & 812 ATH_PKTLOG_HDR_MAC_ID_MASK) >> 813 ATH_PKTLOG_HDR_MAC_ID_SHIFT; 814 #else 815 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 816 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 817 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 818 #endif 819 820 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 821 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 822 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 823 824 #ifdef HELIUMPLUS 825 pl_hdr.type_specific_data = 826 *(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET); 827 #endif 828 829 pl_info = pl_dev->pl_info; 830 log_size = pl_hdr.size; 831 sw_event.sw_event = (void *)pktlog_getbuf(pl_dev, pl_info, 832 log_size, &pl_hdr); 833 834 qdf_mem_copy(sw_event.sw_event, 835 ((char *)data + sizeof(struct ath_pktlog_hdr)), 836 pl_hdr.size); 837 838 return A_OK; 839 } 840 841 A_STATUS process_rate_update(void *pdev, void *data) 842 { 843 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 844 struct ath_pktlog_hdr pl_hdr; 845 size_t log_size; 846 struct ath_pktlog_info *pl_info; 847 struct ath_pktlog_rc_update rcu_log; 848 uint32_t *pl_tgt_hdr; 849 850 if (!pdev || !data || !pl_dev) { 851 qdf_print("%s: Invalid handle", __func__); 852 return A_ERROR; 853 } 854 855 pl_tgt_hdr = (uint32_t *) data; 856 /* 857 * Makes the short words (16 bits) portable b/w little endian 858 * and big endian 859 */ 860 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 861 pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & 862 ATH_PKTLOG_HDR_FLAGS_MASK) >> 863 ATH_PKTLOG_HDR_FLAGS_SHIFT; 864 pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & 865 ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> 866 ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; 867 #ifdef HELIUMPLUS 868 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 869 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 870 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 871 pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & 872 ATH_PKTLOG_HDR_MAC_ID_MASK) >> 873 ATH_PKTLOG_HDR_MAC_ID_SHIFT; 874 pl_hdr.flags |= PKTLOG_HDR_SIZE_16; 875 #else 876 pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & 877 ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> 878 ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; 879 #endif 880 881 pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & 882 ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; 883 pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); 884 log_size = pl_hdr.size; 885 pl_info = pl_dev->pl_info; 886 887 /* 888 * Will be uncommented when the rate control update 889 * for pktlog is implemented in the firmware. 890 * Currently derived from the TX PPDU status 891 */ 892 rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info, 893 log_size, &pl_hdr); 894 qdf_mem_copy(rcu_log.txRateCtrl, 895 ((char *)data + sizeof(struct ath_pktlog_hdr)), 896 pl_hdr.size); 897 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl); 898 return A_OK; 899 } 900 #ifdef QCA_WIFI_QCA6290 901 int process_rx_desc_remote(void *pdev, void *data) 902 { 903 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 904 struct ath_pktlog_hdr pl_hdr; 905 struct ath_pktlog_rx_info rxstat_log; 906 size_t log_size; 907 struct ath_pktlog_info *pl_info; 908 qdf_nbuf_t log_nbuf = (qdf_nbuf_t)data; 909 910 pl_info = pl_dev->pl_info; 911 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 912 pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); 913 pl_hdr.missed_cnt = 0; 914 pl_hdr.log_type = 22; /*PKTLOG_TYPE_RX_STATBUF*/ 915 pl_hdr.size = qdf_nbuf_len(log_nbuf); 916 pl_hdr.timestamp = 0; 917 log_size = pl_hdr.size; 918 rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, 919 log_size, &pl_hdr); 920 921 if (rxstat_log.rx_desc == NULL) { 922 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 923 "%s: Rx descriptor is NULL", __func__); 924 return -EFAULT; 925 } 926 927 qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size); 928 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, 929 rxstat_log.rx_desc); 930 return 0; 931 } 932 933 int 934 process_pktlog_lite(void *context, void *log_data, uint16_t log_type) 935 { 936 struct pktlog_dev_t *pl_dev = get_pktlog_handle(); 937 struct ath_pktlog_info *pl_info; 938 struct ath_pktlog_hdr pl_hdr; 939 struct ath_pktlog_rx_info rxstat_log; 940 size_t log_size; 941 qdf_nbuf_t log_nbuf = (qdf_nbuf_t)log_data; 942 943 pl_info = pl_dev->pl_info; 944 qdf_mem_set(&pl_hdr, sizeof(pl_hdr), 0); 945 pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); 946 pl_hdr.missed_cnt = 0; 947 pl_hdr.log_type = log_type; 948 pl_hdr.size = qdf_nbuf_len(log_nbuf); 949 pl_hdr.timestamp = 0; 950 log_size = pl_hdr.size; 951 rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, 952 log_size, &pl_hdr); 953 954 if (rxstat_log.rx_desc == NULL) { 955 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 956 "%s: Rx descriptor is NULL", __func__); 957 return -EFAULT; 958 } 959 960 qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size); 961 962 cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); 963 return 0; 964 } 965 #else 966 int process_rx_desc_remote(void *pdev, void *data) 967 { 968 return 0; 969 } 970 int 971 process_pktlog_lite(void *context, void *log_data, uint16_t log_type) 972 { 973 return 0; 974 } 975 #endif 976 #endif /*REMOVE_PKT_LOG */ 977