![]() |
|
|||
0001 /***********************license start*************** 0002 * Author: Cavium Networks 0003 * 0004 * Contact: support@caviumnetworks.com 0005 * This file is part of the OCTEON SDK 0006 * 0007 * Copyright (c) 2003-2008 Cavium Networks 0008 * 0009 * This file is free software; you can redistribute it and/or modify 0010 * it under the terms of the GNU General Public License, Version 2, as 0011 * published by the Free Software Foundation. 0012 * 0013 * This file is distributed in the hope that it will be useful, but 0014 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 0015 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 0016 * NONINFRINGEMENT. See the GNU General Public License for more 0017 * details. 0018 * 0019 * You should have received a copy of the GNU General Public License 0020 * along with this file; if not, write to the Free Software 0021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0022 * or visit http://www.gnu.org/licenses/. 0023 * 0024 * This file may also be available under a different license from Cavium. 0025 * Contact Cavium Networks for more information 0026 ***********************license end**************************************/ 0027 0028 /* 0029 * 0030 * Support functions for managing command queues used for 0031 * various hardware blocks. 0032 * 0033 * The common command queue infrastructure abstracts out the 0034 * software necessary for adding to Octeon's chained queue 0035 * structures. These structures are used for commands to the 0036 * PKO, ZIP, DFA, RAID, and DMA engine blocks. Although each 0037 * hardware unit takes commands and CSRs of different types, 0038 * they all use basic linked command buffers to store the 0039 * pending request. In general, users of the CVMX API don't 0040 * call cvmx-cmd-queue functions directly. Instead the hardware 0041 * unit specific wrapper should be used. The wrappers perform 0042 * unit specific validation and CSR writes to submit the 0043 * commands. 0044 * 0045 * Even though most software will never directly interact with 0046 * cvmx-cmd-queue, knowledge of its internal working can help 0047 * in diagnosing performance problems and help with debugging. 0048 * 0049 * Command queue pointers are stored in a global named block 0050 * called "cvmx_cmd_queues". Except for the PKO queues, each 0051 * hardware queue is stored in its own cache line to reduce SMP 0052 * contention on spin locks. The PKO queues are stored such that 0053 * every 16th queue is next to each other in memory. This scheme 0054 * allows for queues being in separate cache lines when there 0055 * are low number of queues per port. With 16 queues per port, 0056 * the first queue for each port is in the same cache area. The 0057 * second queues for each port are in another area, etc. This 0058 * allows software to implement very efficient lockless PKO with 0059 * 16 queues per port using a minimum of cache lines per core. 0060 * All queues for a given core will be isolated in the same 0061 * cache area. 0062 * 0063 * In addition to the memory pointer layout, cvmx-cmd-queue 0064 * provides an optimized fair ll/sc locking mechanism for the 0065 * queues. The lock uses a "ticket / now serving" model to 0066 * maintain fair order on contended locks. In addition, it uses 0067 * predicted locking time to limit cache contention. When a core 0068 * know it must wait in line for a lock, it spins on the 0069 * internal cycle counter to completely eliminate any causes of 0070 * bus traffic. 0071 * 0072 */ 0073 0074 #ifndef __CVMX_CMD_QUEUE_H__ 0075 #define __CVMX_CMD_QUEUE_H__ 0076 0077 #include <linux/prefetch.h> 0078 0079 #include <asm/compiler.h> 0080 0081 #include <asm/octeon/cvmx-fpa.h> 0082 /** 0083 * By default we disable the max depth support. Most programs 0084 * don't use it and it slows down the command queue processing 0085 * significantly. 0086 */ 0087 #ifndef CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH 0088 #define CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH 0 0089 #endif 0090 0091 /** 0092 * Enumeration representing all hardware blocks that use command 0093 * queues. Each hardware block has up to 65536 sub identifiers for 0094 * multiple command queues. Not all chips support all hardware 0095 * units. 0096 */ 0097 typedef enum { 0098 CVMX_CMD_QUEUE_PKO_BASE = 0x00000, 0099 0100 #define CVMX_CMD_QUEUE_PKO(queue) \ 0101 ((cvmx_cmd_queue_id_t)(CVMX_CMD_QUEUE_PKO_BASE + (0xffff&(queue)))) 0102 0103 CVMX_CMD_QUEUE_ZIP = 0x10000, 0104 CVMX_CMD_QUEUE_DFA = 0x20000, 0105 CVMX_CMD_QUEUE_RAID = 0x30000, 0106 CVMX_CMD_QUEUE_DMA_BASE = 0x40000, 0107 0108 #define CVMX_CMD_QUEUE_DMA(queue) \ 0109 ((cvmx_cmd_queue_id_t)(CVMX_CMD_QUEUE_DMA_BASE + (0xffff&(queue)))) 0110 0111 CVMX_CMD_QUEUE_END = 0x50000, 0112 } cvmx_cmd_queue_id_t; 0113 0114 /** 0115 * Command write operations can fail if the command queue needs 0116 * a new buffer and the associated FPA pool is empty. It can also 0117 * fail if the number of queued command words reaches the maximum 0118 * set at initialization. 0119 */ 0120 typedef enum { 0121 CVMX_CMD_QUEUE_SUCCESS = 0, 0122 CVMX_CMD_QUEUE_NO_MEMORY = -1, 0123 CVMX_CMD_QUEUE_FULL = -2, 0124 CVMX_CMD_QUEUE_INVALID_PARAM = -3, 0125 CVMX_CMD_QUEUE_ALREADY_SETUP = -4, 0126 } cvmx_cmd_queue_result_t; 0127 0128 typedef struct { 0129 /* You have lock when this is your ticket */ 0130 uint8_t now_serving; 0131 uint64_t unused1:24; 0132 /* Maximum outstanding command words */ 0133 uint32_t max_depth; 0134 /* FPA pool buffers come from */ 0135 uint64_t fpa_pool:3; 0136 /* Top of command buffer pointer shifted 7 */ 0137 uint64_t base_ptr_div128:29; 0138 uint64_t unused2:6; 0139 /* FPA buffer size in 64bit words minus 1 */ 0140 uint64_t pool_size_m1:13; 0141 /* Number of commands already used in buffer */ 0142 uint64_t index:13; 0143 } __cvmx_cmd_queue_state_t; 0144 0145 /** 0146 * This structure contains the global state of all command queues. 0147 * It is stored in a bootmem named block and shared by all 0148 * applications running on Octeon. Tickets are stored in a differnet 0149 * cache line that queue information to reduce the contention on the 0150 * ll/sc used to get a ticket. If this is not the case, the update 0151 * of queue state causes the ll/sc to fail quite often. 0152 */ 0153 typedef struct { 0154 uint64_t ticket[(CVMX_CMD_QUEUE_END >> 16) * 256]; 0155 __cvmx_cmd_queue_state_t state[(CVMX_CMD_QUEUE_END >> 16) * 256]; 0156 } __cvmx_cmd_queue_all_state_t; 0157 0158 /** 0159 * Initialize a command queue for use. The initial FPA buffer is 0160 * allocated and the hardware unit is configured to point to the 0161 * new command queue. 0162 * 0163 * @queue_id: Hardware command queue to initialize. 0164 * @max_depth: Maximum outstanding commands that can be queued. 0165 * @fpa_pool: FPA pool the command queues should come from. 0166 * @pool_size: Size of each buffer in the FPA pool (bytes) 0167 * 0168 * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code 0169 */ 0170 cvmx_cmd_queue_result_t cvmx_cmd_queue_initialize(cvmx_cmd_queue_id_t queue_id, 0171 int max_depth, int fpa_pool, 0172 int pool_size); 0173 0174 /** 0175 * Shutdown a queue a free it's command buffers to the FPA. The 0176 * hardware connected to the queue must be stopped before this 0177 * function is called. 0178 * 0179 * @queue_id: Queue to shutdown 0180 * 0181 * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code 0182 */ 0183 cvmx_cmd_queue_result_t cvmx_cmd_queue_shutdown(cvmx_cmd_queue_id_t queue_id); 0184 0185 /** 0186 * Return the number of command words pending in the queue. This 0187 * function may be relatively slow for some hardware units. 0188 * 0189 * @queue_id: Hardware command queue to query 0190 * 0191 * Returns Number of outstanding commands 0192 */ 0193 int cvmx_cmd_queue_length(cvmx_cmd_queue_id_t queue_id); 0194 0195 /** 0196 * Return the command buffer to be written to. The purpose of this 0197 * function is to allow CVMX routine access t othe low level buffer 0198 * for initial hardware setup. User applications should not call this 0199 * function directly. 0200 * 0201 * @queue_id: Command queue to query 0202 * 0203 * Returns Command buffer or NULL on failure 0204 */ 0205 void *cvmx_cmd_queue_buffer(cvmx_cmd_queue_id_t queue_id); 0206 0207 /** 0208 * Get the index into the state arrays for the supplied queue id. 0209 * 0210 * @queue_id: Queue ID to get an index for 0211 * 0212 * Returns Index into the state arrays 0213 */ 0214 static inline int __cvmx_cmd_queue_get_index(cvmx_cmd_queue_id_t queue_id) 0215 { 0216 /* 0217 * Warning: This code currently only works with devices that 0218 * have 256 queues or less. Devices with more than 16 queues 0219 * are laid out in memory to allow cores quick access to 0220 * every 16th queue. This reduces cache thrashing when you are 0221 * running 16 queues per port to support lockless operation. 0222 */ 0223 int unit = queue_id >> 16; 0224 int q = (queue_id >> 4) & 0xf; 0225 int core = queue_id & 0xf; 0226 return unit * 256 + core * 16 + q; 0227 } 0228 0229 /** 0230 * Lock the supplied queue so nobody else is updating it at the same 0231 * time as us. 0232 * 0233 * @queue_id: Queue ID to lock 0234 * @qptr: Pointer to the queue's global state 0235 */ 0236 static inline void __cvmx_cmd_queue_lock(cvmx_cmd_queue_id_t queue_id, 0237 __cvmx_cmd_queue_state_t *qptr) 0238 { 0239 extern __cvmx_cmd_queue_all_state_t 0240 *__cvmx_cmd_queue_state_ptr; 0241 int tmp; 0242 int my_ticket; 0243 prefetch(qptr); 0244 asm volatile ( 0245 ".set push\n" 0246 ".set noreorder\n" 0247 "1:\n" 0248 /* Atomic add one to ticket_ptr */ 0249 "ll %[my_ticket], %[ticket_ptr]\n" 0250 /* and store the original value */ 0251 "li %[ticket], 1\n" 0252 /* in my_ticket */ 0253 "baddu %[ticket], %[my_ticket]\n" 0254 "sc %[ticket], %[ticket_ptr]\n" 0255 "beqz %[ticket], 1b\n" 0256 " nop\n" 0257 /* Load the current now_serving ticket */ 0258 "lbu %[ticket], %[now_serving]\n" 0259 "2:\n" 0260 /* Jump out if now_serving == my_ticket */ 0261 "beq %[ticket], %[my_ticket], 4f\n" 0262 /* Find out how many tickets are in front of me */ 0263 " subu %[ticket], %[my_ticket], %[ticket]\n" 0264 /* Use tickets in front of me minus one to delay */ 0265 "subu %[ticket], 1\n" 0266 /* Delay will be ((tickets in front)-1)*32 loops */ 0267 "cins %[ticket], %[ticket], 5, 7\n" 0268 "3:\n" 0269 /* Loop here until our ticket might be up */ 0270 "bnez %[ticket], 3b\n" 0271 " subu %[ticket], 1\n" 0272 /* Jump back up to check out ticket again */ 0273 "b 2b\n" 0274 /* Load the current now_serving ticket */ 0275 " lbu %[ticket], %[now_serving]\n" 0276 "4:\n" 0277 ".set pop\n" : 0278 [ticket_ptr] "=" GCC_OFF_SMALL_ASM()(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]), 0279 [now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp), 0280 [my_ticket] "=r"(my_ticket) 0281 ); 0282 } 0283 0284 /** 0285 * Unlock the queue, flushing all writes. 0286 * 0287 * @qptr: Queue to unlock 0288 */ 0289 static inline void __cvmx_cmd_queue_unlock(__cvmx_cmd_queue_state_t *qptr) 0290 { 0291 qptr->now_serving++; 0292 CVMX_SYNCWS; 0293 } 0294 0295 /** 0296 * Get the queue state structure for the given queue id 0297 * 0298 * @queue_id: Queue id to get 0299 * 0300 * Returns Queue structure or NULL on failure 0301 */ 0302 static inline __cvmx_cmd_queue_state_t 0303 *__cvmx_cmd_queue_get_state(cvmx_cmd_queue_id_t queue_id) 0304 { 0305 extern __cvmx_cmd_queue_all_state_t 0306 *__cvmx_cmd_queue_state_ptr; 0307 return &__cvmx_cmd_queue_state_ptr-> 0308 state[__cvmx_cmd_queue_get_index(queue_id)]; 0309 } 0310 0311 /** 0312 * Write an arbitrary number of command words to a command queue. 0313 * This is a generic function; the fixed number of command word 0314 * functions yield higher performance. 0315 * 0316 * @queue_id: Hardware command queue to write to 0317 * @use_locking: 0318 * Use internal locking to ensure exclusive access for queue 0319 * updates. If you don't use this locking you must ensure 0320 * exclusivity some other way. Locking is strongly recommended. 0321 * @cmd_count: Number of command words to write 0322 * @cmds: Array of commands to write 0323 * 0324 * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code 0325 */ 0326 static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write(cvmx_cmd_queue_id_t 0327 queue_id, 0328 int use_locking, 0329 int cmd_count, 0330 uint64_t *cmds) 0331 { 0332 __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); 0333 0334 /* Make sure nobody else is updating the same queue */ 0335 if (likely(use_locking)) 0336 __cvmx_cmd_queue_lock(queue_id, qptr); 0337 0338 /* 0339 * If a max queue length was specified then make sure we don't 0340 * exceed it. If any part of the command would be below the 0341 * limit we allow it. 0342 */ 0343 if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) { 0344 if (unlikely 0345 (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) { 0346 if (likely(use_locking)) 0347 __cvmx_cmd_queue_unlock(qptr); 0348 return CVMX_CMD_QUEUE_FULL; 0349 } 0350 } 0351 0352 /* 0353 * Normally there is plenty of room in the current buffer for 0354 * the command. 0355 */ 0356 if (likely(qptr->index + cmd_count < qptr->pool_size_m1)) { 0357 uint64_t *ptr = 0358 (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> 0359 base_ptr_div128 << 7); 0360 ptr += qptr->index; 0361 qptr->index += cmd_count; 0362 while (cmd_count--) 0363 *ptr++ = *cmds++; 0364 } else { 0365 uint64_t *ptr; 0366 int count; 0367 /* 0368 * We need a new command buffer. Fail if there isn't 0369 * one available. 0370 */ 0371 uint64_t *new_buffer = 0372 (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool); 0373 if (unlikely(new_buffer == NULL)) { 0374 if (likely(use_locking)) 0375 __cvmx_cmd_queue_unlock(qptr); 0376 return CVMX_CMD_QUEUE_NO_MEMORY; 0377 } 0378 ptr = 0379 (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> 0380 base_ptr_div128 << 7); 0381 /* 0382 * Figure out how many command words will fit in this 0383 * buffer. One location will be needed for the next 0384 * buffer pointer. 0385 */ 0386 count = qptr->pool_size_m1 - qptr->index; 0387 ptr += qptr->index; 0388 cmd_count -= count; 0389 while (count--) 0390 *ptr++ = *cmds++; 0391 *ptr = cvmx_ptr_to_phys(new_buffer); 0392 /* 0393 * The current buffer is full and has a link to the 0394 * next buffer. Time to write the rest of the commands 0395 * into the new buffer. 0396 */ 0397 qptr->base_ptr_div128 = *ptr >> 7; 0398 qptr->index = cmd_count; 0399 ptr = new_buffer; 0400 while (cmd_count--) 0401 *ptr++ = *cmds++; 0402 } 0403 0404 /* All updates are complete. Release the lock and return */ 0405 if (likely(use_locking)) 0406 __cvmx_cmd_queue_unlock(qptr); 0407 return CVMX_CMD_QUEUE_SUCCESS; 0408 } 0409 0410 /** 0411 * Simple function to write two command words to a command 0412 * queue. 0413 * 0414 * @queue_id: Hardware command queue to write to 0415 * @use_locking: 0416 * Use internal locking to ensure exclusive access for queue 0417 * updates. If you don't use this locking you must ensure 0418 * exclusivity some other way. Locking is strongly recommended. 0419 * @cmd1: Command 0420 * @cmd2: Command 0421 * 0422 * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code 0423 */ 0424 static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write2(cvmx_cmd_queue_id_t 0425 queue_id, 0426 int use_locking, 0427 uint64_t cmd1, 0428 uint64_t cmd2) 0429 { 0430 __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); 0431 0432 /* Make sure nobody else is updating the same queue */ 0433 if (likely(use_locking)) 0434 __cvmx_cmd_queue_lock(queue_id, qptr); 0435 0436 /* 0437 * If a max queue length was specified then make sure we don't 0438 * exceed it. If any part of the command would be below the 0439 * limit we allow it. 0440 */ 0441 if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) { 0442 if (unlikely 0443 (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) { 0444 if (likely(use_locking)) 0445 __cvmx_cmd_queue_unlock(qptr); 0446 return CVMX_CMD_QUEUE_FULL; 0447 } 0448 } 0449 0450 /* 0451 * Normally there is plenty of room in the current buffer for 0452 * the command. 0453 */ 0454 if (likely(qptr->index + 2 < qptr->pool_size_m1)) { 0455 uint64_t *ptr = 0456 (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> 0457 base_ptr_div128 << 7); 0458 ptr += qptr->index; 0459 qptr->index += 2; 0460 ptr[0] = cmd1; 0461 ptr[1] = cmd2; 0462 } else { 0463 uint64_t *ptr; 0464 /* 0465 * Figure out how many command words will fit in this 0466 * buffer. One location will be needed for the next 0467 * buffer pointer. 0468 */ 0469 int count = qptr->pool_size_m1 - qptr->index; 0470 /* 0471 * We need a new command buffer. Fail if there isn't 0472 * one available. 0473 */ 0474 uint64_t *new_buffer = 0475 (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool); 0476 if (unlikely(new_buffer == NULL)) { 0477 if (likely(use_locking)) 0478 __cvmx_cmd_queue_unlock(qptr); 0479 return CVMX_CMD_QUEUE_NO_MEMORY; 0480 } 0481 count--; 0482 ptr = 0483 (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> 0484 base_ptr_div128 << 7); 0485 ptr += qptr->index; 0486 *ptr++ = cmd1; 0487 if (likely(count)) 0488 *ptr++ = cmd2; 0489 *ptr = cvmx_ptr_to_phys(new_buffer); 0490 /* 0491 * The current buffer is full and has a link to the 0492 * next buffer. Time to write the rest of the commands 0493 * into the new buffer. 0494 */ 0495 qptr->base_ptr_div128 = *ptr >> 7; 0496 qptr->index = 0; 0497 if (unlikely(count == 0)) { 0498 qptr->index = 1; 0499 new_buffer[0] = cmd2; 0500 } 0501 } 0502 0503 /* All updates are complete. Release the lock and return */ 0504 if (likely(use_locking)) 0505 __cvmx_cmd_queue_unlock(qptr); 0506 return CVMX_CMD_QUEUE_SUCCESS; 0507 } 0508 0509 /** 0510 * Simple function to write three command words to a command 0511 * queue. 0512 * 0513 * @queue_id: Hardware command queue to write to 0514 * @use_locking: 0515 * Use internal locking to ensure exclusive access for queue 0516 * updates. If you don't use this locking you must ensure 0517 * exclusivity some other way. Locking is strongly recommended. 0518 * @cmd1: Command 0519 * @cmd2: Command 0520 * @cmd3: Command 0521 * 0522 * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code 0523 */ 0524 static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write3(cvmx_cmd_queue_id_t 0525 queue_id, 0526 int use_locking, 0527 uint64_t cmd1, 0528 uint64_t cmd2, 0529 uint64_t cmd3) 0530 { 0531 __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); 0532 0533 /* Make sure nobody else is updating the same queue */ 0534 if (likely(use_locking)) 0535 __cvmx_cmd_queue_lock(queue_id, qptr); 0536 0537 /* 0538 * If a max queue length was specified then make sure we don't 0539 * exceed it. If any part of the command would be below the 0540 * limit we allow it. 0541 */ 0542 if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) { 0543 if (unlikely 0544 (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) { 0545 if (likely(use_locking)) 0546 __cvmx_cmd_queue_unlock(qptr); 0547 return CVMX_CMD_QUEUE_FULL; 0548 } 0549 } 0550 0551 /* 0552 * Normally there is plenty of room in the current buffer for 0553 * the command. 0554 */ 0555 if (likely(qptr->index + 3 < qptr->pool_size_m1)) { 0556 uint64_t *ptr = 0557 (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> 0558 base_ptr_div128 << 7); 0559 ptr += qptr->index; 0560 qptr->index += 3; 0561 ptr[0] = cmd1; 0562 ptr[1] = cmd2; 0563 ptr[2] = cmd3; 0564 } else { 0565 uint64_t *ptr; 0566 /* 0567 * Figure out how many command words will fit in this 0568 * buffer. One location will be needed for the next 0569 * buffer pointer 0570 */ 0571 int count = qptr->pool_size_m1 - qptr->index; 0572 /* 0573 * We need a new command buffer. Fail if there isn't 0574 * one available 0575 */ 0576 uint64_t *new_buffer = 0577 (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool); 0578 if (unlikely(new_buffer == NULL)) { 0579 if (likely(use_locking)) 0580 __cvmx_cmd_queue_unlock(qptr); 0581 return CVMX_CMD_QUEUE_NO_MEMORY; 0582 } 0583 count--; 0584 ptr = 0585 (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> 0586 base_ptr_div128 << 7); 0587 ptr += qptr->index; 0588 *ptr++ = cmd1; 0589 if (count) { 0590 *ptr++ = cmd2; 0591 if (count > 1) 0592 *ptr++ = cmd3; 0593 } 0594 *ptr = cvmx_ptr_to_phys(new_buffer); 0595 /* 0596 * The current buffer is full and has a link to the 0597 * next buffer. Time to write the rest of the commands 0598 * into the new buffer. 0599 */ 0600 qptr->base_ptr_div128 = *ptr >> 7; 0601 qptr->index = 0; 0602 ptr = new_buffer; 0603 if (count == 0) { 0604 *ptr++ = cmd2; 0605 qptr->index++; 0606 } 0607 if (count < 2) { 0608 *ptr++ = cmd3; 0609 qptr->index++; 0610 } 0611 } 0612 0613 /* All updates are complete. Release the lock and return */ 0614 if (likely(use_locking)) 0615 __cvmx_cmd_queue_unlock(qptr); 0616 return CVMX_CMD_QUEUE_SUCCESS; 0617 } 0618 0619 #endif /* __CVMX_CMD_QUEUE_H__ */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |