1 /* 2 * BSD LICENSE 3 * 4 * Copyright(c) 2017 Cavium, Inc.. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Cavium, Inc. nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /*$FreeBSD$*/ 34 35 #include "lio_bsd.h" 36 #include "lio_common.h" 37 #include "lio_droq.h" 38 #include "lio_iq.h" 39 #include "lio_response_manager.h" 40 #include "lio_device.h" 41 #include "lio_main.h" 42 #include "cn23xx_pf_device.h" 43 #include "lio_network.h" 44 45 struct __dispatch { 46 struct lio_stailq_node node; 47 struct lio_recv_info *rinfo; 48 lio_dispatch_fn_t disp_fn; 49 }; 50 51 void *lio_get_dispatch_arg(struct octeon_device *oct, 52 uint16_t opcode, uint16_t subcode); 53 54 /* 55 * Get the argument that the user set when registering dispatch 56 * function for a given opcode/subcode. 57 * @param octeon_dev - the octeon device pointer. 58 * @param opcode - the opcode for which the dispatch argument 59 * is to be checked. 60 * @param subcode - the subcode for which the dispatch argument 61 * is to be checked. 62 * @return Success: void * (argument to the dispatch function) 63 * @return Failure: NULL 64 * 65 */ 66 void * 67 lio_get_dispatch_arg(struct octeon_device *octeon_dev, 68 uint16_t opcode, uint16_t subcode) 69 { 70 struct lio_stailq_node *dispatch; 71 void *fn_arg = NULL; 72 int idx; 73 uint16_t combined_opcode; 74 75 combined_opcode = LIO_OPCODE_SUBCODE(opcode, subcode); 76 77 idx = combined_opcode & LIO_OPCODE_MASK; 78 79 mtx_lock(&octeon_dev->dispatch.lock); 80 81 if (octeon_dev->dispatch.count == 0) { 82 mtx_unlock(&octeon_dev->dispatch.lock); 83 return (NULL); 84 } 85 86 if (octeon_dev->dispatch.dlist[idx].opcode == combined_opcode) { 87 fn_arg = octeon_dev->dispatch.dlist[idx].arg; 88 } else { 89 STAILQ_FOREACH(dispatch, 90 &octeon_dev->dispatch.dlist[idx].head, entries) { 91 if (((struct lio_dispatch *)dispatch)->opcode == 92 combined_opcode) { 93 fn_arg = ((struct lio_dispatch *)dispatch)->arg; 94 break; 95 } 96 } 97 } 98 99 mtx_unlock(&octeon_dev->dispatch.lock); 100 return (fn_arg); 101 } 102 103 /* 104 * Check for packets on Droq. This function should be called with lock held. 105 * @param droq - Droq on which count is checked. 106 * @return Returns packet count. 107 */ 108 uint32_t 109 lio_droq_check_hw_for_pkts(struct lio_droq *droq) 110 { 111 struct octeon_device *oct = droq->oct_dev; 112 uint32_t last_count; 113 uint32_t pkt_count = 0; 114 115 pkt_count = lio_read_csr32(oct, droq->pkts_sent_reg); 116 117 last_count = pkt_count - droq->pkt_count; 118 droq->pkt_count = pkt_count; 119 120 /* we shall write to cnts at the end of processing */ 121 if (last_count) 122 atomic_add_int(&droq->pkts_pending, last_count); 123 124 return (last_count); 125 } 126 127 static void 128 lio_droq_compute_max_packet_bufs(struct lio_droq *droq) 129 { 130 uint32_t count = 0; 131 132 /* 133 * max_empty_descs is the max. no. of descs that can have no buffers. 134 * If the empty desc count goes beyond this value, we cannot safely 135 * read in a 64K packet sent by Octeon 136 * (64K is max pkt size from Octeon) 137 */ 138 droq->max_empty_descs = 0; 139 140 do { 141 droq->max_empty_descs++; 142 count += droq->buffer_size; 143 } while (count < (64 * 1024)); 144 145 droq->max_empty_descs = droq->max_count - droq->max_empty_descs; 146 } 147 148 static void 149 lio_droq_reset_indices(struct lio_droq *droq) 150 { 151 152 droq->read_idx = 0; 153 droq->refill_idx = 0; 154 droq->refill_count = 0; 155 atomic_store_rel_int(&droq->pkts_pending, 0); 156 } 157 158 static void 159 lio_droq_destroy_ring_buffers(struct octeon_device *oct, 160 struct lio_droq *droq) 161 { 162 uint32_t i; 163 164 for (i = 0; i < droq->max_count; i++) { 165 if (droq->recv_buf_list[i].buffer != NULL) { 166 lio_recv_buffer_free(droq->recv_buf_list[i].buffer); 167 droq->recv_buf_list[i].buffer = NULL; 168 } 169 } 170 171 lio_droq_reset_indices(droq); 172 } 173 174 static int 175 lio_droq_setup_ring_buffers(struct octeon_device *oct, 176 struct lio_droq *droq) 177 { 178 struct lio_droq_desc *desc_ring = droq->desc_ring; 179 void *buf; 180 uint32_t i; 181 182 for (i = 0; i < droq->max_count; i++) { 183 buf = lio_recv_buffer_alloc(droq->buffer_size); 184 185 if (buf == NULL) { 186 lio_dev_err(oct, "%s buffer alloc failed\n", 187 __func__); 188 droq->stats.rx_alloc_failure++; 189 return (-ENOMEM); 190 } 191 192 droq->recv_buf_list[i].buffer = buf; 193 droq->recv_buf_list[i].data = ((struct mbuf *)buf)->m_data; 194 desc_ring[i].info_ptr = 0; 195 desc_ring[i].buffer_ptr = 196 lio_map_ring(oct->device, droq->recv_buf_list[i].buffer, 197 droq->buffer_size); 198 } 199 200 lio_droq_reset_indices(droq); 201 202 lio_droq_compute_max_packet_bufs(droq); 203 204 return (0); 205 } 206 207 int 208 lio_delete_droq(struct octeon_device *oct, uint32_t q_no) 209 { 210 struct lio_droq *droq = oct->droq[q_no]; 211 212 lio_dev_dbg(oct, "%s[%d]\n", __func__, q_no); 213 214 while (taskqueue_cancel(droq->droq_taskqueue, &droq->droq_task, NULL)) 215 taskqueue_drain(droq->droq_taskqueue, &droq->droq_task); 216 217 taskqueue_free(droq->droq_taskqueue); 218 droq->droq_taskqueue = NULL; 219 220 lio_droq_destroy_ring_buffers(oct, droq); 221 free(droq->recv_buf_list, M_DEVBUF); 222 223 if (droq->desc_ring != NULL) 224 lio_dma_free((droq->max_count * LIO_DROQ_DESC_SIZE), 225 droq->desc_ring); 226 227 oct->io_qmask.oq &= ~(1ULL << q_no); 228 bzero(oct->droq[q_no], sizeof(struct lio_droq)); 229 oct->num_oqs--; 230 231 return (0); 232 } 233 234 void 235 lio_droq_bh(void *ptr, int pending __unused) 236 { 237 struct lio_droq *droq = ptr; 238 struct octeon_device *oct = droq->oct_dev; 239 struct lio_instr_queue *iq = oct->instr_queue[droq->q_no]; 240 int reschedule, tx_done = 1; 241 242 reschedule = lio_droq_process_packets(oct, droq, oct->rx_budget); 243 244 if (atomic_load_acq_int(&iq->instr_pending)) 245 tx_done = lio_flush_iq(oct, iq, oct->tx_budget); 246 247 if (reschedule || !tx_done) 248 taskqueue_enqueue(droq->droq_taskqueue, &droq->droq_task); 249 else 250 lio_enable_irq(droq, iq); 251 } 252 253 int 254 lio_init_droq(struct octeon_device *oct, uint32_t q_no, 255 uint32_t num_descs, uint32_t desc_size, void *app_ctx) 256 { 257 struct lio_droq *droq; 258 unsigned long size; 259 uint32_t c_buf_size = 0, c_num_descs = 0, c_pkts_per_intr = 0; 260 uint32_t c_refill_threshold = 0, desc_ring_size = 0; 261 262 lio_dev_dbg(oct, "%s[%d]\n", __func__, q_no); 263 264 droq = oct->droq[q_no]; 265 bzero(droq, LIO_DROQ_SIZE); 266 267 droq->oct_dev = oct; 268 droq->q_no = q_no; 269 if (app_ctx != NULL) 270 droq->app_ctx = app_ctx; 271 else 272 droq->app_ctx = (void *)(size_t)q_no; 273 274 c_num_descs = num_descs; 275 c_buf_size = desc_size; 276 if (LIO_CN23XX_PF(oct)) { 277 struct lio_config *conf23 = LIO_CHIP_CONF(oct, cn23xx_pf); 278 279 c_pkts_per_intr = 280 (uint32_t)LIO_GET_OQ_PKTS_PER_INTR_CFG(conf23); 281 c_refill_threshold = 282 (uint32_t)LIO_GET_OQ_REFILL_THRESHOLD_CFG(conf23); 283 } else { 284 return (1); 285 } 286 287 droq->max_count = c_num_descs; 288 droq->buffer_size = c_buf_size; 289 290 desc_ring_size = droq->max_count * LIO_DROQ_DESC_SIZE; 291 droq->desc_ring = lio_dma_alloc(desc_ring_size, &droq->desc_ring_dma); 292 if (droq->desc_ring == NULL) { 293 lio_dev_err(oct, "Output queue %d ring alloc failed\n", q_no); 294 return (1); 295 } 296 297 lio_dev_dbg(oct, "droq[%d]: desc_ring: virt: 0x%p, dma: %llx\n", q_no, 298 droq->desc_ring, LIO_CAST64(droq->desc_ring_dma)); 299 lio_dev_dbg(oct, "droq[%d]: num_desc: %d\n", q_no, droq->max_count); 300 301 size = droq->max_count * LIO_DROQ_RECVBUF_SIZE; 302 droq->recv_buf_list = 303 (struct lio_recv_buffer *)malloc(size, M_DEVBUF, 304 M_NOWAIT | M_ZERO); 305 if (droq->recv_buf_list == NULL) { 306 lio_dev_err(oct, "Output queue recv buf list alloc failed\n"); 307 goto init_droq_fail; 308 } 309 310 if (lio_droq_setup_ring_buffers(oct, droq)) 311 goto init_droq_fail; 312 313 droq->pkts_per_intr = c_pkts_per_intr; 314 droq->refill_threshold = c_refill_threshold; 315 316 lio_dev_dbg(oct, "DROQ INIT: max_empty_descs: %d\n", 317 droq->max_empty_descs); 318 319 mtx_init(&droq->lock, "droq_lock", NULL, MTX_DEF); 320 321 STAILQ_INIT(&droq->dispatch_stq_head); 322 323 oct->fn_list.setup_oq_regs(oct, q_no); 324 325 oct->io_qmask.oq |= BIT_ULL(q_no); 326 327 /* 328 * Initialize the taskqueue that handles 329 * output queue packet processing. 330 */ 331 lio_dev_dbg(oct, "Initializing droq%d taskqueue\n", q_no); 332 NET_TASK_INIT(&droq->droq_task, 0, lio_droq_bh, (void *)droq); 333 334 droq->droq_taskqueue = taskqueue_create_fast("lio_droq_task", M_NOWAIT, 335 taskqueue_thread_enqueue, 336 &droq->droq_taskqueue); 337 taskqueue_start_threads_cpuset(&droq->droq_taskqueue, 1, PI_NET, 338 &oct->ioq_vector[q_no].affinity_mask, 339 "lio%d_droq%d_task", oct->octeon_id, 340 q_no); 341 342 return (0); 343 344 init_droq_fail: 345 lio_delete_droq(oct, q_no); 346 return (1); 347 } 348 349 /* 350 * lio_create_recv_info 351 * Parameters: 352 * octeon_dev - pointer to the octeon device structure 353 * droq - droq in which the packet arrived. 354 * buf_cnt - no. of buffers used by the packet. 355 * idx - index in the descriptor for the first buffer in the packet. 356 * Description: 357 * Allocates a recv_info_t and copies the buffer addresses for packet data 358 * into the recv_pkt space which starts at an 8B offset from recv_info_t. 359 * Flags the descriptors for refill later. If available descriptors go 360 * below the threshold to receive a 64K pkt, new buffers are first allocated 361 * before the recv_pkt_t is created. 362 * This routine will be called in interrupt context. 363 * Returns: 364 * Success: Pointer to recv_info_t 365 * Failure: NULL. 366 * Locks: 367 * The droq->lock is held when this routine is called. 368 */ 369 static inline struct lio_recv_info * 370 lio_create_recv_info(struct octeon_device *octeon_dev, struct lio_droq *droq, 371 uint32_t buf_cnt, uint32_t idx) 372 { 373 struct lio_droq_info *info; 374 struct lio_recv_pkt *recv_pkt; 375 struct lio_recv_info *recv_info; 376 uint32_t bytes_left, i; 377 378 info = (struct lio_droq_info *)droq->recv_buf_list[idx].data; 379 380 recv_info = lio_alloc_recv_info(sizeof(struct __dispatch)); 381 if (recv_info == NULL) 382 return (NULL); 383 384 recv_pkt = recv_info->recv_pkt; 385 recv_pkt->rh = info->rh; 386 recv_pkt->length = (uint32_t)info->length; 387 recv_pkt->buffer_count = (uint16_t)buf_cnt; 388 recv_pkt->octeon_id = (uint16_t)octeon_dev->octeon_id; 389 390 i = 0; 391 bytes_left = (uint32_t)info->length; 392 393 while (buf_cnt) { 394 recv_pkt->buffer_size[i] = (bytes_left >= droq->buffer_size) ? 395 droq->buffer_size : bytes_left; 396 397 recv_pkt->buffer_ptr[i] = droq->recv_buf_list[idx].buffer; 398 droq->recv_buf_list[idx].buffer = NULL; 399 400 idx = lio_incr_index(idx, 1, droq->max_count); 401 bytes_left -= droq->buffer_size; 402 i++; 403 buf_cnt--; 404 } 405 406 return (recv_info); 407 } 408 409 /* 410 * If we were not able to refill all buffers, try to move around 411 * the buffers that were not dispatched. 412 */ 413 static inline uint32_t 414 lio_droq_refill_pullup_descs(struct lio_droq *droq, 415 struct lio_droq_desc *desc_ring) 416 { 417 uint32_t desc_refilled = 0; 418 uint32_t refill_index = droq->refill_idx; 419 420 while (refill_index != droq->read_idx) { 421 if (droq->recv_buf_list[refill_index].buffer != NULL) { 422 droq->recv_buf_list[droq->refill_idx].buffer = 423 droq->recv_buf_list[refill_index].buffer; 424 droq->recv_buf_list[droq->refill_idx].data = 425 droq->recv_buf_list[refill_index].data; 426 desc_ring[droq->refill_idx].buffer_ptr = 427 desc_ring[refill_index].buffer_ptr; 428 droq->recv_buf_list[refill_index].buffer = NULL; 429 desc_ring[refill_index].buffer_ptr = 0; 430 do { 431 droq->refill_idx = 432 lio_incr_index(droq->refill_idx, 1, 433 droq->max_count); 434 desc_refilled++; 435 droq->refill_count--; 436 } while (droq->recv_buf_list[droq->refill_idx].buffer != 437 NULL); 438 } 439 refill_index = lio_incr_index(refill_index, 1, droq->max_count); 440 } /* while */ 441 return (desc_refilled); 442 } 443 444 /* 445 * lio_droq_refill 446 * Parameters: 447 * droq - droq in which descriptors require new buffers. 448 * Description: 449 * Called during normal DROQ processing in interrupt mode or by the poll 450 * thread to refill the descriptors from which buffers were dispatched 451 * to upper layers. Attempts to allocate new buffers. If that fails, moves 452 * up buffers (that were not dispatched) to form a contiguous ring. 453 * Returns: 454 * No of descriptors refilled. 455 * Locks: 456 * This routine is called with droq->lock held. 457 */ 458 uint32_t 459 lio_droq_refill(struct octeon_device *octeon_dev, struct lio_droq *droq) 460 { 461 struct lio_droq_desc *desc_ring; 462 void *buf = NULL; 463 uint32_t desc_refilled = 0; 464 uint8_t *data; 465 466 desc_ring = droq->desc_ring; 467 468 while (droq->refill_count && (desc_refilled < droq->max_count)) { 469 /* 470 * If a valid buffer exists (happens if there is no dispatch), 471 * reuse 472 * the buffer, else allocate. 473 */ 474 if (droq->recv_buf_list[droq->refill_idx].buffer == NULL) { 475 buf = lio_recv_buffer_alloc(droq->buffer_size); 476 /* 477 * If a buffer could not be allocated, no point in 478 * continuing 479 */ 480 if (buf == NULL) { 481 droq->stats.rx_alloc_failure++; 482 break; 483 } 484 485 droq->recv_buf_list[droq->refill_idx].buffer = buf; 486 data = ((struct mbuf *)buf)->m_data; 487 } else { 488 data = ((struct mbuf *)droq->recv_buf_list 489 [droq->refill_idx].buffer)->m_data; 490 } 491 492 droq->recv_buf_list[droq->refill_idx].data = data; 493 494 desc_ring[droq->refill_idx].buffer_ptr = 495 lio_map_ring(octeon_dev->device, 496 droq->recv_buf_list[droq->refill_idx].buffer, 497 droq->buffer_size); 498 499 droq->refill_idx = lio_incr_index(droq->refill_idx, 1, 500 droq->max_count); 501 desc_refilled++; 502 droq->refill_count--; 503 } 504 505 if (droq->refill_count) 506 desc_refilled += lio_droq_refill_pullup_descs(droq, desc_ring); 507 508 /* 509 * if droq->refill_count 510 * The refill count would not change in pass two. We only moved buffers 511 * to close the gap in the ring, but we would still have the same no. of 512 * buffers to refill. 513 */ 514 return (desc_refilled); 515 } 516 517 static inline uint32_t 518 lio_droq_get_bufcount(uint32_t buf_size, uint32_t total_len) 519 { 520 521 return ((total_len + buf_size - 1) / buf_size); 522 } 523 524 static int 525 lio_droq_dispatch_pkt(struct octeon_device *oct, struct lio_droq *droq, 526 union octeon_rh *rh, struct lio_droq_info *info) 527 { 528 struct lio_recv_info *rinfo; 529 lio_dispatch_fn_t disp_fn; 530 uint32_t cnt; 531 532 cnt = lio_droq_get_bufcount(droq->buffer_size, (uint32_t)info->length); 533 534 disp_fn = lio_get_dispatch(oct, (uint16_t)rh->r.opcode, 535 (uint16_t)rh->r.subcode); 536 if (disp_fn) { 537 rinfo = lio_create_recv_info(oct, droq, cnt, droq->read_idx); 538 if (rinfo != NULL) { 539 struct __dispatch *rdisp = rinfo->rsvd; 540 541 rdisp->rinfo = rinfo; 542 rdisp->disp_fn = disp_fn; 543 rinfo->recv_pkt->rh = *rh; 544 STAILQ_INSERT_TAIL(&droq->dispatch_stq_head, 545 &rdisp->node, entries); 546 } else { 547 droq->stats.dropped_nomem++; 548 } 549 } else { 550 lio_dev_err(oct, "DROQ: No dispatch function (opcode %u/%u)\n", 551 (unsigned int)rh->r.opcode, 552 (unsigned int)rh->r.subcode); 553 droq->stats.dropped_nodispatch++; 554 } 555 556 return (cnt); 557 } 558 559 static inline void 560 lio_droq_drop_packets(struct octeon_device *oct, struct lio_droq *droq, 561 uint32_t cnt) 562 { 563 struct lio_droq_info *info; 564 uint32_t i = 0, buf_cnt; 565 566 for (i = 0; i < cnt; i++) { 567 info = (struct lio_droq_info *) 568 droq->recv_buf_list[droq->read_idx].data; 569 570 lio_swap_8B_data((uint64_t *)info, 2); 571 572 if (info->length) { 573 info->length += 8; 574 droq->stats.bytes_received += info->length; 575 buf_cnt = lio_droq_get_bufcount(droq->buffer_size, 576 (uint32_t)info->length); 577 } else { 578 lio_dev_err(oct, "DROQ: In drop: pkt with len 0\n"); 579 buf_cnt = 1; 580 } 581 582 droq->read_idx = lio_incr_index(droq->read_idx, buf_cnt, 583 droq->max_count); 584 droq->refill_count += buf_cnt; 585 } 586 } 587 588 static uint32_t 589 lio_droq_fast_process_packets(struct octeon_device *oct, struct lio_droq *droq, 590 uint32_t pkts_to_process) 591 { 592 struct lio_droq_info *info; 593 union octeon_rh *rh; 594 uint32_t pkt, pkt_count, total_len = 0; 595 596 pkt_count = pkts_to_process; 597 598 for (pkt = 0; pkt < pkt_count; pkt++) { 599 struct mbuf *nicbuf = NULL; 600 uint32_t pkt_len = 0; 601 602 info = (struct lio_droq_info *) 603 droq->recv_buf_list[droq->read_idx].data; 604 605 lio_swap_8B_data((uint64_t *)info, 2); 606 607 if (!info->length) { 608 lio_dev_err(oct, 609 "DROQ[%d] idx: %d len:0, pkt_cnt: %d\n", 610 droq->q_no, droq->read_idx, pkt_count); 611 hexdump((uint8_t *)info, LIO_DROQ_INFO_SIZE, NULL, 612 HD_OMIT_CHARS); 613 pkt++; 614 lio_incr_index(droq->read_idx, 1, droq->max_count); 615 droq->refill_count++; 616 break; 617 } 618 619 rh = &info->rh; 620 621 info->length += 8; 622 rh->r_dh.len += (LIO_DROQ_INFO_SIZE + 7) / 8; 623 624 total_len += (uint32_t)info->length; 625 if (lio_opcode_slow_path(rh)) { 626 uint32_t buf_cnt; 627 628 buf_cnt = lio_droq_dispatch_pkt(oct, droq, rh, info); 629 droq->read_idx = lio_incr_index(droq->read_idx, buf_cnt, 630 droq->max_count); 631 droq->refill_count += buf_cnt; 632 } else { 633 if (info->length <= droq->buffer_size) { 634 pkt_len = (uint32_t)info->length; 635 nicbuf = droq->recv_buf_list[ 636 droq->read_idx].buffer; 637 nicbuf->m_len = pkt_len; 638 droq->recv_buf_list[droq->read_idx].buffer = 639 NULL; 640 641 droq->read_idx = 642 lio_incr_index(droq->read_idx, 643 1, droq->max_count); 644 droq->refill_count++; 645 } else { 646 bool secondary_frag = false; 647 648 pkt_len = 0; 649 650 while (pkt_len < info->length) { 651 int frag_len, idx = droq->read_idx; 652 struct mbuf *buffer; 653 654 frag_len = 655 ((pkt_len + droq->buffer_size) > 656 info->length) ? 657 ((uint32_t)info->length - 658 pkt_len) : droq->buffer_size; 659 660 buffer = ((struct mbuf *) 661 droq->recv_buf_list[idx]. 662 buffer); 663 buffer->m_len = frag_len; 664 if (__predict_true(secondary_frag)) { 665 m_cat(nicbuf, buffer); 666 } else { 667 nicbuf = buffer; 668 secondary_frag = true; 669 } 670 671 droq->recv_buf_list[droq->read_idx]. 672 buffer = NULL; 673 674 pkt_len += frag_len; 675 droq->read_idx = 676 lio_incr_index(droq->read_idx, 677 1, 678 droq->max_count); 679 droq->refill_count++; 680 } 681 } 682 683 if (nicbuf != NULL) { 684 if (droq->ops.fptr != NULL) { 685 droq->ops.fptr(nicbuf, pkt_len, rh, 686 droq, droq->ops.farg); 687 } else { 688 lio_recv_buffer_free(nicbuf); 689 } 690 } 691 } 692 693 if (droq->refill_count >= droq->refill_threshold) { 694 int desc_refilled = lio_droq_refill(oct, droq); 695 696 /* 697 * Flush the droq descriptor data to memory to be sure 698 * that when we update the credits the data in memory 699 * is accurate. 700 */ 701 wmb(); 702 lio_write_csr32(oct, droq->pkts_credit_reg, 703 desc_refilled); 704 /* make sure mmio write completes */ 705 __compiler_membar(); 706 } 707 } /* for (each packet)... */ 708 709 /* Increment refill_count by the number of buffers processed. */ 710 droq->stats.pkts_received += pkt; 711 droq->stats.bytes_received += total_len; 712 713 tcp_lro_flush_all(&droq->lro); 714 715 if ((droq->ops.drop_on_max) && (pkts_to_process - pkt)) { 716 lio_droq_drop_packets(oct, droq, (pkts_to_process - pkt)); 717 718 droq->stats.dropped_toomany += (pkts_to_process - pkt); 719 return (pkts_to_process); 720 } 721 722 return (pkt); 723 } 724 725 int 726 lio_droq_process_packets(struct octeon_device *oct, struct lio_droq *droq, 727 uint32_t budget) 728 { 729 struct lio_stailq_node *tmp, *tmp2; 730 uint32_t pkt_count = 0, pkts_processed = 0; 731 732 /* Grab the droq lock */ 733 mtx_lock(&droq->lock); 734 735 lio_droq_check_hw_for_pkts(droq); 736 pkt_count = atomic_load_acq_int(&droq->pkts_pending); 737 738 if (!pkt_count) { 739 mtx_unlock(&droq->lock); 740 return (0); 741 } 742 if (pkt_count > budget) 743 pkt_count = budget; 744 745 pkts_processed = lio_droq_fast_process_packets(oct, droq, pkt_count); 746 747 atomic_subtract_int(&droq->pkts_pending, pkts_processed); 748 749 /* Release the lock */ 750 mtx_unlock(&droq->lock); 751 752 STAILQ_FOREACH_SAFE(tmp, &droq->dispatch_stq_head, entries, tmp2) { 753 struct __dispatch *rdisp = (struct __dispatch *)tmp; 754 755 STAILQ_REMOVE_HEAD(&droq->dispatch_stq_head, entries); 756 rdisp->disp_fn(rdisp->rinfo, lio_get_dispatch_arg(oct, 757 (uint16_t)rdisp->rinfo->recv_pkt->rh.r.opcode, 758 (uint16_t)rdisp->rinfo->recv_pkt->rh.r.subcode)); 759 } 760 761 /* If there are packets pending. schedule tasklet again */ 762 if (atomic_load_acq_int(&droq->pkts_pending)) 763 return (1); 764 765 return (0); 766 } 767 768 int 769 lio_register_droq_ops(struct octeon_device *oct, uint32_t q_no, 770 struct lio_droq_ops *ops) 771 { 772 struct lio_droq *droq; 773 struct lio_config *lio_cfg = NULL; 774 775 lio_cfg = lio_get_conf(oct); 776 777 if (lio_cfg == NULL) 778 return (-EINVAL); 779 780 if (ops == NULL) { 781 lio_dev_err(oct, "%s: droq_ops pointer is NULL\n", __func__); 782 return (-EINVAL); 783 } 784 785 if (q_no >= LIO_GET_OQ_MAX_Q_CFG(lio_cfg)) { 786 lio_dev_err(oct, "%s: droq id (%d) exceeds MAX (%d)\n", 787 __func__, q_no, (oct->num_oqs - 1)); 788 return (-EINVAL); 789 } 790 droq = oct->droq[q_no]; 791 792 mtx_lock(&droq->lock); 793 794 memcpy(&droq->ops, ops, sizeof(struct lio_droq_ops)); 795 796 mtx_unlock(&droq->lock); 797 798 return (0); 799 } 800 801 int 802 lio_unregister_droq_ops(struct octeon_device *oct, uint32_t q_no) 803 { 804 struct lio_droq *droq; 805 struct lio_config *lio_cfg = NULL; 806 807 lio_cfg = lio_get_conf(oct); 808 809 if (lio_cfg == NULL) 810 return (-EINVAL); 811 812 if (q_no >= LIO_GET_OQ_MAX_Q_CFG(lio_cfg)) { 813 lio_dev_err(oct, "%s: droq id (%d) exceeds MAX (%d)\n", 814 __func__, q_no, oct->num_oqs - 1); 815 return (-EINVAL); 816 } 817 818 droq = oct->droq[q_no]; 819 820 if (droq == NULL) { 821 lio_dev_info(oct, "Droq id (%d) not available.\n", q_no); 822 return (0); 823 } 824 825 mtx_lock(&droq->lock); 826 827 droq->ops.fptr = NULL; 828 droq->ops.farg = NULL; 829 droq->ops.drop_on_max = 0; 830 831 mtx_unlock(&droq->lock); 832 833 return (0); 834 } 835 836 int 837 lio_create_droq(struct octeon_device *oct, uint32_t q_no, uint32_t num_descs, 838 uint32_t desc_size, void *app_ctx) 839 { 840 841 if (oct->droq[q_no]->oct_dev != NULL) { 842 lio_dev_dbg(oct, "Droq already in use. Cannot create droq %d again\n", 843 q_no); 844 return (1); 845 } 846 847 /* Initialize the Droq */ 848 if (lio_init_droq(oct, q_no, num_descs, desc_size, app_ctx)) { 849 bzero(oct->droq[q_no], sizeof(struct lio_droq)); 850 goto create_droq_fail; 851 } 852 853 oct->num_oqs++; 854 855 lio_dev_dbg(oct, "%s: Total number of OQ: %d\n", __func__, 856 oct->num_oqs); 857 858 /* Global Droq register settings */ 859 860 /* 861 * As of now not required, as setting are done for all 32 Droqs at 862 * the same time. 863 */ 864 return (0); 865 866 create_droq_fail: 867 return (-ENOMEM); 868 } 869