1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 #include "hif_io32.h" 20 #include "reg_struct.h" 21 #include "ce_api.h" 22 #include "ce_main.h" 23 #include "ce_internal.h" 24 #include "ce_reg.h" 25 #include "qdf_lock.h" 26 #include "regtable.h" 27 #include "hif_main.h" 28 #include "hif_debug.h" 29 #include "hal_api.h" 30 #include "pld_common.h" 31 #include "qdf_module.h" 32 #include "hif.h" 33 34 /* 35 * Support for Copy Engine hardware, which is mainly used for 36 * communication between Host and Target over a PCIe interconnect. 37 */ 38 39 /* 40 * A single CopyEngine (CE) comprises two "rings": 41 * a source ring 42 * a destination ring 43 * 44 * Each ring consists of a number of descriptors which specify 45 * an address, length, and meta-data. 46 * 47 * Typically, one side of the PCIe interconnect (Host or Target) 48 * controls one ring and the other side controls the other ring. 49 * The source side chooses when to initiate a transfer and it 50 * chooses what to send (buffer address, length). The destination 51 * side keeps a supply of "anonymous receive buffers" available and 52 * it handles incoming data as it arrives (when the destination 53 * receives an interrupt). 54 * 55 * The sender may send a simple buffer (address/length) or it may 56 * send a small list of buffers. When a small list is sent, hardware 57 * "gathers" these and they end up in a single destination buffer 58 * with a single interrupt. 59 * 60 * There are several "contexts" managed by this layer -- more, it 61 * may seem -- than should be needed. These are provided mainly for 62 * maximum flexibility and especially to facilitate a simpler HIF 63 * implementation. There are per-CopyEngine recv, send, and watermark 64 * contexts. These are supplied by the caller when a recv, send, 65 * or watermark handler is established and they are echoed back to 66 * the caller when the respective callbacks are invoked. There is 67 * also a per-transfer context supplied by the caller when a buffer 68 * (or sendlist) is sent and when a buffer is enqueued for recv. 69 * These per-transfer contexts are echoed back to the caller when 70 * the buffer is sent/received. 71 * Target TX harsh result toeplitz_hash_result 72 */ 73 74 #define CE_ADDR_COPY(desc, dma_addr) do {\ 75 (desc)->buffer_addr_lo = (uint32_t)((dma_addr) &\ 76 0xFFFFFFFF);\ 77 (desc)->buffer_addr_hi =\ 78 (uint32_t)(((dma_addr) >> 32) & 0xFF);\ 79 } while (0) 80 hif_display_ctrl_traffic_pipes_state(struct hif_opaque_softc * hif_ctx)81 void hif_display_ctrl_traffic_pipes_state(struct hif_opaque_softc *hif_ctx) 82 { 83 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 84 struct CE_state *CE_state; 85 uint32_t hp = 0, tp = 0; 86 87 CE_state = scn->ce_id_to_state[2]; 88 hal_get_sw_hptp(scn->hal_soc, 89 CE_state->status_ring->srng_ctx, 90 &tp, &hp); 91 hif_info_high("CE-2 Dest status ring current snapshot HP:%u TP:%u", 92 hp, tp); 93 94 hp = 0; 95 tp = 0; 96 CE_state = scn->ce_id_to_state[3]; 97 hal_get_sw_hptp(scn->hal_soc, CE_state->src_ring->srng_ctx, &tp, &hp); 98 hif_info_high("CE-3 Source ring current snapshot HP:%u TP:%u", hp, tp); 99 } 100 101 #if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF) hif_record_ce_srng_desc_event(struct hif_softc * scn,int ce_id,enum hif_ce_event_type type,union ce_srng_desc * descriptor,void * memory,int index,int len,void * hal_ring)102 void hif_record_ce_srng_desc_event(struct hif_softc *scn, int ce_id, 103 enum hif_ce_event_type type, 104 union ce_srng_desc *descriptor, 105 void *memory, int index, 106 int len, void *hal_ring) 107 { 108 int record_index; 109 struct hif_ce_desc_event *event; 110 struct ce_desc_hist *ce_hist = &scn->hif_ce_desc_hist; 111 struct hif_ce_desc_event *hist_ev = NULL; 112 113 if (ce_id < CE_COUNT_MAX) 114 hist_ev = (struct hif_ce_desc_event *)ce_hist->hist_ev[ce_id]; 115 else 116 return; 117 118 if (ce_id >= CE_COUNT_MAX) 119 return; 120 121 if (!ce_hist->enable[ce_id]) 122 return; 123 124 if (!hist_ev) 125 return; 126 127 record_index = get_next_record_index( 128 &ce_hist->history_index[ce_id], HIF_CE_HISTORY_MAX); 129 130 event = &hist_ev[record_index]; 131 132 hif_clear_ce_desc_debug_data(event); 133 134 event->type = type; 135 event->time = qdf_get_log_timestamp(); 136 event->cpu_id = qdf_get_cpu(); 137 138 if (descriptor) 139 qdf_mem_copy(&event->descriptor, descriptor, 140 hal_get_entrysize_from_srng(hal_ring)); 141 142 if (hal_ring) 143 hal_get_sw_hptp(scn->hal_soc, hal_ring, &event->current_tp, 144 &event->current_hp); 145 146 event->memory = memory; 147 event->index = index; 148 149 if (event->type == HIF_CE_SRC_RING_BUFFER_POST) 150 hif_ce_desc_record_rx_paddr(scn, event, memory); 151 152 if (ce_hist->data_enable[ce_id]) 153 hif_ce_desc_data_record(event, len); 154 155 hif_record_latest_evt(ce_hist, type, ce_id, event->time, 156 event->current_hp, event->current_tp); 157 } 158 #endif /* HIF_CONFIG_SLUB_DEBUG_ON || HIF_CE_DEBUG_DATA_BUF */ 159 160 static QDF_STATUS ce_send_nolock_srng(struct CE_handle * copyeng,void * per_transfer_context,qdf_dma_addr_t buffer,uint32_t nbytes,uint32_t transfer_id,uint32_t flags,uint32_t user_flags)161 ce_send_nolock_srng(struct CE_handle *copyeng, 162 void *per_transfer_context, 163 qdf_dma_addr_t buffer, 164 uint32_t nbytes, 165 uint32_t transfer_id, 166 uint32_t flags, 167 uint32_t user_flags) 168 { 169 QDF_STATUS status; 170 struct CE_state *CE_state = (struct CE_state *)copyeng; 171 struct CE_ring_state *src_ring = CE_state->src_ring; 172 unsigned int nentries_mask = src_ring->nentries_mask; 173 unsigned int write_index = src_ring->write_index; 174 uint64_t dma_addr = buffer; 175 struct hif_softc *scn = CE_state->scn; 176 177 if (Q_TARGET_ACCESS_BEGIN(scn) < 0) 178 return QDF_STATUS_E_FAILURE; 179 if (unlikely(hal_srng_src_num_avail(scn->hal_soc, src_ring->srng_ctx, 180 false) <= 0)) { 181 OL_ATH_CE_PKT_ERROR_COUNT_INCR(scn, CE_RING_DELTA_FAIL); 182 Q_TARGET_ACCESS_END(scn); 183 return QDF_STATUS_E_FAILURE; 184 } 185 { 186 enum hif_ce_event_type event_type = HIF_CE_SRC_RING_BUFFER_POST; 187 struct ce_srng_src_desc *src_desc; 188 189 if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx)) { 190 Q_TARGET_ACCESS_END(scn); 191 return QDF_STATUS_E_FAILURE; 192 } 193 194 src_desc = hal_srng_src_get_next_reaped(scn->hal_soc, 195 src_ring->srng_ctx); 196 if (!src_desc) { 197 Q_TARGET_ACCESS_END(scn); 198 return QDF_STATUS_E_INVAL; 199 } 200 201 /* Update low 32 bits source descriptor address */ 202 src_desc->buffer_addr_lo = 203 (uint32_t)(dma_addr & 0xFFFFFFFF); 204 src_desc->buffer_addr_hi = 205 (uint32_t)((dma_addr >> 32) & 0xFF); 206 207 src_desc->meta_data = transfer_id; 208 209 /* 210 * Set the swap bit if: 211 * typical sends on this CE are swapped (host is big-endian) 212 * and this send doesn't disable the swapping 213 * (data is not bytestream) 214 */ 215 src_desc->byte_swap = 216 (((CE_state->attr_flags & CE_ATTR_BYTE_SWAP_DATA) 217 != 0) & ((flags & CE_SEND_FLAG_SWAP_DISABLE) == 0)); 218 src_desc->gather = ((flags & CE_SEND_FLAG_GATHER) != 0); 219 src_desc->nbytes = nbytes; 220 221 src_ring->per_transfer_context[write_index] = 222 per_transfer_context; 223 write_index = CE_RING_IDX_INCR(nentries_mask, write_index); 224 225 hal_srng_access_end(scn->hal_soc, src_ring->srng_ctx); 226 227 /* src_ring->write index hasn't been updated event though 228 * the register has already been written to. 229 */ 230 hif_record_ce_srng_desc_event(scn, CE_state->id, event_type, 231 (union ce_srng_desc *)src_desc, 232 per_transfer_context, 233 src_ring->write_index, nbytes, 234 src_ring->srng_ctx); 235 236 src_ring->write_index = write_index; 237 status = QDF_STATUS_SUCCESS; 238 } 239 Q_TARGET_ACCESS_END(scn); 240 return status; 241 } 242 243 static QDF_STATUS ce_sendlist_send_srng(struct CE_handle * copyeng,void * per_transfer_context,struct ce_sendlist * sendlist,unsigned int transfer_id)244 ce_sendlist_send_srng(struct CE_handle *copyeng, 245 void *per_transfer_context, 246 struct ce_sendlist *sendlist, unsigned int transfer_id) 247 { 248 QDF_STATUS status = QDF_STATUS_E_NOMEM; 249 struct ce_sendlist_s *sl = (struct ce_sendlist_s *)sendlist; 250 struct CE_state *CE_state = (struct CE_state *)copyeng; 251 struct CE_ring_state *src_ring = CE_state->src_ring; 252 unsigned int num_items = sl->num_items; 253 unsigned int sw_index; 254 unsigned int write_index; 255 struct hif_softc *scn = CE_state->scn; 256 257 QDF_ASSERT((num_items > 0) && (num_items < src_ring->nentries)); 258 259 qdf_spin_lock_bh(&CE_state->ce_index_lock); 260 sw_index = src_ring->sw_index; 261 write_index = src_ring->write_index; 262 263 if (hal_srng_src_num_avail(scn->hal_soc, src_ring->srng_ctx, false) >= 264 num_items) { 265 struct ce_sendlist_item *item; 266 int i; 267 268 /* handle all but the last item uniformly */ 269 for (i = 0; i < num_items - 1; i++) { 270 item = &sl->item[i]; 271 /* TBDXXX: Support extensible sendlist_types? */ 272 QDF_ASSERT(item->send_type == CE_SIMPLE_BUFFER_TYPE); 273 status = ce_send_nolock_srng(copyeng, 274 CE_SENDLIST_ITEM_CTXT, 275 (qdf_dma_addr_t) item->data, 276 item->u.nbytes, transfer_id, 277 item->flags | CE_SEND_FLAG_GATHER, 278 item->user_flags); 279 QDF_ASSERT(status == QDF_STATUS_SUCCESS); 280 } 281 /* provide valid context pointer for final item */ 282 item = &sl->item[i]; 283 /* TBDXXX: Support extensible sendlist_types? */ 284 QDF_ASSERT(item->send_type == CE_SIMPLE_BUFFER_TYPE); 285 status = ce_send_nolock_srng(copyeng, per_transfer_context, 286 (qdf_dma_addr_t) item->data, 287 item->u.nbytes, 288 transfer_id, item->flags, 289 item->user_flags); 290 QDF_ASSERT(status == QDF_STATUS_SUCCESS); 291 QDF_NBUF_UPDATE_TX_PKT_COUNT((qdf_nbuf_t)per_transfer_context, 292 QDF_NBUF_TX_PKT_CE); 293 DPTRACE(qdf_dp_trace((qdf_nbuf_t)per_transfer_context, 294 QDF_DP_TRACE_CE_PACKET_PTR_RECORD, 295 QDF_TRACE_DEFAULT_PDEV_ID, 296 (uint8_t *)(((qdf_nbuf_t)per_transfer_context)->data), 297 sizeof(((qdf_nbuf_t)per_transfer_context)->data), QDF_TX)); 298 } else { 299 /* 300 * Probably not worth the additional complexity to support 301 * partial sends with continuation or notification. We expect 302 * to use large rings and small sendlists. If we can't handle 303 * the entire request at once, punt it back to the caller. 304 */ 305 } 306 qdf_spin_unlock_bh(&CE_state->ce_index_lock); 307 308 return status; 309 } 310 311 #define SLOTS_PER_DATAPATH_TX 2 312 313 #ifndef AH_NEED_TX_DATA_SWAP 314 #define AH_NEED_TX_DATA_SWAP 0 315 #endif 316 /** 317 * ce_recv_buf_enqueue_srng() - enqueue a recv buffer into a copy engine 318 * @copyeng: copy engine handle 319 * @per_recv_context: virtual address of the nbuf 320 * @buffer: physical address of the nbuf 321 * 322 * Return: QDF_STATUS_SUCCESS if the buffer is enqueued 323 */ 324 static QDF_STATUS ce_recv_buf_enqueue_srng(struct CE_handle * copyeng,void * per_recv_context,qdf_dma_addr_t buffer)325 ce_recv_buf_enqueue_srng(struct CE_handle *copyeng, 326 void *per_recv_context, qdf_dma_addr_t buffer) 327 { 328 QDF_STATUS status; 329 struct CE_state *CE_state = (struct CE_state *)copyeng; 330 struct CE_ring_state *dest_ring = CE_state->dest_ring; 331 unsigned int nentries_mask = dest_ring->nentries_mask; 332 unsigned int write_index; 333 unsigned int sw_index; 334 uint64_t dma_addr = buffer; 335 struct hif_softc *scn = CE_state->scn; 336 struct ce_srng_dest_desc *dest_desc = NULL; 337 338 qdf_spin_lock_bh(&CE_state->ce_index_lock); 339 write_index = dest_ring->write_index; 340 sw_index = dest_ring->sw_index; 341 342 if (Q_TARGET_ACCESS_BEGIN(scn) < 0) { 343 qdf_spin_unlock_bh(&CE_state->ce_index_lock); 344 return QDF_STATUS_E_IO; 345 } 346 347 /* HP/TP update if any should happen only once per interrupt, 348 * therefore checking for CE receive_count. 349 */ 350 hal_srng_check_and_update_hptp(scn->hal_soc, dest_ring->srng_ctx, 351 !CE_state->receive_count); 352 353 if (hal_srng_access_start(scn->hal_soc, dest_ring->srng_ctx)) { 354 qdf_spin_unlock_bh(&CE_state->ce_index_lock); 355 return QDF_STATUS_E_FAILURE; 356 } 357 358 if ((hal_srng_src_num_avail(scn->hal_soc, 359 dest_ring->srng_ctx, false) > 0)) { 360 dest_desc = hal_srng_src_get_next(scn->hal_soc, 361 dest_ring->srng_ctx); 362 363 if (!dest_desc) { 364 status = QDF_STATUS_E_FAILURE; 365 } else { 366 367 CE_ADDR_COPY(dest_desc, dma_addr); 368 369 dest_ring->per_transfer_context[write_index] = 370 per_recv_context; 371 372 /* Update Destination Ring Write Index */ 373 write_index = CE_RING_IDX_INCR(nentries_mask, 374 write_index); 375 status = QDF_STATUS_SUCCESS; 376 } 377 } else { 378 dest_desc = NULL; 379 status = QDF_STATUS_E_FAILURE; 380 } 381 382 dest_ring->write_index = write_index; 383 hal_srng_access_end(scn->hal_soc, dest_ring->srng_ctx); 384 hif_record_ce_srng_desc_event(scn, CE_state->id, 385 HIF_CE_DEST_RING_BUFFER_POST, 386 (union ce_srng_desc *)dest_desc, 387 per_recv_context, 388 dest_ring->write_index, 0, 389 dest_ring->srng_ctx); 390 391 Q_TARGET_ACCESS_END(scn); 392 qdf_spin_unlock_bh(&CE_state->ce_index_lock); 393 return status; 394 } 395 396 /* 397 * Guts of ce_recv_entries_done. 398 * The caller takes responsibility for any necessary locking. 399 */ 400 static unsigned int ce_recv_entries_done_nolock_srng(struct hif_softc * scn,struct CE_state * CE_state)401 ce_recv_entries_done_nolock_srng(struct hif_softc *scn, 402 struct CE_state *CE_state) 403 { 404 struct CE_ring_state *status_ring = CE_state->status_ring; 405 406 return hal_srng_dst_num_valid(scn->hal_soc, 407 status_ring->srng_ctx, false); 408 } 409 410 /* 411 * Guts of ce_send_entries_done. 412 * The caller takes responsibility for any necessary locking. 413 */ 414 static unsigned int ce_send_entries_done_nolock_srng(struct hif_softc * scn,struct CE_state * CE_state)415 ce_send_entries_done_nolock_srng(struct hif_softc *scn, 416 struct CE_state *CE_state) 417 { 418 419 struct CE_ring_state *src_ring = CE_state->src_ring; 420 int count = 0; 421 422 if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx)) 423 return 0; 424 425 count = hal_srng_src_done_val(scn->hal_soc, src_ring->srng_ctx); 426 427 hal_srng_access_end_reap(scn->hal_soc, src_ring->srng_ctx); 428 429 return count; 430 } 431 432 /* 433 * Guts of ce_completed_recv_next. 434 * The caller takes responsibility for any necessary locking. 435 */ 436 static QDF_STATUS ce_completed_recv_next_nolock_srng(struct CE_state * CE_state,void ** per_CE_contextp,void ** per_transfer_contextp,qdf_dma_addr_t * bufferp,unsigned int * nbytesp,unsigned int * transfer_idp,unsigned int * flagsp)437 ce_completed_recv_next_nolock_srng(struct CE_state *CE_state, 438 void **per_CE_contextp, 439 void **per_transfer_contextp, 440 qdf_dma_addr_t *bufferp, 441 unsigned int *nbytesp, 442 unsigned int *transfer_idp, 443 unsigned int *flagsp) 444 { 445 QDF_STATUS status; 446 struct CE_ring_state *dest_ring = CE_state->dest_ring; 447 struct CE_ring_state *status_ring = CE_state->status_ring; 448 unsigned int nentries_mask = dest_ring->nentries_mask; 449 unsigned int sw_index = dest_ring->sw_index; 450 struct hif_softc *scn = CE_state->scn; 451 struct ce_srng_dest_status_desc *dest_status = NULL; 452 int nbytes; 453 struct ce_srng_dest_status_desc dest_status_info; 454 455 /* HP/TP update if any should happen only once per interrupt, 456 * therefore checking for CE receive_count. 457 */ 458 hal_srng_check_and_update_hptp(scn->hal_soc, status_ring->srng_ctx, 459 !CE_state->receive_count); 460 461 if (hal_srng_access_start(scn->hal_soc, status_ring->srng_ctx)) 462 return QDF_STATUS_E_FAILURE; 463 464 dest_status = hal_srng_dst_peek(scn->hal_soc, status_ring->srng_ctx); 465 if (!dest_status) { 466 hal_srng_access_end_reap(scn->hal_soc, status_ring->srng_ctx); 467 return QDF_STATUS_E_FAILURE; 468 } 469 470 /* 471 * By copying the dest_desc_info element to local memory, we could 472 * avoid extra memory read from non-cachable memory. 473 */ 474 dest_status_info = *dest_status; 475 nbytes = dest_status_info.nbytes; 476 if (nbytes == 0) { 477 uint32_t hp, tp; 478 479 /* 480 * This closes a relatively unusual race where the Host 481 * sees the updated DRRI before the update to the 482 * corresponding descriptor has completed. We treat this 483 * as a descriptor that is not yet done. 484 */ 485 hal_get_sw_hptp(scn->hal_soc, status_ring->srng_ctx, 486 &tp, &hp); 487 hif_info_rl("No data to reap, hp %d tp %d", hp, tp); 488 status = QDF_STATUS_E_FAILURE; 489 hal_srng_access_end_reap(scn->hal_soc, status_ring->srng_ctx); 490 goto done; 491 } 492 493 /* 494 * Move the tail pointer since nbytes is non-zero and 495 * this entry is processed. 496 */ 497 hal_srng_dst_get_next(scn->hal_soc, status_ring->srng_ctx); 498 499 dest_status->nbytes = 0; 500 501 *nbytesp = nbytes; 502 *transfer_idp = dest_status_info.meta_data; 503 *flagsp = (dest_status_info.byte_swap) ? CE_RECV_FLAG_SWAPPED : 0; 504 505 if (per_CE_contextp) 506 *per_CE_contextp = CE_state->recv_context; 507 508 /* NOTE: sw_index is more like a read_index in this context. It has a 509 * one-to-one mapping with status ring. 510 * Get the per trasnfer context from dest_ring. 511 */ 512 if (per_transfer_contextp) 513 *per_transfer_contextp = 514 dest_ring->per_transfer_context[sw_index]; 515 516 dest_ring->per_transfer_context[sw_index] = 0; /* sanity */ 517 518 /* Update sw_index */ 519 sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); 520 dest_ring->sw_index = sw_index; 521 status = QDF_STATUS_SUCCESS; 522 523 hal_srng_access_end(scn->hal_soc, status_ring->srng_ctx); 524 hif_record_ce_srng_desc_event(scn, CE_state->id, 525 HIF_CE_DEST_RING_BUFFER_REAP, 526 NULL, 527 dest_ring-> 528 per_transfer_context[sw_index], 529 dest_ring->sw_index, nbytes, 530 dest_ring->srng_ctx); 531 532 done: 533 hif_record_ce_srng_desc_event(scn, CE_state->id, 534 HIF_CE_DEST_STATUS_RING_REAP, 535 (union ce_srng_desc *)dest_status, 536 NULL, 537 -1, 0, 538 status_ring->srng_ctx); 539 540 return status; 541 } 542 543 static QDF_STATUS ce_revoke_recv_next_srng(struct CE_handle * copyeng,void ** per_CE_contextp,void ** per_transfer_contextp,qdf_dma_addr_t * bufferp)544 ce_revoke_recv_next_srng(struct CE_handle *copyeng, 545 void **per_CE_contextp, 546 void **per_transfer_contextp, qdf_dma_addr_t *bufferp) 547 { 548 struct CE_state *CE_state = (struct CE_state *)copyeng; 549 struct CE_ring_state *dest_ring = CE_state->dest_ring; 550 unsigned int sw_index; 551 552 if (!dest_ring) 553 return QDF_STATUS_E_FAILURE; 554 555 sw_index = dest_ring->sw_index; 556 557 if (per_CE_contextp) 558 *per_CE_contextp = CE_state->recv_context; 559 560 /* NOTE: sw_index is more like a read_index in this context. It has a 561 * one-to-one mapping with status ring. 562 * Get the per trasnfer context from dest_ring. 563 */ 564 if (per_transfer_contextp) 565 *per_transfer_contextp = 566 dest_ring->per_transfer_context[sw_index]; 567 568 if (!dest_ring->per_transfer_context[sw_index]) 569 return QDF_STATUS_E_FAILURE; 570 571 /* provide end condition */ 572 dest_ring->per_transfer_context[sw_index] = NULL; 573 574 /* Update sw_index */ 575 sw_index = CE_RING_IDX_INCR(dest_ring->nentries_mask, sw_index); 576 dest_ring->sw_index = sw_index; 577 return QDF_STATUS_SUCCESS; 578 } 579 580 /* 581 * Guts of ce_completed_send_next. 582 * The caller takes responsibility for any necessary locking. 583 */ 584 static QDF_STATUS ce_completed_send_next_nolock_srng(struct CE_state * CE_state,void ** per_CE_contextp,void ** per_transfer_contextp,qdf_dma_addr_t * bufferp,unsigned int * nbytesp,unsigned int * transfer_idp,unsigned int * sw_idx,unsigned int * hw_idx,uint32_t * toeplitz_hash_result)585 ce_completed_send_next_nolock_srng(struct CE_state *CE_state, 586 void **per_CE_contextp, 587 void **per_transfer_contextp, 588 qdf_dma_addr_t *bufferp, 589 unsigned int *nbytesp, 590 unsigned int *transfer_idp, 591 unsigned int *sw_idx, 592 unsigned int *hw_idx, 593 uint32_t *toeplitz_hash_result) 594 { 595 QDF_STATUS status = QDF_STATUS_E_FAILURE; 596 struct CE_ring_state *src_ring = CE_state->src_ring; 597 unsigned int nentries_mask = src_ring->nentries_mask; 598 unsigned int sw_index = src_ring->sw_index; 599 unsigned int swi = src_ring->sw_index; 600 struct hif_softc *scn = CE_state->scn; 601 struct ce_srng_src_desc *src_desc; 602 603 if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx)) { 604 status = QDF_STATUS_E_FAILURE; 605 return status; 606 } 607 608 src_desc = hal_srng_src_reap_next(scn->hal_soc, src_ring->srng_ctx); 609 if (src_desc) { 610 hif_record_ce_srng_desc_event(scn, CE_state->id, 611 HIF_TX_DESC_COMPLETION, 612 (union ce_srng_desc *)src_desc, 613 src_ring-> 614 per_transfer_context[swi], 615 swi, src_desc->nbytes, 616 src_ring->srng_ctx); 617 618 /* Return data from completed source descriptor */ 619 *bufferp = (qdf_dma_addr_t) 620 (((uint64_t)(src_desc)->buffer_addr_lo + 621 ((uint64_t)((src_desc)->buffer_addr_hi & 622 0xFF) << 32))); 623 *nbytesp = src_desc->nbytes; 624 *transfer_idp = src_desc->meta_data; 625 *toeplitz_hash_result = 0; /*src_desc->toeplitz_hash_result;*/ 626 627 if (per_CE_contextp) 628 *per_CE_contextp = CE_state->send_context; 629 630 /* sw_index is used more like read index */ 631 if (per_transfer_contextp) 632 *per_transfer_contextp = 633 src_ring->per_transfer_context[sw_index]; 634 635 src_ring->per_transfer_context[sw_index] = 0; /* sanity */ 636 637 /* Update sw_index */ 638 sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); 639 src_ring->sw_index = sw_index; 640 status = QDF_STATUS_SUCCESS; 641 } 642 hal_srng_access_end_reap(scn->hal_soc, src_ring->srng_ctx); 643 644 return status; 645 } 646 647 /* NB: Modelled after ce_completed_send_next */ 648 static QDF_STATUS ce_cancel_send_next_srng(struct CE_handle * copyeng,void ** per_CE_contextp,void ** per_transfer_contextp,qdf_dma_addr_t * bufferp,unsigned int * nbytesp,unsigned int * transfer_idp,uint32_t * toeplitz_hash_result)649 ce_cancel_send_next_srng(struct CE_handle *copyeng, 650 void **per_CE_contextp, 651 void **per_transfer_contextp, 652 qdf_dma_addr_t *bufferp, 653 unsigned int *nbytesp, 654 unsigned int *transfer_idp, 655 uint32_t *toeplitz_hash_result) 656 { 657 struct CE_state *CE_state; 658 QDF_STATUS status = QDF_STATUS_E_FAILURE; 659 struct CE_ring_state *src_ring; 660 unsigned int nentries_mask; 661 unsigned int sw_index; 662 struct hif_softc *scn; 663 struct ce_srng_src_desc *src_desc; 664 665 CE_state = (struct CE_state *)copyeng; 666 src_ring = CE_state->src_ring; 667 if (!src_ring) 668 return QDF_STATUS_E_FAILURE; 669 670 nentries_mask = src_ring->nentries_mask; 671 sw_index = src_ring->sw_index; 672 scn = CE_state->scn; 673 674 if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx)) { 675 status = QDF_STATUS_E_FAILURE; 676 return status; 677 } 678 679 src_desc = hal_srng_src_pending_reap_next(scn->hal_soc, 680 src_ring->srng_ctx); 681 if (src_desc) { 682 /* Return data from completed source descriptor */ 683 *bufferp = (qdf_dma_addr_t) 684 (((uint64_t)(src_desc)->buffer_addr_lo + 685 ((uint64_t)((src_desc)->buffer_addr_hi & 686 0xFF) << 32))); 687 *nbytesp = src_desc->nbytes; 688 *transfer_idp = src_desc->meta_data; 689 *toeplitz_hash_result = 0; /*src_desc->toeplitz_hash_result;*/ 690 691 if (per_CE_contextp) 692 *per_CE_contextp = CE_state->send_context; 693 694 /* sw_index is used more like read index */ 695 if (per_transfer_contextp) 696 *per_transfer_contextp = 697 src_ring->per_transfer_context[sw_index]; 698 699 src_ring->per_transfer_context[sw_index] = 0; /* sanity */ 700 701 /* Update sw_index */ 702 sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); 703 src_ring->sw_index = sw_index; 704 status = QDF_STATUS_SUCCESS; 705 } 706 hal_srng_access_end_reap(scn->hal_soc, src_ring->srng_ctx); 707 708 return status; 709 } 710 711 /* 712 * Adjust interrupts for the copy complete handler. 713 * If it's needed for either send or recv, then unmask 714 * this interrupt; otherwise, mask it. 715 * 716 * Called with target_lock held. 717 */ 718 static void ce_per_engine_handler_adjust_srng(struct CE_state * CE_state,int disable_copy_compl_intr)719 ce_per_engine_handler_adjust_srng(struct CE_state *CE_state, 720 int disable_copy_compl_intr) 721 { 722 } 723 ce_check_int_watermark_srng(struct CE_state * CE_state,unsigned int * flags)724 static bool ce_check_int_watermark_srng(struct CE_state *CE_state, 725 unsigned int *flags) 726 { 727 /*TODO*/ 728 return false; 729 } 730 ce_get_desc_size_srng(uint8_t ring_type)731 static uint32_t ce_get_desc_size_srng(uint8_t ring_type) 732 { 733 switch (ring_type) { 734 case CE_RING_SRC: 735 return sizeof(struct ce_srng_src_desc); 736 case CE_RING_DEST: 737 return sizeof(struct ce_srng_dest_desc); 738 case CE_RING_STATUS: 739 return sizeof(struct ce_srng_dest_status_desc); 740 default: 741 return 0; 742 } 743 return 0; 744 } 745 ce_srng_msi_ring_params_setup(struct hif_softc * scn,uint32_t ce_id,struct hal_srng_params * ring_params)746 static void ce_srng_msi_ring_params_setup(struct hif_softc *scn, uint32_t ce_id, 747 struct hal_srng_params *ring_params) 748 { 749 uint32_t addr_low; 750 uint32_t addr_high; 751 uint32_t msi_data_start; 752 uint32_t msi_data_count; 753 uint32_t msi_irq_start; 754 int ret; 755 int irq_id; 756 757 ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE", 758 &msi_data_count, &msi_data_start, 759 &msi_irq_start); 760 761 /* msi config not found */ 762 if (ret) 763 return; 764 765 irq_id = scn->int_assignment->msi_idx[ce_id]; 766 pld_get_msi_address(scn->qdf_dev->dev, &addr_low, &addr_high); 767 768 ring_params->msi_addr = addr_low; 769 ring_params->msi_addr |= (qdf_dma_addr_t)(((uint64_t)addr_high) << 32); 770 ring_params->msi_data = irq_id + msi_data_start; 771 ring_params->flags |= HAL_SRNG_MSI_INTR; 772 773 hif_debug("ce_id %d irq_id %d, msi_addr %pK, msi_data %d", ce_id, 774 irq_id, (void *)ring_params->msi_addr, ring_params->msi_data); 775 } 776 ce_srng_src_ring_setup(struct hif_softc * scn,uint32_t ce_id,struct CE_ring_state * src_ring,struct CE_attr * attr)777 static void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id, 778 struct CE_ring_state *src_ring, 779 struct CE_attr *attr) 780 { 781 struct hal_srng_params ring_params = {0}; 782 783 hif_debug("%s: ce_id %d", __func__, ce_id); 784 785 ring_params.ring_base_paddr = src_ring->base_addr_CE_space; 786 ring_params.ring_base_vaddr = src_ring->base_addr_owner_space; 787 ring_params.num_entries = src_ring->nentries; 788 /* 789 * The minimum increment for the timer is 8us 790 * A default value of 0 disables the timer 791 * A valid default value caused continuous interrupts to 792 * fire with MSI enabled. Need to revisit usage of the timer 793 */ 794 795 if (!(CE_ATTR_DISABLE_INTR & attr->flags)) { 796 ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params); 797 798 ring_params.intr_timer_thres_us = 0; 799 ring_params.intr_batch_cntr_thres_entries = 1; 800 ring_params.prefetch_timer = HAL_SRNG_PREFETCH_TIMER; 801 } 802 803 src_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_SRC, ce_id, 0, 804 &ring_params, 0); 805 } 806 807 #ifdef WLAN_WAR_CE_DISABLE_SRNG_TIMER_IRQ 808 static void ce_srng_initialize_dest_ring_thresh(struct CE_ring_state * dest_ring,struct hal_srng_params * ring_params)809 ce_srng_initialize_dest_ring_thresh(struct CE_ring_state *dest_ring, 810 struct hal_srng_params *ring_params) 811 { 812 ring_params->low_threshold = dest_ring->nentries >> 3; 813 ring_params->intr_timer_thres_us = 0; 814 ring_params->intr_batch_cntr_thres_entries = 1; 815 ring_params->flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE; 816 } 817 #else 818 static void ce_srng_initialize_dest_ring_thresh(struct CE_ring_state * dest_ring,struct hal_srng_params * ring_params)819 ce_srng_initialize_dest_ring_thresh(struct CE_ring_state *dest_ring, 820 struct hal_srng_params *ring_params) 821 { 822 ring_params->low_threshold = dest_ring->nentries >> 3; 823 ring_params->intr_timer_thres_us = 100000; 824 ring_params->intr_batch_cntr_thres_entries = 0; 825 ring_params->flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE; 826 } 827 #endif 828 829 #ifdef WLAN_DISABLE_STATUS_RING_TIMER_WAR ce_is_status_ring_timer_thresh_war_needed(void)830 static inline bool ce_is_status_ring_timer_thresh_war_needed(void) 831 { 832 return false; 833 } 834 #else ce_is_status_ring_timer_thresh_war_needed(void)835 static inline bool ce_is_status_ring_timer_thresh_war_needed(void) 836 { 837 return true; 838 } 839 #endif 840 841 /** 842 * ce_srng_initialize_dest_timer_interrupt_war() - war initialization 843 * @dest_ring: ring being initialized 844 * @ring_params: pointer to initialized parameters 845 * 846 * For Napier & Hawkeye v1, the status ring timer interrupts do not work 847 * As a workaround host configures the destination rings to be a proxy for 848 * work needing to be done. 849 * 850 * The interrupts are setup such that if the destination ring is less than fully 851 * posted, there is likely undone work for the status ring that the host should 852 * process. 853 * 854 * There is a timing bug in srng based copy engines such that a fully posted 855 * srng based copy engine has 2 empty entries instead of just one. The copy 856 * engine data structures work with 1 empty entry, but the software frequently 857 * fails to post the last entry due to the race condition. 858 */ ce_srng_initialize_dest_timer_interrupt_war(struct CE_ring_state * dest_ring,struct hal_srng_params * ring_params)859 static void ce_srng_initialize_dest_timer_interrupt_war( 860 struct CE_ring_state *dest_ring, 861 struct hal_srng_params *ring_params) 862 { 863 int num_buffers_when_fully_posted = dest_ring->nentries - 2; 864 865 ring_params->low_threshold = num_buffers_when_fully_posted - 1; 866 ring_params->intr_timer_thres_us = 1024; 867 ring_params->intr_batch_cntr_thres_entries = 0; 868 ring_params->flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE; 869 } 870 ce_srng_dest_ring_setup(struct hif_softc * scn,uint32_t ce_id,struct CE_ring_state * dest_ring,struct CE_attr * attr)871 static void ce_srng_dest_ring_setup(struct hif_softc *scn, 872 uint32_t ce_id, 873 struct CE_ring_state *dest_ring, 874 struct CE_attr *attr) 875 { 876 struct hal_srng_params ring_params = {0}; 877 878 hif_debug("ce_id: %d", ce_id); 879 880 ring_params.ring_base_paddr = dest_ring->base_addr_CE_space; 881 ring_params.ring_base_vaddr = dest_ring->base_addr_owner_space; 882 ring_params.num_entries = dest_ring->nentries; 883 ring_params.max_buffer_length = attr->src_sz_max; 884 885 if (!(CE_ATTR_DISABLE_INTR & attr->flags)) { 886 ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params); 887 if (ce_is_status_ring_timer_thresh_war_needed()) { 888 ce_srng_initialize_dest_timer_interrupt_war( 889 dest_ring, &ring_params); 890 } else { 891 /* normal behavior for future chips */ 892 ce_srng_initialize_dest_ring_thresh(dest_ring, 893 &ring_params); 894 } 895 ring_params.prefetch_timer = HAL_SRNG_PREFETCH_TIMER; 896 } 897 898 /*Dest ring is also source ring*/ 899 dest_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_DST, ce_id, 0, 900 &ring_params, 0); 901 } 902 903 #ifdef WLAN_CE_INTERRUPT_THRESHOLD_CONFIG 904 /** 905 * ce_status_ring_config_int_threshold() - configure ce status ring interrupt 906 * thresholds 907 * @scn: hif handle 908 * @ring_params: ce srng params 909 * 910 * Return: None 911 */ 912 static inline ce_status_ring_config_int_threshold(struct hif_softc * scn,struct hal_srng_params * ring_params)913 void ce_status_ring_config_int_threshold(struct hif_softc *scn, 914 struct hal_srng_params *ring_params) 915 { 916 ring_params->intr_timer_thres_us = 917 scn->ini_cfg.ce_status_ring_timer_threshold; 918 ring_params->intr_batch_cntr_thres_entries = 919 scn->ini_cfg.ce_status_ring_batch_count_threshold; 920 } 921 #else 922 static inline ce_status_ring_config_int_threshold(struct hif_softc * scn,struct hal_srng_params * ring_params)923 void ce_status_ring_config_int_threshold(struct hif_softc *scn, 924 struct hal_srng_params *ring_params) 925 { 926 ring_params->intr_timer_thres_us = 0x1000; 927 ring_params->intr_batch_cntr_thres_entries = 0x1; 928 } 929 #endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */ 930 ce_srng_status_ring_setup(struct hif_softc * scn,uint32_t ce_id,struct CE_ring_state * status_ring,struct CE_attr * attr)931 static void ce_srng_status_ring_setup(struct hif_softc *scn, uint32_t ce_id, 932 struct CE_ring_state *status_ring, 933 struct CE_attr *attr) 934 { 935 struct hal_srng_params ring_params = {0}; 936 937 hif_debug("ce_id: %d", ce_id); 938 939 ring_params.ring_base_paddr = status_ring->base_addr_CE_space; 940 ring_params.ring_base_vaddr = status_ring->base_addr_owner_space; 941 ring_params.num_entries = status_ring->nentries; 942 943 if (!(CE_ATTR_DISABLE_INTR & attr->flags)) { 944 ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params); 945 ce_status_ring_config_int_threshold(scn, &ring_params); 946 } 947 948 status_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_DST_STATUS, 949 ce_id, 0, &ring_params, 0); 950 } 951 ce_ring_setup_srng(struct hif_softc * scn,uint8_t ring_type,uint32_t ce_id,struct CE_ring_state * ring,struct CE_attr * attr)952 static int ce_ring_setup_srng(struct hif_softc *scn, uint8_t ring_type, 953 uint32_t ce_id, struct CE_ring_state *ring, 954 struct CE_attr *attr) 955 { 956 switch (ring_type) { 957 case CE_RING_SRC: 958 ce_srng_src_ring_setup(scn, ce_id, ring, attr); 959 break; 960 case CE_RING_DEST: 961 ce_srng_dest_ring_setup(scn, ce_id, ring, attr); 962 break; 963 case CE_RING_STATUS: 964 ce_srng_status_ring_setup(scn, ce_id, ring, attr); 965 break; 966 default: 967 qdf_assert(0); 968 break; 969 } 970 971 return 0; 972 } 973 ce_ring_cleanup_srng(struct hif_softc * scn,struct CE_state * CE_state,uint8_t ring_type)974 static void ce_ring_cleanup_srng(struct hif_softc *scn, 975 struct CE_state *CE_state, 976 uint8_t ring_type) 977 { 978 hal_ring_handle_t hal_srng = NULL; 979 980 switch (ring_type) { 981 case CE_RING_SRC: 982 hal_srng = (hal_ring_handle_t)CE_state->src_ring->srng_ctx; 983 break; 984 case CE_RING_DEST: 985 hal_srng = (hal_ring_handle_t)CE_state->dest_ring->srng_ctx; 986 break; 987 case CE_RING_STATUS: 988 hal_srng = (hal_ring_handle_t)CE_state->status_ring->srng_ctx; 989 break; 990 } 991 992 if (hal_srng) 993 hal_srng_cleanup(scn->hal_soc, hal_srng, 0); 994 } 995 ce_construct_shadow_config_srng(struct hif_softc * scn)996 static void ce_construct_shadow_config_srng(struct hif_softc *scn) 997 { 998 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); 999 int ce_id; 1000 1001 for (ce_id = 0; ce_id < scn->ce_count; ce_id++) { 1002 if (hif_state->host_ce_config[ce_id].src_nentries) 1003 hal_set_one_shadow_config(scn->hal_soc, 1004 CE_SRC, ce_id); 1005 1006 if (hif_state->host_ce_config[ce_id].dest_nentries) { 1007 hal_set_one_shadow_config(scn->hal_soc, 1008 CE_DST, ce_id); 1009 1010 hal_set_one_shadow_config(scn->hal_soc, 1011 CE_DST_STATUS, ce_id); 1012 } 1013 } 1014 } 1015 ce_prepare_shadow_register_v2_cfg_srng(struct hif_softc * scn,struct pld_shadow_reg_v2_cfg ** shadow_config,int * num_shadow_registers_configured)1016 static void ce_prepare_shadow_register_v2_cfg_srng(struct hif_softc *scn, 1017 struct pld_shadow_reg_v2_cfg **shadow_config, 1018 int *num_shadow_registers_configured) 1019 { 1020 if (!scn->hal_soc) { 1021 hif_err("hal not initialized: not initializing shadow config"); 1022 return; 1023 } 1024 1025 hal_get_shadow_config(scn->hal_soc, shadow_config, 1026 num_shadow_registers_configured); 1027 1028 if (*num_shadow_registers_configured != 0) { 1029 hif_err("hal shadow register configuration already constructed"); 1030 1031 /* return with original configuration*/ 1032 return; 1033 } 1034 hal_construct_srng_shadow_regs(scn->hal_soc); 1035 ce_construct_shadow_config_srng(scn); 1036 hal_set_shadow_regs(scn->hal_soc); 1037 hal_construct_shadow_regs(scn->hal_soc); 1038 /* get updated configuration */ 1039 hal_get_shadow_config(scn->hal_soc, shadow_config, 1040 num_shadow_registers_configured); 1041 } 1042 1043 #ifdef CONFIG_SHADOW_V3 ce_prepare_shadow_register_v3_cfg_srng(struct hif_softc * scn,struct pld_shadow_reg_v3_cfg ** shadow_config,int * num_shadow_registers_configured)1044 static void ce_prepare_shadow_register_v3_cfg_srng(struct hif_softc *scn, 1045 struct pld_shadow_reg_v3_cfg **shadow_config, 1046 int *num_shadow_registers_configured) 1047 { 1048 if (!scn->hal_soc) { 1049 hif_err("hal not initialized: not initializing shadow config"); 1050 return; 1051 } 1052 1053 hal_get_shadow_v3_config(scn->hal_soc, shadow_config, 1054 num_shadow_registers_configured); 1055 1056 if (*num_shadow_registers_configured != 0) { 1057 hif_err("hal shadow register configuration already constructed"); 1058 1059 /* return with original configuration*/ 1060 return; 1061 } 1062 hal_construct_srng_shadow_regs(scn->hal_soc); 1063 ce_construct_shadow_config_srng(scn); 1064 hal_set_shadow_regs(scn->hal_soc); 1065 hal_construct_shadow_regs(scn->hal_soc); 1066 /* get updated configuration */ 1067 hal_get_shadow_v3_config(scn->hal_soc, shadow_config, 1068 num_shadow_registers_configured); 1069 } 1070 #endif 1071 1072 #ifdef HIF_CE_LOG_INFO 1073 /** 1074 * ce_get_index_info_srng(): Get CE index info 1075 * @scn: HIF Context 1076 * @ce_state: CE opaque handle 1077 * @info: CE info 1078 * 1079 * Return: 0 for success and non zero for failure 1080 */ 1081 static ce_get_index_info_srng(struct hif_softc * scn,void * ce_state,struct ce_index * info)1082 int ce_get_index_info_srng(struct hif_softc *scn, void *ce_state, 1083 struct ce_index *info) 1084 { 1085 struct CE_state *CE_state = (struct CE_state *)ce_state; 1086 uint32_t tp, hp; 1087 1088 info->id = CE_state->id; 1089 if (CE_state->src_ring) { 1090 hal_get_sw_hptp(scn->hal_soc, CE_state->src_ring->srng_ctx, 1091 &tp, &hp); 1092 info->u.srng_info.tp = tp; 1093 info->u.srng_info.hp = hp; 1094 } else if (CE_state->dest_ring && CE_state->status_ring) { 1095 hal_get_sw_hptp(scn->hal_soc, CE_state->status_ring->srng_ctx, 1096 &tp, &hp); 1097 info->u.srng_info.status_tp = tp; 1098 info->u.srng_info.status_hp = hp; 1099 hal_get_sw_hptp(scn->hal_soc, CE_state->dest_ring->srng_ctx, 1100 &tp, &hp); 1101 info->u.srng_info.tp = tp; 1102 info->u.srng_info.hp = hp; 1103 } 1104 1105 return 0; 1106 } 1107 #endif 1108 1109 #ifdef FEATURE_DIRECT_LINK 1110 /** 1111 * ce_set_srng_msi_irq_config_by_ceid(): Set srng MSI irq configuration for CE 1112 * given by id 1113 * @scn: HIF Context 1114 * @ce_id: 1115 * @addr: 1116 * @data: 1117 * 1118 * Return: 0 for success and non zero for failure 1119 */ 1120 static QDF_STATUS ce_set_srng_msi_irq_config_by_ceid(struct hif_softc * scn,uint8_t ce_id,uint64_t addr,uint32_t data)1121 ce_set_srng_msi_irq_config_by_ceid(struct hif_softc *scn, uint8_t ce_id, 1122 uint64_t addr, uint32_t data) 1123 { 1124 struct CE_state *ce_state; 1125 hal_ring_handle_t ring_hdl; 1126 struct hal_srng_params ring_params = {0}; 1127 1128 ce_state = scn->ce_id_to_state[ce_id]; 1129 if (!ce_state) 1130 return QDF_STATUS_E_NOSUPPORT; 1131 1132 ring_params.msi_addr = addr; 1133 ring_params.msi_data = data; 1134 1135 if (ce_state->src_ring) { 1136 ring_hdl = ce_state->src_ring->srng_ctx; 1137 1138 ring_params.intr_timer_thres_us = 0; 1139 ring_params.intr_batch_cntr_thres_entries = 1; 1140 ring_params.prefetch_timer = HAL_SRNG_PREFETCH_TIMER; 1141 } else if (ce_state->dest_ring) { 1142 ring_hdl = ce_state->status_ring->srng_ctx; 1143 1144 ce_status_ring_config_int_threshold(scn, &ring_params); 1145 1146 hal_srng_set_msi_irq_config(scn->hal_soc, ring_hdl, 1147 &ring_params); 1148 1149 if (ce_is_status_ring_timer_thresh_war_needed()) { 1150 ce_srng_initialize_dest_timer_interrupt_war( 1151 ce_state->dest_ring, &ring_params); 1152 } else { 1153 ce_srng_initialize_dest_ring_thresh(ce_state->dest_ring, 1154 &ring_params); 1155 } 1156 ring_params.prefetch_timer = HAL_SRNG_PREFETCH_TIMER; 1157 ring_hdl = ce_state->dest_ring->srng_ctx; 1158 } else { 1159 return QDF_STATUS_E_FAILURE; 1160 } 1161 1162 hal_srng_set_msi_irq_config(scn->hal_soc, ring_hdl, &ring_params); 1163 1164 return QDF_STATUS_SUCCESS; 1165 } 1166 1167 static ce_get_direct_link_dest_srng_buffers(struct hif_softc * scn,uint64_t ** dma_addr,uint32_t * buf_size)1168 uint16_t ce_get_direct_link_dest_srng_buffers(struct hif_softc *scn, 1169 uint64_t **dma_addr, 1170 uint32_t *buf_size) 1171 { 1172 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); 1173 struct CE_state *ce_state; 1174 struct service_to_pipe *tgt_svc_cfg; 1175 uint64_t *dma_addr_arr = NULL; 1176 uint32_t i; 1177 uint32_t j = 0; 1178 1179 tgt_svc_cfg = hif_state->tgt_svc_map; 1180 1181 for (i = 0; i < hif_state->sz_tgt_svc_map; i++) { 1182 if (tgt_svc_cfg[i].service_id != LPASS_DATA_MSG_SVC || 1183 tgt_svc_cfg[i].pipedir != PIPEDIR_IN) 1184 continue; 1185 1186 ce_state = scn->ce_id_to_state[tgt_svc_cfg[i].pipenum]; 1187 if (!ce_state || !ce_state->dest_ring) { 1188 hif_err("Direct Link CE pipe %d not initialized", 1189 tgt_svc_cfg[i].pipenum); 1190 return QDF_STATUS_E_FAILURE; 1191 } 1192 1193 QDF_ASSERT(scn->dl_recv_pages.dma_pages); 1194 1195 dma_addr_arr = qdf_mem_malloc(sizeof(*dma_addr_arr) * 1196 scn->dl_recv_pages.num_pages); 1197 if (!dma_addr_arr) 1198 return 0; 1199 1200 for (j = 0; j < scn->dl_recv_pages.num_pages; j++) 1201 dma_addr_arr[j] = 1202 scn->dl_recv_pages.dma_pages[j].page_p_addr; 1203 1204 *buf_size = ce_state->src_sz_max; 1205 1206 break; 1207 } 1208 1209 *dma_addr = dma_addr_arr; 1210 1211 return j; 1212 } 1213 1214 /** 1215 * ce_save_srng_info() - Get and save srng information 1216 * @hif_ctx: hif context 1217 * @srng_info: Direct Link CE srng information 1218 * @srng_ctx: Direct Link CE srng context 1219 * 1220 * Return: QDF status 1221 */ 1222 static void ce_save_srng_info(struct hif_softc * hif_ctx,struct hif_ce_ring_info * srng_info,void * srng_ctx)1223 ce_save_srng_info(struct hif_softc *hif_ctx, struct hif_ce_ring_info *srng_info, 1224 void *srng_ctx) 1225 { 1226 struct hal_srng_params params; 1227 1228 hal_get_srng_params(hif_ctx->hal_soc, srng_ctx, ¶ms); 1229 1230 srng_info->ring_id = params.ring_id; 1231 srng_info->ring_dir = params.ring_dir; 1232 srng_info->num_entries = params.num_entries; 1233 srng_info->entry_size = params.entry_size; 1234 srng_info->ring_base_paddr = params.ring_base_paddr; 1235 srng_info->hp_paddr = 1236 hal_srng_get_hp_addr(hif_ctx->hal_soc, srng_ctx); 1237 srng_info->tp_paddr = 1238 hal_srng_get_tp_addr(hif_ctx->hal_soc, srng_ctx); 1239 } 1240 1241 static ce_get_direct_link_srng_info(struct hif_softc * scn,struct hif_direct_link_ce_info * info,uint8_t max_ce_info_len)1242 QDF_STATUS ce_get_direct_link_srng_info(struct hif_softc *scn, 1243 struct hif_direct_link_ce_info *info, 1244 uint8_t max_ce_info_len) 1245 { 1246 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); 1247 struct CE_state *ce_state; 1248 struct service_to_pipe *tgt_svc_cfg; 1249 uint8_t ce_info_idx = 0; 1250 uint32_t i; 1251 1252 tgt_svc_cfg = hif_state->tgt_svc_map; 1253 1254 for (i = 0; i < hif_state->sz_tgt_svc_map; i++) { 1255 if (tgt_svc_cfg[i].service_id != LPASS_DATA_MSG_SVC) 1256 continue; 1257 1258 ce_state = scn->ce_id_to_state[tgt_svc_cfg[i].pipenum]; 1259 if (!ce_state) { 1260 hif_err("Direct Link CE pipe %d not initialized", 1261 tgt_svc_cfg[i].pipenum); 1262 return QDF_STATUS_E_FAILURE; 1263 } 1264 1265 if (ce_info_idx > max_ce_info_len) 1266 return QDF_STATUS_E_FAILURE; 1267 1268 info[ce_info_idx].ce_id = ce_state->id; 1269 info[ce_info_idx].pipe_dir = tgt_svc_cfg[i].pipedir; 1270 1271 if (ce_state->src_ring) 1272 ce_save_srng_info(scn, &info[ce_info_idx].ring_info, 1273 ce_state->src_ring->srng_ctx); 1274 else 1275 ce_save_srng_info(scn, &info[ce_info_idx].ring_info, 1276 ce_state->dest_ring->srng_ctx); 1277 1278 ce_info_idx++; 1279 1280 if (!ce_state->status_ring) 1281 continue; 1282 1283 if (ce_info_idx > max_ce_info_len) 1284 return QDF_STATUS_E_FAILURE; 1285 1286 info[ce_info_idx].ce_id = ce_state->id; 1287 info[ce_info_idx].pipe_dir = tgt_svc_cfg[i].pipedir; 1288 1289 ce_save_srng_info(scn, &info[ce_info_idx].ring_info, 1290 ce_state->status_ring->srng_ctx); 1291 ce_info_idx++; 1292 } 1293 1294 return QDF_STATUS_SUCCESS; 1295 } 1296 #endif 1297 1298 static struct ce_ops ce_service_srng = { 1299 .ce_get_desc_size = ce_get_desc_size_srng, 1300 .ce_ring_setup = ce_ring_setup_srng, 1301 .ce_srng_cleanup = ce_ring_cleanup_srng, 1302 .ce_sendlist_send = ce_sendlist_send_srng, 1303 .ce_completed_recv_next_nolock = ce_completed_recv_next_nolock_srng, 1304 .ce_revoke_recv_next = ce_revoke_recv_next_srng, 1305 .ce_cancel_send_next = ce_cancel_send_next_srng, 1306 .ce_recv_buf_enqueue = ce_recv_buf_enqueue_srng, 1307 .ce_per_engine_handler_adjust = ce_per_engine_handler_adjust_srng, 1308 .ce_send_nolock = ce_send_nolock_srng, 1309 .watermark_int = ce_check_int_watermark_srng, 1310 .ce_completed_send_next_nolock = ce_completed_send_next_nolock_srng, 1311 .ce_recv_entries_done_nolock = ce_recv_entries_done_nolock_srng, 1312 .ce_send_entries_done_nolock = ce_send_entries_done_nolock_srng, 1313 .ce_prepare_shadow_register_v2_cfg = 1314 ce_prepare_shadow_register_v2_cfg_srng, 1315 #ifdef CONFIG_SHADOW_V3 1316 .ce_prepare_shadow_register_v3_cfg = 1317 ce_prepare_shadow_register_v3_cfg_srng, 1318 #endif 1319 #ifdef HIF_CE_LOG_INFO 1320 .ce_get_index_info = 1321 ce_get_index_info_srng, 1322 #endif 1323 #ifdef FEATURE_DIRECT_LINK 1324 .ce_set_irq_config_by_ceid = ce_set_srng_msi_irq_config_by_ceid, 1325 .ce_get_direct_link_dest_buffers = ce_get_direct_link_dest_srng_buffers, 1326 .ce_get_direct_link_ring_info = ce_get_direct_link_srng_info, 1327 #endif 1328 }; 1329 ce_services_srng(void)1330 struct ce_ops *ce_services_srng(void) 1331 { 1332 return &ce_service_srng; 1333 } 1334 qdf_export_symbol(ce_services_srng); 1335 ce_service_srng_init(void)1336 void ce_service_srng_init(void) 1337 { 1338 ce_service_register_module(CE_SVC_SRNG, &ce_services_srng); 1339 } 1340