/*
functions for managing Chip per-connection context
*/
#include "context.h"
#include "command.h"
#include "cdu_def.h"
#include "bd_chain.h"
/* returns a pionter to a connections chip context*/
/* calculate which context page the CID is on*/
/* calculate at what offset inside the page CID is on*/
/* now goto page,off */
ret = (void*)((char*)pdev->vars.context_cdu_virt_addr_table[page] + (pdev->params.context_line_size * off));
/* warrning, this assumes context line size is in chars, need to check!!!*/
return ret;
}
/* same as above but returns phys address in 64 bit pointer */
/* calculate which context page the CID is on*/
/* calculate at what offset inside the page CID is on*/
/* now goto page,off */
ret = (pdev->vars.context_cdu_phys_addr_table[page].as_u64 + (pdev->params.context_line_size * off));
/* warrning, this assumes context line size is in chars, need to check!!!*/
return ret;
}
{
int offset = 0 ;
/* sanity */
{
DbgBreakMsg("Invalid Parameters") ;
return LM_STATUS_INVALID_PARAMETER ;
}
{
return LM_STATUS_FAILURE;
}
/* init value for searcher key */
// TODO: for now a fixed key, need to change at runtime
/* Microsoft's example key */
// *(u32_t *)(&hash_info->searcher_key[0]) = 0xda565a6d;
// *(u32_t *)(&hash_info->searcher_key[4]) = 0xc20e5b25;
// *(u32_t *)(&hash_info->searcher_key[8]) = 0x3d256741;
// *(u32_t *)(&hash_info->searcher_key[12]) = 0xb08fa343;
// *(u32_t *)(&hash_info->searcher_key[16]) = 0xcb2bcad0;
// *(u32_t *)(&hash_info->searcher_key[20]) = 0xb4307bae;
// *(u32_t *)(&hash_info->searcher_key[24]) = 0xa32dcb77;
// *(u32_t *)(&hash_info->searcher_key[28]) = 0x0cf23080;
// *(u32_t *)(&hash_info->searcher_key[32]) = 0x3bb7426a;
// *(u32_t *)(&hash_info->searcher_key[36]) = 0xfa01acbe;
/* init searcher_key_bits array */
{
int j,k;
for (j= 0; j < 4; j++)
{
for (k = 0; k < 8; k++)
{
}
}
}
/* init value for num hash bits */
return LM_STATUS_SUCCESS ;
}
{
{
return LM_STATUS_INVALID_PARAMETER ;
}
/* searcher is defined with per-function #connections */
{
return LM_STATUS_INVALID_PARAMETER ;
}
/* allocate searcher mirror hash table */
{
return LM_STATUS_RESOURCE ;
}
return LM_STATUS_SUCCESS ;
}
{
int i = 0;
{
return LM_STATUS_INVALID_PARAMETER;
}
{
return LM_STATUS_INVALID_PARAMETER;
}
{
}
return LM_STATUS_SUCCESS;
}
{
u32_t i,j;
{
DbgBreakIf(!pdev);
return LM_STATUS_INVALID_PARAMETER;
}
{
return LM_STATUS_INVALID_PARAMETER;
}
context->proto_end [TOE_CONNECTION_TYPE] = context->proto_start[TOE_CONNECTION_TYPE] + pdev->params.max_func_toe_cons - 1;
context->proto_end [RDMA_CONNECTION_TYPE] = context->proto_start[RDMA_CONNECTION_TYPE] + pdev->params.max_func_rdma_cons - 1;
context->proto_end [ISCSI_CONNECTION_TYPE] = context->proto_start[ISCSI_CONNECTION_TYPE] + pdev->params.max_func_iscsi_cons - 1;
context->proto_end [FCOE_CONNECTION_TYPE] = context->proto_start[FCOE_CONNECTION_TYPE] + pdev->params.max_func_fcoe_cons - 1;
{
return LM_STATUS_INVALID_PARAMETER;
}
/* zero cookies and populate the free lists */
{
{
lm_init_cid_resc(pdev, j);
}
/* set the first free item if max_func_XX_cons > 0 */
}
else
{
context->proto_ffree[i] = 0;
}
context->proto_pending[i] = 0;
/* put 0 (end of freelist in the last entry for the proto */
}
//The ETH cid doorbell space was remapped just fixing the pointers.
for (j = context->proto_start[ETH_CONNECTION_TYPE]; j <= context->proto_end[ETH_CONNECTION_TYPE]; j++)
{
#ifdef VF_INVOLVED
if (IS_CHANNEL_VFDEV(pdev)) {
(volatile void *)((u8_t*)pdev->vars.mapped_bar_addr[BAR_0] + j*lm_vf_get_doorbell_size(pdev) + VF_BAR0_DB_OFFSET);
#ifdef __SunOS
#endif /* __SunOS */
} else
#endif /* VF_INVOLVED */
{
#ifdef __SunOS
#endif /* __SunOS */
}
}
return lm_setup_searcher_hash_info(pdev) ;
}
/* context pool initializer */
{
DbgBreakIf(!pdev);
return LM_STATUS_INVALID_PARAMETER ;
}
/* must not be called if allready initialized */
{
return LM_STATUS_FAILURE ;
}
/* number of context is per-function, the cdu has a per-port register that can be set to be higher than the max_func_connections, but
* the amount of memory actually allocated for the CDU matches max_func_connections. */
/* allocate context info and cookie array */
{
return LM_STATUS_RESOURCE ;
}
/* allocate list entries */
{
return LM_STATUS_RESOURCE ;
}
/* initilize the lock */
/* put the context where it belongs */
/* init searcher hash info */
return lm_alloc_searcher_hash_info(pdev);
/* return success */
}
/* context pool release function */
u32_t i, j;
/* must only be called if initialized */
/* first make a copy and kill the original refference */
/* free context cookie array
sanity check: scan it and make sure it is empty */
{
for (j = 0; j < MAX_PROTO; j++)
{
}
/* NirV: can't call from here, context_info is NULL */
/*DbgBreakIf(lm_sp_req_manager_shutdown(pdev, i) != LM_STATUS_SUCCESS);*/
}
/* mm_free_mem(context->array); */
/* sanity check - searcher mirror hash must be empty */
/* de-initilize the lock? if in debug mode we can leave it taken to chatch errors */
/* free context info */
/* mm_free_mem(context); */
/* return success */
}
{
u16_t i = 0;
u16_t j = 0;
/* prepare input string */
{
}
else
{
}
/* prepare searcher_in_str_bits from in_str */
for (i = 0; i < in_bits; i++)
{
/* 0x80 - the leftmost bit. */
}
/* calc ToeplitzHash */
for (i = 0; i < 32; i++)
{
u8_t h = 0;
for (j = 0; j < in_bits; j++)
{
h ^= key_bits[i+j] & in_str_bits[j];
}
}
return result;
}
/* assumption: CID lock NOT taken by caller */
lm_status_t lm_searcher_mirror_hash_insert(struct _lm_device_t *pdev, u32_t cid, lm_4tuple_t *tuple)
{
/* take spinlock */
/* calc hash val */
/* take only num_hash_bits LSBs */
/* init num_hash_bits in the searcher: if the h_val is all FFFFs - set it to 0 */
h_val = 0;
}
/* get the hash entry */
/* start the alg. to find if there is a place available in that entry */
/* tempDepthIpv4 = max ( depthIpv4(H), roundup(tempIpv4/2) ) */
}
/* each hash entry has SRC_HASH_DEPTH_TH available places.
* each place can contain 1 ipv6 connection or 2 ipv4 connections */
DbgBreakMsg("Reached searcher hash limit\n");
} else {
/* for debug, save the max depth reached */
}
/* remeber the IP type and h_val to know where and how much
* to decrease upon CID recycling */
}
/* release spinlock */
return lm_status;
}
/* assumption: CID lock NOT taken by caller */
{
/* take spinlock */
/* i.e lm_searcher_mirror_hash_insert was not called for this cid */
"not removing CID %d from SRC hash (hash insert was not called for this cid)\n"
,cid);
/* release spinlock */
return;
}
hash_entry->num_ipv6--;
}
else
{
hash_entry->num_ipv4--;
{
}
}
/* for debug */
/* clear the entry of the context */
/* release spinlock */
}
/* allocate a free context by type
returns CID in the out_cid param
return LM_STATUS_SUCCESS for available cid
LM_STATUS_RESOURCE if no cids are available
LM_STATUS_PENDING if there is a pending cfc-delete cid
takes the list spinlock */
{
DbgBreakIf(!out_cid) ;
DbgBreakIf(!pdev);
DbgBreakIf(!cookie);
return LM_STATUS_INVALID_PARAMETER ;
}
*out_cid = 0;
/* take spinlock */
// if the free list is empty return error
if ((pdev->params.cid_allocation_mode == LM_CID_ALLOC_REGULAR) || (context->proto_pending[type] == 0)) {
// if the free list is empty AND the pending list is empty return error OR
// the free list is empty and we're in the regular allocating mode
}
else
{
/* pop pendinglist entry and place cookie */
/* we only use the cid to connect between the pending connection and this cid, but
* the connection can't know of this cid before it is acually freed, for this reason
* we return cid = 0, which means, 'pending' */
/* make sure the first cid previous is set correctly*/
if (cid) {
}
}
}else{
/* pop freelist entry and place cookie*/
}
if(LM_STATUS_SUCCESS == lm_status)
{
//If the function allocated a new free CID, (not pending) the function MmMapIoSpace will be called
//to map the specific physical cid doorbell space to a virtual address.
//In case of a pending CID, the map doorbell space will not be remapped. The pending CID will use
//the old mapping cid doorbell space.
#ifdef __SunOS
#ifdef VF_INVOLVED
#else /* !VF_INVOLVED */
(volatile void *)mm_map_io_space_solaris(pdev,
(cid * LM_DQ_CID_SIZE),
#endif /* VF_INVOLVED */
#else /* !__SunOS */
#ifdef VF_INVOLVED
#else /* !VF_INVOLVED */
#endif /* VF_INVOLVED */
#endif /* __SunOS */
// If the mapping failed we will return LM_STATUS_RESOURCE and return the cid resource.
{
DbgMessage(pdev, FATAL, "lm_allocate_cid: mm_map_io_space failed. address low=%d address high=%d\n", phy_addr.as_u32.low,phy_addr.as_u32.high );
/* take spinlock */
/* return the cid to free list */
*out_cid =0;
}
}
return lm_status;
}
{
{
DbgBreakIf(!pdev);
if (!flr_in_progress)
{
}
else
{
DbgMessage(pdev, FATAL, "lm_cfc_delete: invalid %d for cid=%d\n", pdev->context_info->array[cid].invalid,cid);
{
DbgBreakIf(1);
}
}
}
{
}
else
{
/* use common bit */
cid,
0 );
}
return;
}
/* free a context
takes the list spinlock */
{
DbgBreakIf(!pdev);
return;
}
{
}
if (notify_fw)
{
/* Vladz: Added in order to optimize CID release in DOS */
#else
delay_time = 0;
#endif
recycle_now = FALSE;
/* add the cid to proto-pending: it'll be freed soon when cfc-delete is done */
if (curr_cid != 0)
{
}
}
else
{
recycle_now = TRUE;
/* If we're recylcing now, there's no point in adding it to the pending list */
}
if (recycle_now) {
}
else
{
if (type == TOE_CONNECTION_TYPE)
{
}
else
{
}
}
}
u32_t i;
{
DbgBreakIf(!pdev);
return;
}
for (i=0; i < MAX_PROTO; i++ ) {
{
type = i;
break;
}
}
{
return;
}
/* take spinlock */
#ifdef _VBD_
{
pdev->vars.last_recycling_timestamp = mm_get_current_time(pdev) * 1000 / pdev->ofld_info.l4_params.ticks_per_second; /*time in ms*/
}
#endif
/* If no cookie is waiting on this cid extract from pending and push enrty into the freelist */
/* take the cid out of the proto_pending cids if it's there */
if (prev_cid) {
}
if (next_cid) {
}
DbgBreakIf(prev_cid != 0);
}
/* add to free list */
//free virtual memory for cids not in use.
#ifndef VF_INVOLVED
mm_unmap_io_space(pdev,(void *)pdev->context_info->array[cid].cid_resc.mapped_cid_bar_addr, LM_DQ_CID_SIZE);
#endif
}
else
{
/* No need to extract from pending - it's not there. */
/* NirV: we still can't set cid_resc.cid_pending to false, */
/* will be possible only in the callback */
}
/* time to clear the active bit (cdu-validation ) we can only do this after cfc-delete has completed, at this point, invalid==LM_CONTEXT_VALID */
/* rlease spinlock */
/* call here the cid recycle callback of that
protocol type if such cb exists*/
pdev->cid_recycled_callbacks[type](pdev, pdev->context_info->array[cid].cid_resc.cookies[type], cid);
}
return;
}
/* lookup the protocol cookie for a given CID
does not take a lock
will DbgBreakIf( if the CID is not allocated. */
{
DbgBreakIf(!pdev);
}
{
return NULL;
}
/* if the cid is pending, return null */
{
return NULL;
}
}
/* lookup the protocol cid_resc for a given CID
does not take a lock
will DbgBreakIf( if the CID is not allocated */
{
DbgBreakIf(!pdev);
}
}
{
u8_t i;
return type;
}
for (i=0; i < MAX_PROTO; i++ ) {
type = i;
break;
}
}
return type;
}
{
{
DbgBreakIf(!pdev);
DbgBreakIf(sw_cid < PFDEV(pdev)->context_info->proto_start[ETH_CONNECTION_TYPE]); /* first legal NIC CID */
DbgBreakIf(sw_cid > PFDEV(pdev)->context_info->proto_end[ETH_CONNECTION_TYPE]); /* last legal NIC CID */
}
/* calculate the cdu-validation value. */
}
{
{
return LM_STATUS_INVALID_PARAMETER;
}
/* take spinlock */
{
return LM_STATUS_INVALID_PARAMETER;
}
/* rlease spinlock */
return lm_status;
}
{
{
return LM_STATUS_INVALID_PARAMETER;
}
/* take spinlock */
{
return LM_STATUS_INVALID_PARAMETER;
}
{
proto_idx++;
}
/* rlease spinlock */
{
/* We'll call lm_map_cid_to_proto() to compute the appropriate type that was associated with that CID,
* this is done to avoid assert upon race scenarios in which the last cookie resource that gets freed is not from the type of the CID */
}
return LM_STATUS_SUCCESS;
}
)
{
{
return NULL;
}
{
return NULL;
}
return &cid_resc->sp_req_mgr;
}
)
{
{
return LM_CID_STATE_ERROR;
}
{
return LM_CID_STATE_ERROR;
}
}
)
{
{
return LM_STATUS_INVALID_PARAMETER;
}
/* take spinlock */
{
return LM_STATUS_INVALID_PARAMETER;
}
/* rlease spinlock */
return LM_STATUS_SUCCESS;
}
/**
* sets the CDU validation data to be valid for a given cid
*
* @param pdev - the physical device handle
* @param cid - the context of this cid will be initialized with the cdu validataion data
*
* @return lm_status_t
*/
{
u8_t *cdu_reserved = NULL; /* Pointer to the actual location of cdu_reserved field according to protocol */
u8_t *cdu_usage = NULL; /* Pointer to the actual location of cdu_usage field according to protocol */
if (!context) {
return LM_STATUS_FAILURE;
}
switch (proto_type) {
case TOE_CONNECTION_TYPE:
break;
case ETH_CONNECTION_TYPE:
break;
case ISCSI_CONNECTION_TYPE:
break;
case FCOE_CONNECTION_TYPE:
break;
default:
break;
}
if (cdu_reserved && cdu_usage) {
if (invalidate) {
} else {
}
}
return lm_status;
}
{
return LM_STATUS_SUCCESS;
}
{
{
return LM_STATUS_INVALID_PARAMETER;
}
return LM_STATUS_SUCCESS;
}
{
{
return LM_CON_STATE_CLOSE;
}
}