1 /*- 2 ******************************************************************************* 3 Copyright (C) 2015 Annapurna Labs Ltd. 4 5 This file may be licensed under the terms of the Annapurna Labs Commercial 6 License Agreement. 7 8 Alternatively, this file can be distributed under the terms of the GNU General 9 Public License V2 as published by the Free Software Foundation and can be 10 found at http://www.gnu.org/licenses/gpl-2.0.html 11 12 Alternatively, redistribution and use in source and binary forms, with or 13 without modification, are permitted provided that the following conditions are 14 met: 15 16 * Redistributions of source code must retain the above copyright notice, 17 this list of conditions and the following disclaimer. 18 19 * Redistributions in binary form must reproduce the above copyright 20 notice, this list of conditions and the following disclaimer in 21 the documentation and/or other materials provided with the 22 distribution. 23 24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 25 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 28 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 31 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 35 *******************************************************************************/ 36 37 /** 38 * @defgroup group_udma_api API 39 * @ingroup group_udma 40 * UDMA API 41 * @{ 42 * @} 43 * 44 * @defgroup group_udma_main UDMA Main 45 * @ingroup group_udma_api 46 * UDMA main API 47 * @{ 48 * @file al_hal_udma.h 49 * 50 * @brief C Header file for the Universal DMA HAL driver 51 * 52 */ 53 54 #ifndef __AL_HAL_UDMA_H__ 55 #define __AL_HAL_UDMA_H__ 56 57 #include "al_hal_common.h" 58 #include "al_hal_udma_regs.h" 59 60 /* *INDENT-OFF* */ 61 #ifdef __cplusplus 62 extern "C" { 63 #endif 64 /* *INDENT-ON* */ 65 66 #define DMA_MAX_Q 4 67 #define AL_UDMA_MIN_Q_SIZE 4 68 #define AL_UDMA_MAX_Q_SIZE (1 << 16) /* hw can do more, but we limit it */ 69 70 /* Default Max number of descriptors supported per action */ 71 #define AL_UDMA_DEFAULT_MAX_ACTN_DESCS 16 72 73 #define AL_UDMA_REV_ID_0 0 74 #define AL_UDMA_REV_ID_1 1 75 #define AL_UDMA_REV_ID_2 2 76 77 #define DMA_RING_ID_MASK 0x3 78 /* New registers ?? */ 79 /* Statistics - TBD */ 80 81 /** UDMA submission descriptor */ 82 union al_udma_desc { 83 /* TX */ 84 struct { 85 uint32_t len_ctrl; 86 uint32_t meta_ctrl; 87 uint64_t buf_ptr; 88 } tx; 89 /* TX Meta, used by upper layer */ 90 struct { 91 uint32_t len_ctrl; 92 uint32_t meta_ctrl; 93 uint32_t meta1; 94 uint32_t meta2; 95 } tx_meta; 96 /* RX */ 97 struct { 98 uint32_t len_ctrl; 99 uint32_t buf2_ptr_lo; 100 uint64_t buf1_ptr; 101 } rx; 102 } __packed_a16; 103 104 /* TX desc length and control fields */ 105 106 #define AL_M2S_DESC_CONCAT AL_BIT(31) /* concatenate */ 107 #define AL_M2S_DESC_DMB AL_BIT(30) 108 /** Data Memory Barrier */ 109 #define AL_M2S_DESC_NO_SNOOP_H AL_BIT(29) 110 #define AL_M2S_DESC_INT_EN AL_BIT(28) /** enable interrupt */ 111 #define AL_M2S_DESC_LAST AL_BIT(27) 112 #define AL_M2S_DESC_FIRST AL_BIT(26) 113 #define AL_M2S_DESC_RING_ID_SHIFT 24 114 #define AL_M2S_DESC_RING_ID_MASK (0x3 << AL_M2S_DESC_RING_ID_SHIFT) 115 #define AL_M2S_DESC_META_DATA AL_BIT(23) 116 #define AL_M2S_DESC_DUMMY AL_BIT(22) /* for Metdata only */ 117 #define AL_M2S_DESC_LEN_ADJ_SHIFT 20 118 #define AL_M2S_DESC_LEN_ADJ_MASK (0x7 << AL_M2S_DESC_LEN_ADJ_SHIFT) 119 #define AL_M2S_DESC_LEN_SHIFT 0 120 #define AL_M2S_DESC_LEN_MASK (0xfffff << AL_M2S_DESC_LEN_SHIFT) 121 122 #define AL_S2M_DESC_DUAL_BUF AL_BIT(31) 123 #define AL_S2M_DESC_NO_SNOOP_H AL_BIT(29) 124 #define AL_S2M_DESC_INT_EN AL_BIT(28) /** enable interrupt */ 125 #define AL_S2M_DESC_RING_ID_SHIFT 24 126 #define AL_S2M_DESC_RING_ID_MASK (0x3 << AL_S2M_DESC_RING_ID_SHIFT) 127 #define AL_S2M_DESC_LEN_SHIFT 0 128 #define AL_S2M_DESC_LEN_MASK (0xffff << AL_S2M_DESC_LEN_SHIFT) 129 #define AL_S2M_DESC_LEN2_SHIFT 16 130 #define AL_S2M_DESC_LEN2_MASK (0x3fff << AL_S2M_DESC_LEN2_SHIFT) 131 #define AL_S2M_DESC_LEN2_GRANULARITY_SHIFT 6 132 133 /* TX/RX descriptor VMID field (in the buffer address 64 bit field) */ 134 #define AL_UDMA_DESC_VMID_SHIFT 48 135 136 /** UDMA completion descriptor */ 137 union al_udma_cdesc { 138 /* TX completion */ 139 struct { 140 uint32_t ctrl_meta; 141 } al_desc_comp_tx; 142 /* RX completion */ 143 struct { 144 /* TBD */ 145 uint32_t ctrl_meta; 146 } al_desc_comp_rx; 147 } __packed_a4; 148 149 /* TX/RX common completion desc ctrl_meta feilds */ 150 #define AL_UDMA_CDESC_ERROR AL_BIT(31) 151 #define AL_UDMA_CDESC_BUF1_USED AL_BIT(30) 152 #define AL_UDMA_CDESC_DDP AL_BIT(29) 153 #define AL_UDMA_CDESC_LAST AL_BIT(27) 154 #define AL_UDMA_CDESC_FIRST AL_BIT(26) 155 /* word 2 */ 156 #define AL_UDMA_CDESC_BUF2_USED AL_BIT(31) 157 #define AL_UDMA_CDESC_BUF2_LEN_SHIFT 16 158 #define AL_UDMA_CDESC_BUF2_LEN_MASK AL_FIELD_MASK(29, 16) 159 /** Basic Buffer structure */ 160 struct al_buf { 161 al_phys_addr_t addr; /**< Buffer physical address */ 162 uint32_t len; /**< Buffer lenght in bytes */ 163 }; 164 165 /** Block is a set of buffers that belong to same source or destination */ 166 struct al_block { 167 struct al_buf *bufs; /**< The buffers of the block */ 168 uint32_t num; /**< Number of buffers of the block */ 169 170 /**< 171 * VMID to be assigned to the block descriptors 172 * Requires VMID in descriptor to be enabled for the specific UDMA 173 * queue. 174 */ 175 uint16_t vmid; 176 }; 177 178 /** UDMA type */ 179 enum al_udma_type { 180 UDMA_TX, 181 UDMA_RX 182 }; 183 184 /** UDMA state */ 185 enum al_udma_state { 186 UDMA_DISABLE = 0, 187 UDMA_IDLE, 188 UDMA_NORMAL, 189 UDMA_ABORT, 190 UDMA_RESET 191 }; 192 193 extern const char *const al_udma_states_name[]; 194 195 /** UDMA Q specific parameters from upper layer */ 196 struct al_udma_q_params { 197 uint32_t size; /**< ring size (in descriptors), submission and 198 * completion rings must have same size 199 */ 200 union al_udma_desc *desc_base; /**< cpu address for submission ring 201 * descriptors 202 */ 203 al_phys_addr_t desc_phy_base; /**< submission ring descriptors 204 * physical base address 205 */ 206 #ifdef __FreeBSD__ 207 bus_dma_tag_t desc_phy_base_tag; 208 bus_dmamap_t desc_phy_base_map; 209 #endif 210 uint8_t *cdesc_base; /**< completion descriptors pointer, NULL */ 211 /* means no completion update */ 212 al_phys_addr_t cdesc_phy_base; /**< completion descriptors ring 213 * physical base address 214 */ 215 #ifdef __FreeBSD__ 216 bus_dma_tag_t cdesc_phy_base_tag; 217 bus_dmamap_t cdesc_phy_base_map; 218 #endif 219 uint32_t cdesc_size; /**< size (in bytes) of a single dma completion 220 * descriptor 221 */ 222 223 uint8_t adapter_rev_id; /**<PCI adapter revision ID */ 224 }; 225 226 /** UDMA parameters from upper layer */ 227 struct al_udma_params { 228 struct unit_regs __iomem *udma_regs_base; 229 enum al_udma_type type; /**< Tx or Rx */ 230 uint8_t num_of_queues; /**< number of queues supported by the UDMA */ 231 const char *name; /**< the upper layer must keep the string area */ 232 }; 233 234 /* Fordward decleration */ 235 struct al_udma; 236 237 /** SW status of a queue */ 238 enum al_udma_queue_status { 239 AL_QUEUE_NOT_INITIALIZED = 0, 240 AL_QUEUE_DISABLED, 241 AL_QUEUE_ENABLED, 242 AL_QUEUE_ABORTED 243 }; 244 245 /** UDMA Queue private data structure */ 246 struct __cache_aligned al_udma_q { 247 uint16_t size_mask; /**< mask used for pointers wrap around 248 * equals to size - 1 249 */ 250 union udma_q_regs __iomem *q_regs; /**< pointer to the per queue UDMA 251 * registers 252 */ 253 union al_udma_desc *desc_base_ptr; /**< base address submission ring 254 * descriptors 255 */ 256 uint16_t next_desc_idx; /**< index to the next available submission 257 * descriptor 258 */ 259 260 uint32_t desc_ring_id; /**< current submission ring id */ 261 262 uint8_t *cdesc_base_ptr;/**< completion descriptors pointer, NULL */ 263 /* means no completion */ 264 uint32_t cdesc_size; /**< size (in bytes) of the udma completion ring 265 * descriptor 266 */ 267 uint16_t next_cdesc_idx; /**< index in descriptors for next completing 268 * ring descriptor 269 */ 270 uint8_t *end_cdesc_ptr; /**< used for wrap around detection */ 271 uint16_t comp_head_idx; /**< completion ring head pointer register 272 *shadow 273 */ 274 volatile union al_udma_cdesc *comp_head_ptr; /**< when working in get_packet mode 275 * we maintain pointer instead of the 276 * above idx 277 */ 278 279 uint32_t pkt_crnt_descs; /**< holds the number of processed descriptors 280 * of the current packet 281 */ 282 uint32_t comp_ring_id; /**< current completion Ring Id */ 283 284 285 al_phys_addr_t desc_phy_base; /**< submission desc. physical base */ 286 al_phys_addr_t cdesc_phy_base; /**< completion desc. physical base */ 287 288 uint32_t flags; /**< flags used for completion modes */ 289 uint32_t size; /**< ring size in descriptors */ 290 enum al_udma_queue_status status; 291 struct al_udma *udma; /**< pointer to parent UDMA */ 292 uint32_t qid; /**< the index number of the queue */ 293 294 /* 295 * The following fields are duplicated from the UDMA parent adapter 296 * due to performance considerations. 297 */ 298 uint8_t adapter_rev_id; /**<PCI adapter revision ID */ 299 }; 300 301 /* UDMA */ 302 struct al_udma { 303 const char *name; 304 enum al_udma_type type; /* Tx or Rx */ 305 enum al_udma_state state; 306 uint8_t num_of_queues; /* number of queues supported by the UDMA */ 307 union udma_regs __iomem *udma_regs; /* pointer to the UDMA registers */ 308 struct udma_gen_regs *gen_regs; /* pointer to the Gen registers*/ 309 struct al_udma_q udma_q[DMA_MAX_Q]; /* Array of UDMA Qs pointers */ 310 unsigned int rev_id; /* UDMA revision ID */ 311 }; 312 313 314 /* 315 * Configurations 316 */ 317 318 /* Initializations functions */ 319 /** 320 * Initialize the udma engine 321 * 322 * @param udma udma data structure 323 * @param udma_params udma parameters from upper layer 324 * 325 * @return 0 on success. -EINVAL otherwise. 326 */ 327 int al_udma_init(struct al_udma *udma, struct al_udma_params *udma_params); 328 329 /** 330 * Initialize the udma queue data structure 331 * 332 * @param udma 333 * @param qid 334 * @param q_params 335 * 336 * @return 0 if no error found. 337 * -EINVAL if the qid is out of range 338 * -EIO if queue was already initialized 339 */ 340 341 int al_udma_q_init(struct al_udma *udma, uint32_t qid, 342 struct al_udma_q_params *q_params); 343 344 /** 345 * Reset a udma queue 346 * 347 * Prior to calling this function make sure: 348 * 1. Queue interrupts are masked 349 * 2. No additional descriptors are written to the descriptor ring of the queue 350 * 3. No completed descriptors are being fetched 351 * 352 * The queue can be initialized again using 'al_udma_q_init' 353 * 354 * @param udma_q 355 * 356 * @return 0 if no error found. 357 */ 358 359 int al_udma_q_reset(struct al_udma_q *udma_q); 360 361 /** 362 * return (by reference) a pointer to a specific queue date structure. 363 * this pointer needed for calling functions (i.e. al_udma_desc_action_add) that 364 * require this pointer as input argument. 365 * 366 * @param udma udma data structure 367 * @param qid queue index 368 * @param q_handle pointer to the location where the queue structure pointer 369 * written to. 370 * 371 * @return 0 on success. -EINVAL otherwise. 372 */ 373 int al_udma_q_handle_get(struct al_udma *udma, uint32_t qid, 374 struct al_udma_q **q_handle); 375 376 /** 377 * Change the UDMA's state 378 * 379 * @param udma udma data structure 380 * @param state the target state 381 * 382 * @return 0 383 */ 384 int al_udma_state_set(struct al_udma *udma, enum al_udma_state state); 385 386 /** 387 * return the current UDMA hardware state 388 * 389 * @param udma udma handle 390 * 391 * @return the UDMA state as reported by the hardware. 392 */ 393 enum al_udma_state al_udma_state_get(struct al_udma *udma); 394 395 /* 396 * Action handling 397 */ 398 399 /** 400 * get number of descriptors that can be submitted to the udma. 401 * keep one free descriptor to simplify full/empty management 402 * @param udma_q queue handle 403 * 404 * @return num of free descriptors. 405 */ 406 static INLINE uint32_t al_udma_available_get(struct al_udma_q *udma_q) 407 { 408 uint16_t tmp = udma_q->next_cdesc_idx - (udma_q->next_desc_idx + 1); 409 tmp &= udma_q->size_mask; 410 411 return (uint32_t) tmp; 412 } 413 414 /** 415 * check if queue has pending descriptors 416 * 417 * @param udma_q queue handle 418 * 419 * @return AL_TRUE if descriptors are submitted to completion ring and still 420 * not completed (with ack). AL_FALSE otherwise. 421 */ 422 static INLINE al_bool al_udma_is_empty(struct al_udma_q *udma_q) 423 { 424 if (((udma_q->next_cdesc_idx - udma_q->next_desc_idx) & 425 udma_q->size_mask) == 0) 426 return AL_TRUE; 427 428 return AL_FALSE; 429 } 430 431 /** 432 * get next available descriptor 433 * @param udma_q queue handle 434 * 435 * @return pointer to the next available descriptor 436 */ 437 static INLINE union al_udma_desc *al_udma_desc_get(struct al_udma_q *udma_q) 438 { 439 union al_udma_desc *desc; 440 uint16_t next_desc_idx; 441 442 al_assert(udma_q); 443 444 next_desc_idx = udma_q->next_desc_idx; 445 desc = udma_q->desc_base_ptr + next_desc_idx; 446 447 next_desc_idx++; 448 449 /* if reached end of queue, wrap around */ 450 udma_q->next_desc_idx = next_desc_idx & udma_q->size_mask; 451 452 return desc; 453 } 454 455 /** 456 * get ring id for the last allocated descriptor 457 * @param udma_q 458 * 459 * @return ring id for the last allocated descriptor 460 * this function must be called each time a new descriptor is allocated 461 * by the al_udma_desc_get(), unless ring id is ignored. 462 */ 463 static INLINE uint32_t al_udma_ring_id_get(struct al_udma_q *udma_q) 464 { 465 uint32_t ring_id; 466 467 al_assert(udma_q); 468 469 ring_id = udma_q->desc_ring_id; 470 471 /* calculate the ring id of the next desc */ 472 /* if next_desc points to first desc, then queue wrapped around */ 473 if (unlikely(udma_q->next_desc_idx) == 0) 474 udma_q->desc_ring_id = (udma_q->desc_ring_id + 1) & 475 DMA_RING_ID_MASK; 476 return ring_id; 477 } 478 479 /* add DMA action - trigger the engine */ 480 /** 481 * add num descriptors to the submission queue. 482 * 483 * @param udma_q queue handle 484 * @param num number of descriptors to add to the queues ring. 485 * 486 * @return 0; 487 */ 488 static INLINE int al_udma_desc_action_add(struct al_udma_q *udma_q, 489 uint32_t num) 490 { 491 uint32_t *addr; 492 493 al_assert(udma_q); 494 al_assert((num > 0) && (num <= udma_q->size)); 495 496 addr = &udma_q->q_regs->rings.drtp_inc; 497 /* make sure data written to the descriptors will be visible by the */ 498 /* DMA */ 499 al_local_data_memory_barrier(); 500 501 /* 502 * As we explicitly invoke the synchronization function 503 * (al_data_memory_barrier()), then we can use the relaxed version. 504 */ 505 al_reg_write32_relaxed(addr, num); 506 507 return 0; 508 } 509 510 #define cdesc_is_first(flags) ((flags) & AL_UDMA_CDESC_FIRST) 511 #define cdesc_is_last(flags) ((flags) & AL_UDMA_CDESC_LAST) 512 513 /** 514 * return pointer to the cdesc + offset desciptors. wrap around when needed. 515 * 516 * @param udma_q queue handle 517 * @param cdesc pointer that set by this function 518 * @param offset offset desciptors 519 * 520 */ 521 static INLINE volatile union al_udma_cdesc *al_cdesc_next( 522 struct al_udma_q *udma_q, 523 volatile union al_udma_cdesc *cdesc, 524 uint32_t offset) 525 { 526 volatile uint8_t *tmp = (volatile uint8_t *) cdesc + offset * udma_q->cdesc_size; 527 al_assert(udma_q); 528 al_assert(cdesc); 529 530 /* if wrap around */ 531 if (unlikely((tmp > udma_q->end_cdesc_ptr))) 532 return (union al_udma_cdesc *) 533 (udma_q->cdesc_base_ptr + 534 (tmp - udma_q->end_cdesc_ptr - udma_q->cdesc_size)); 535 536 return (volatile union al_udma_cdesc *) tmp; 537 } 538 539 /** 540 * check if the flags of the descriptor indicates that is new one 541 * the function uses the ring id from the descriptor flags to know whether it 542 * new one by comparing it with the curring ring id of the queue 543 * 544 * @param udma_q queue handle 545 * @param flags the flags of the completion descriptor 546 * 547 * @return AL_TRUE if the completion descriptor is new one. 548 * AL_FALSE if it old one. 549 */ 550 static INLINE al_bool al_udma_new_cdesc(struct al_udma_q *udma_q, 551 uint32_t flags) 552 { 553 if (((flags & AL_M2S_DESC_RING_ID_MASK) >> AL_M2S_DESC_RING_ID_SHIFT) 554 == udma_q->comp_ring_id) 555 return AL_TRUE; 556 return AL_FALSE; 557 } 558 559 /** 560 * get next completion descriptor 561 * this function will also increment the completion ring id when the ring wraps 562 * around 563 * 564 * @param udma_q queue handle 565 * @param cdesc current completion descriptor 566 * 567 * @return pointer to the completion descriptor that follows the one pointed by 568 * cdesc 569 */ 570 static INLINE volatile union al_udma_cdesc *al_cdesc_next_update( 571 struct al_udma_q *udma_q, 572 volatile union al_udma_cdesc *cdesc) 573 { 574 /* if last desc, wrap around */ 575 if (unlikely(((volatile uint8_t *) cdesc == udma_q->end_cdesc_ptr))) { 576 udma_q->comp_ring_id = 577 (udma_q->comp_ring_id + 1) & DMA_RING_ID_MASK; 578 return (union al_udma_cdesc *) udma_q->cdesc_base_ptr; 579 } 580 return (volatile union al_udma_cdesc *) ((volatile uint8_t *) cdesc + udma_q->cdesc_size); 581 } 582 583 /** 584 * get next completed packet from completion ring of the queue 585 * 586 * @param udma_q udma queue handle 587 * @param desc pointer that set by this function to the first descriptor 588 * note: desc is valid only when return value is not zero 589 * @return number of descriptors that belong to the packet. 0 means no completed 590 * full packet was found. 591 * If the descriptors found in the completion queue don't form full packet (no 592 * desc with LAST flag), then this function will do the following: 593 * (1) save the number of processed descriptors. 594 * (2) save last processed descriptor, so next time it called, it will resume 595 * from there. 596 * (3) return 0. 597 * note: the descriptors that belong to the completed packet will still be 598 * considered as used, that means the upper layer is safe to access those 599 * descriptors when this function returns. the al_udma_cdesc_ack() should be 600 * called to inform the udma driver that those descriptors are freed. 601 */ 602 uint32_t al_udma_cdesc_packet_get( 603 struct al_udma_q *udma_q, 604 volatile union al_udma_cdesc **desc); 605 606 /** get completion descriptor pointer from its index */ 607 #define al_udma_cdesc_idx_to_ptr(udma_q, idx) \ 608 ((volatile union al_udma_cdesc *) ((udma_q)->cdesc_base_ptr + \ 609 (idx) * (udma_q)->cdesc_size)) 610 611 612 /** 613 * return number of all completed descriptors in the completion ring 614 * 615 * @param udma_q udma queue handle 616 * @param cdesc pointer that set by this function to the first descriptor 617 * note: desc is valid only when return value is not zero 618 * note: pass NULL if not interested 619 * @return number of descriptors. 0 means no completed descriptors were found. 620 * note: the descriptors that belong to the completed packet will still be 621 * considered as used, that means the upper layer is safe to access those 622 * descriptors when this function returns. the al_udma_cdesc_ack() should be 623 * called to inform the udma driver that those descriptors are freed. 624 */ 625 static INLINE uint32_t al_udma_cdesc_get_all( 626 struct al_udma_q *udma_q, 627 volatile union al_udma_cdesc **cdesc) 628 { 629 uint16_t count = 0; 630 631 al_assert(udma_q); 632 633 udma_q->comp_head_idx = (uint16_t) 634 (al_reg_read32(&udma_q->q_regs->rings.crhp) & 635 0xFFFF); 636 637 count = (udma_q->comp_head_idx - udma_q->next_cdesc_idx) & 638 udma_q->size_mask; 639 640 if (cdesc) 641 *cdesc = al_udma_cdesc_idx_to_ptr(udma_q, udma_q->next_cdesc_idx); 642 643 return (uint32_t)count; 644 } 645 646 /** 647 * acknowledge the driver that the upper layer completed processing completion 648 * descriptors 649 * 650 * @param udma_q udma queue handle 651 * @param num number of descriptors to acknowledge 652 * 653 * @return 0 654 */ 655 static INLINE int al_udma_cdesc_ack(struct al_udma_q *udma_q, uint32_t num) 656 { 657 al_assert(udma_q); 658 659 udma_q->next_cdesc_idx += num; 660 udma_q->next_cdesc_idx &= udma_q->size_mask; 661 662 return 0; 663 } 664 665 /* *INDENT-OFF* */ 666 #ifdef __cplusplus 667 } 668 #endif 669 /* *INDENT-ON* */ 670 671 #endif /* __AL_HAL_UDMA_H__ */ 672 /** @} end of UDMA group */ 673