/***********************license start*************** * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights * reserved. * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * * Neither the name of Cavium Networks nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. * * * For any questions regarding licensing please contact marketing@caviumnetworks.com * ***********************license end**************************************/ /*------------------------------------------------------------------ * octeon_fpa.c Free Pool Allocator * *------------------------------------------------------------------ */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include "octeon_fpa.h" #define FPA_DEBUG 1 /* * octeon_dump_fpa * */ void octeon_dump_fpa (void) { int i; octeon_fpa_ctl_status_t status; octeon_fpa_queue_available_t q_avail; status.word64 = oct_read64(OCTEON_FPA_CTL_STATUS); if (!status.bits.enb) { printf("\n FPA Disabled"); /* * No dumping if disabled */ return; } printf(" FPA Ctrl-Status-reg 0x%llX := 0x%llX EN %X M1_E %X M0_E %X\n", OCTEON_FPA_CTL_STATUS, (unsigned long long)status.word64, status.bits.enb, status.bits.mem1_err, status.bits.mem0_err); for (i = 0; i < OCTEON_FPA_QUEUES; i++) { printf(" Pool: %d\n", i); q_avail.word64 = oct_read64((OCTEON_FPA_QUEUE_AVAILABLE + (i)*8ull)); printf(" Avail-reg 0x%llX := Size: 0x%X\n", (OCTEON_FPA_QUEUE_AVAILABLE + (i)*8ull), q_avail.bits.queue_size); } } void octeon_dump_fpa_pool (u_int pool) { octeon_fpa_ctl_status_t status; octeon_fpa_queue_available_t q_avail; status.word64 = oct_read64(OCTEON_FPA_CTL_STATUS); if (!status.bits.enb) { printf("\n FPA Disabled"); /* * No dumping if disabled */ return; } printf(" FPA Ctrl-Status-reg 0x%llX := 0x%llX EN %X M1_E %X M0_E %X\n", OCTEON_FPA_CTL_STATUS, (unsigned long long)status.word64, status.bits.enb, status.bits.mem1_err, status.bits.mem0_err); q_avail.word64 = oct_read64((OCTEON_FPA_QUEUE_AVAILABLE + (pool)*8ull)); printf(" FPA Pool: %u Avail-reg 0x%llX := Size: 0x%X\n", pool, (OCTEON_FPA_QUEUE_AVAILABLE + (pool)*8ull), q_avail.bits.queue_size); } u_int octeon_fpa_pool_size (u_int pool) { octeon_fpa_queue_available_t q_avail; u_int size = 0; if (pool < 7) { q_avail.word64 = oct_read64((OCTEON_FPA_QUEUE_AVAILABLE + (pool)*8ull)); size = q_avail.bits.queue_size; } return (size); } /* * octeon_enable_fpa * * configure fpa with defaults and then mark it enabled. */ void octeon_enable_fpa (void) { int i; octeon_fpa_ctl_status_t status; octeon_fpa_fpf_marks_t marks; for (i = 0; i < OCTEON_FPA_QUEUES; i++) { marks.word64 = oct_read64((OCTEON_FPA_FPF_MARKS + (i)*8ull)); marks.bits.fpf_wr = 0xe0; oct_write64((OCTEON_FPA_FPF_MARKS + (i)*8ull), marks.word64); } /* Enforce a 10 cycle delay between config and enable */ octeon_wait(10); status.word64 = 0; status.bits.enb = 1; oct_write64(OCTEON_FPA_CTL_STATUS, status.word64); } #define FPA_DEBUG_TERSE 1 /* * octeon_fpa_fill_pool_mem * * Fill the specified FPA pool with elem_num number of * elements of size elem_size_words * 8 */ void octeon_fpa_fill_pool_mem (u_int pool, u_int elem_size_words, u_int elem_num) { void *memory; u_int bytes, elem_size_bytes; u_int block_size; #ifdef FPA_DEBUG u_int elems = elem_num; printf(" FPA fill: Pool %u elem_size_words %u Num: %u\n", pool, elem_size_words, elem_num); #endif elem_size_bytes = elem_size_words * sizeof(uint64_t); block_size = OCTEON_ALIGN(elem_size_bytes); // block_size = ((elem_size_bytes / OCTEON_FPA_POOL_ALIGNMENT) + 1) * OCTEON_FPA_POOL_ALIGNMENT; bytes = (elem_num * block_size); #ifdef FPA_DEBUG printf(" elem_size_bytes = words * 8 = %u; block_size %u\n", elem_size_bytes, block_size); #endif #ifdef FPA_DEBUG int block = 0; printf(" %% Filling Pool %u with %u blocks of %u bytes %u words\n", pool, elem_num, elem_size_bytes, elem_size_words); #endif // memory = malloc(bytes, M_DEVBUF, M_NOWAIT | M_ZERO); memory = contigmalloc(bytes, M_DEVBUF, M_NOWAIT | M_ZERO, 0, 0x20000000, OCTEON_FPA_POOL_ALIGNMENT, 0); if (memory == NULL) { printf(" %% FPA pool %u could not be filled with %u bytes\n", pool, bytes); return; } /* * Forward Align allocated mem to needed alignment. Don't worry about growth, we * already preallocated extra */ #ifdef FPA_DEBUG printf(" %% Huge MemBlock %p Bytes %u\n", memory, bytes); #endif memory = (void *) OCTEON_ALIGN(memory); #ifdef FPA_DEBUG_TERSE printf("FPA fill: %u Count: %u SizeBytes: %u SizeBytesAligned: %u 1st: %p = %p\n", pool, elem_num, elem_size_bytes, block_size, memory, (void *)(intptr_t)OCTEON_PTR2PHYS(memory)); #endif // memory = (void *) ((((u_int) memory / OCTEON_FPA_POOL_ALIGNMENT) + 1) * OCTEON_FPA_POOL_ALIGNMENT); while (elem_num--) { #ifdef FPA_DEBUG if (((elems - elem_num) < 4) || (elem_num < 4)) printf(" %% Block %d: %p Phys %p Bytes %u\n", block, memory, (void *)(intptr_t)OCTEON_PTR2PHYS(memory), elem_size_bytes); block++; #endif octeon_fpa_free(memory, pool, 0); memory = (void *) (((u_long) memory) + block_size); } }