/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2004-2011 Emulex. All rights reserved.
* Use is subject to license terms.
*/
#include <emlxs.h>
/* #define EMLXS_POOL_DEBUG */
extern int32_t
{
int32_t i;
/* Allocate the fc_table */
"fc_table buffer.");
goto failed;
}
/* Prepare the memory pools */
for (i = 0; i < FC_MAX_SEG; i++) {
switch (i) {
case MEM_NLP:
break;
case MEM_IOCB:
break;
case MEM_MBOX:
break;
case MEM_BPL:
continue;
}
break;
case MEM_BUF:
/* These are the unsolicited ELS buffers. */
break;
case MEM_IPBUF:
/* These are the unsolicited IP buffers. */
continue;
}
seg->fc_lo_water = 0;
break;
case MEM_CTBUF:
/* These are the unsolicited CT buffers. */
break;
#ifdef SFCT_SUPPORT
case MEM_FCTBUF:
/* These are the unsolicited FCT buffers. */
continue;
}
seg->fc_lo_water = 0;
break;
#endif /* SFCT_SUPPORT */
default:
continue;
}
if (seg->fc_memsize == 0) {
continue;
}
"%s: count=%d size=%d flags=%x lo=%d hi=%d",
seg->fc_hi_water);
goto failed;
}
}
/* If SLI3 and MEM_BPL pool is static */
/*
* Allocate and Initialize bpl_table
* This is for increased performance.
*/
"BPL table buffer.");
goto failed;
}
}
}
return (1);
(void) emlxs_mem_free_buffer(hba);
return (0);
} /* emlxs_mem_alloc_buffer() */
/*
* emlxs_mem_free_buffer
*
* and TGTM resource.
*/
extern int
{
int32_t j;
for (j = 0; j < hba->chan_count; j++) {
/* Flush the ring */
}
/* free the mapped address match area for each ring */
for (j = 0; j < MAX_RINGS; j++) {
addr = 0;
if ((j == hba->channel_els) ||
(j == hba->channel_ct) ||
#ifdef SFCT_SUPPORT
(j == hba->CHANNEL_FCT) ||
#endif /* SFCT_SUPPORT */
(j == hba->channel_ip)) {
}
if (j == hba->channel_els) {
MEM_ELSBUF, (void *)mp);
} else if (j == hba->channel_ct) {
} else if (j == hba->channel_ip) {
}
#ifdef SFCT_SUPPORT
else if (j == hba->CHANNEL_FCT) {
MEM_FCTBUF, (void *)mp);
}
#endif /* SFCT_SUPPORT */
}
}
}
}
}
}
/* Free the nodes */
for (j = 0; j < MAX_VPORTS; j++) {
if (vport->node_count) {
}
}
/* Make sure the mailbox queue is empty */
}
/* Return MEM_BPLs to their pool */
}
}
/* Free the memory segments */
for (j = 0; j < FC_MAX_SEG; j++) {
}
return (0);
} /* emlxs_mem_free_buffer() */
/* Must hold EMLXS_MEMGET_LOCK when calling */
static uint32_t
{
uint32_t i;
if (seg->fc_memsize == 0) {
return (0);
}
return (0);
}
if (count == 0) {
return (0);
}
}
/* Check for initial allocation */
"%s alloc:%d n=%d s=%d f=%x l=%d,%d,%d "
"f=%d:%d",
}
goto vmem_pool;
}
/* dma_pool */
for (i = 0; i < count; i++) {
"%s: count=%d size=%d",
goto done;
}
"%s: count=%d size=%d",
/* Free the mp object */
goto done;
}
#ifdef SFCT_SUPPORT
/* Free the DMA memory itself */
/* Free the mp object */
goto done;
}
}
#endif /* SFCT_SUPPORT */
/* Add the buffer desc to the tail of the pool freelist */
} else {
seg->fc_memget_cnt++;
}
seg->fc_numblks++;
}
goto done;
for (i = 0; i < count; i++) {
"%s: count=%d size=%d",
goto done;
}
/* Add the buffer to the tail of the pool freelist */
} else {
seg->fc_memget_cnt++;
}
seg->fc_numblks++;
}
done:
} /* emlxs_mem_pool_alloc() */
/* Must hold EMLXS_MEMGET_LOCK & EMLXS_MEMPUT_LOCK when calling */
static void
{
if ((seg->fc_memsize == 0) ||
(seg->fc_numblks == 0) ||
(count == 0)) {
return;
}
/* Check max count */
}
/* Move memput list to memget list */
if (seg->fc_memput_ptr) {
} else {
}
seg->fc_memput_cnt = 0;
}
/* Check for final deallocation */
"%s free:%d n=%d s=%d f=%x l=%d,%d,%d "
"f=%d:%d",
}
goto vmem_pool;
}
/* Free memory associated with all buffers on get buffer pool */
/* Remove buffer from list */
seg->fc_memget_cnt = 0;
} else {
seg->fc_memget_cnt--;
}
#ifdef SFCT_SUPPORT
}
#endif /* SFCT_SUPPORT */
/* Free the DMA memory itself */
/* Free the handle */
seg->fc_numblks--;
count--;
}
return;
/* Free memory associated with all buffers on get buffer pool */
/* Remove buffer from list */
seg->fc_memget_cnt = 0;
} else {
seg->fc_memget_cnt--;
}
/* Free the Virtual memory itself */
seg->fc_numblks--;
count--;
}
return;
} /* emlxs_mem_pool_free() */
extern uint32_t
{
if (seg->fc_memsize == 0) {
return (0);
}
/* Sanity check hi > lo */
}
/* If dynamic pools are disabled, then force pool to max level */
}
/* If pool is dynamic, then fc_step must be >0 */
/* Otherwise, fc_step must be 0 */
}
} else {
}
seg->fc_numblks = 0;
seg->fc_total_memsize = 0;
return (seg->fc_numblks);
} /* emlxs_mem_pool_create() */
extern void
{
if (seg->fc_memsize == 0) {
return;
}
/* Leave FC_MEMSEG_PUT_ENABLED set for now */
/* Try to free all objects */
if (seg->fc_numblks) {
"mem_pool_destroy: %s leak detected: "
"%d objects still allocated.",
} else {
"mem_pool_destroy: %s destroyed.",
/* Clear all */
}
return;
} /* emlxs_mem_pool_destroy() */
extern void
{
return;
}
goto done;
}
#ifdef EMLXS_POOL_DEBUG
"%s clean: n=%d s=%d f=%x l=%d,%d,%d "
"f=%d:%d",
#endif /* EMLXS_POOL_DEBUG */
/* Calculatge current free count */
/* Reset fc_low value to current free count */
/* Return if pool is already at lo water mark */
goto done;
}
/* Return if there is nothing to clean */
if ((free_count == 0) ||
(clean_count <= 1)) {
goto done;
}
/* Calculate a 3 percent free pad count (1 being minimum) */
} else {
free_pad = 1;
}
/* Return if fc_low is below pool free pad */
if (clean_count <= free_pad) {
goto done;
}
clean_count -= free_pad;
/* clean_count can't exceed minimum pool levels */
}
done:
"%s update: n=%d->%d s=%d f=%x l=%d,%d,%d "
"f=%d:%d",
}
return;
} /* emlxs_mem_pool_clean() */
extern void *
{
/* Check if memory pool is GET enabled */
return (NULL);
}
/* If no entries on memget list, then check memput list */
if (!seg->fc_memget_ptr) {
if (seg->fc_memput_ptr) {
/*
* Move list from memput to memget
*/
seg->fc_memput_cnt = 0;
}
}
/* If no entries on memget list, then pool is empty */
/* Try to allocate more if pool is dynamic */
if (!seg->fc_memget_ptr &&
}
/* If no entries on memget list, then pool is empty */
if (!seg->fc_memget_ptr) {
return (NULL);
}
/* Remove an entry from the get list */
seg->fc_memget_cnt = 0;
} else {
seg->fc_memget_cnt--;
}
/* Initialize buffer */
} else {
}
/* Set fc_low if pool is dynamic */
}
}
return (bp);
} /* emlxs_mem_pool_get() */
extern void
{
/* Free the pool object */
/* Check if memory pool is PUT enabled */
return;
}
/* Check if buffer was just freed */
return;
}
/* Validate DMA buffer */
"mem_pool_put: %s invalid: mp=%p " \
return;
}
}
/* Release buffer to the end of the memput list */
} else {
seg->fc_memput_cnt++;
}
/* This is for late PUT's after an initial */
/* emlxs_mem_pool_destroy call */
}
return;
} /* emlxs_mem_pool_put() */
extern MATCHMAP *
{
"MEM_BUF_ALLOC buffer.");
return (NULL);
}
"MEM_BUF_ALLOC DMA buffer.");
/* Free the mp object */
return (0);
}
return (mp);
} /* emlxs_mem_buf_alloc() */
extern void
{
return;
}
return;
} /* emlxs_mem_buf_free() */
extern void *
{
void *bp;
if (seg_id >= FC_MAX_SEG) {
"mem_get: Invalid segment id = %d",
seg_id);
return (NULL);
}
/* Alloc a buffer from the pool */
if (bp) {
switch (seg_id) {
case MEM_MBOX:
break;
case MEM_IOCB:
break;
case MEM_NLP:
break;
}
}
return (bp);
} /* emlxs_mem_get() */
extern void
{
if (seg_id >= FC_MAX_SEG) {
"mem_put: Invalid segment id = %d: bp=%p",
return;
}
/* Verify buffer */
switch (seg_id) {
case MEM_MBOX:
return;
}
break;
case MEM_IOCB:
return;
}
/* Any IOCBQ with a packet attached did not come */
/* from our pool */
return;
}
break;
case MEM_NLP:
return;
}
break;
default:
return;
}
return;
}
return;
}
break;
}
/* Free a buffer to the pool */
return;
} /* emlxs_mem_put() */
/*
* Look up the virtual address given a mapped address
*/
/* SLI3 */
extern MATCHMAP *
{
prev = 0;
while (mp) {
if (prev == 0) {
} else {
}
}
return (mp);
}
}
"ELS Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
prev = 0;
while (mp) {
if (prev == 0) {
} else {
}
}
return (mp);
}
}
"CT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
prev = 0;
while (mp) {
if (prev == 0) {
} else {
}
}
return (mp);
}
}
"IP Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
#ifdef SFCT_SUPPORT
prev = 0;
while (mp) {
if (prev == 0) {
} else {
}
}
return (mp);
}
}
"FCT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
#endif /* SFCT_SUPPORT */
}
return (0);
} /* emlxs_mem_get_vaddr() */
/*
* Given a virtual address bp, generate the physical mapped address and
* place it where addr points to. Save the address pair for lookup later.
*/
/* SLI3 */
extern void
{
/*
* Update slot fc_mpon points to then bump it
* fc_mpoff is pointer head of the list.
* fc_mpon is pointer tail of the list.
*/
} else {
(void *)mp;
}
/* return mapped address */
/* return mapped address */
} else {
/* return mapped address */
}
/*
* Update slot fc_mpon points to then bump it
* fc_mpoff is pointer head of the list.
* fc_mpon is pointer tail of the list.
*/
} else {
(void *)mp;
}
/* return mapped address */
/* return mapped address */
} else {
/* return mapped address */
}
/*
* Update slot fc_mpon points to then bump it
* fc_mpoff is pointer head of the list.
* fc_mpon is pointer tail of the list.
*/
} else {
(void *)mp;
}
/* return mapped address */
} else {
}
#ifdef SFCT_SUPPORT
/*
* Update slot fc_mpon points to then bump it
* fc_mpoff is pointer head of the list.
* fc_mpon is pointer tail of the list.
*/
} else {
(void *)mp;
}
/* return mapped address */
/* return mapped address */
} else {
/* return mapped address */
}
#endif /* SFCT_SUPPORT */
}
} /* emlxs_mem_map_vaddr() */
/* SLI3 */
{
/* Get the system's page size in a DDI-compliant way. */
"Unable to alloc HBQ.");
return (ENOMEM);
}
}
return (0);
} /* emlxs_hbq_alloc() */