1*d14abf15SRobert Mustacchi 
2*d14abf15SRobert Mustacchi /*
3*d14abf15SRobert Mustacchi functions for managing Chip per-connection context
4*d14abf15SRobert Mustacchi */
5*d14abf15SRobert Mustacchi #include "context.h"
6*d14abf15SRobert Mustacchi #include "command.h"
7*d14abf15SRobert Mustacchi #include "cdu_def.h"
8*d14abf15SRobert Mustacchi #include "bd_chain.h"
9*d14abf15SRobert Mustacchi 
10*d14abf15SRobert Mustacchi /* returns a pionter to a connections chip context*/
lm_get_context(struct _lm_device_t * pdev,u32_t cid)11*d14abf15SRobert Mustacchi void * lm_get_context(struct _lm_device_t *pdev, u32_t cid){
12*d14abf15SRobert Mustacchi 
13*d14abf15SRobert Mustacchi     void * ret = NULL;
14*d14abf15SRobert Mustacchi     u32_t page,off;
15*d14abf15SRobert Mustacchi 
16*d14abf15SRobert Mustacchi     DbgBreakIf(cid > pdev->params.max_func_connections);
17*d14abf15SRobert Mustacchi     DbgBreakIf(pdev->context_info->array[cid].invalid != LM_CONTEXT_VALID);
18*d14abf15SRobert Mustacchi 
19*d14abf15SRobert Mustacchi     /* calculate which context page the CID is on*/
20*d14abf15SRobert Mustacchi     page = cid / (pdev->params.num_context_in_page);
21*d14abf15SRobert Mustacchi 
22*d14abf15SRobert Mustacchi     /* calculate at what offset inside the page CID is on*/
23*d14abf15SRobert Mustacchi     off = cid % (pdev->params.num_context_in_page);
24*d14abf15SRobert Mustacchi 
25*d14abf15SRobert Mustacchi     /* now goto page,off */
26*d14abf15SRobert Mustacchi     ret = (void*)((char*)pdev->vars.context_cdu_virt_addr_table[page] + (pdev->params.context_line_size * off));
27*d14abf15SRobert Mustacchi     /* warrning, this assumes context line size is in chars, need to check!!!*/
28*d14abf15SRobert Mustacchi 
29*d14abf15SRobert Mustacchi     return ret;
30*d14abf15SRobert Mustacchi }
31*d14abf15SRobert Mustacchi 
32*d14abf15SRobert Mustacchi /* same as above but returns phys address in 64 bit pointer */
lm_get_context_phys(struct _lm_device_t * pdev,u32_t cid)33*d14abf15SRobert Mustacchi u64_t lm_get_context_phys(struct _lm_device_t *pdev, u32_t cid){
34*d14abf15SRobert Mustacchi 
35*d14abf15SRobert Mustacchi     u64_t ret = 0;
36*d14abf15SRobert Mustacchi     u32_t page,off;
37*d14abf15SRobert Mustacchi 
38*d14abf15SRobert Mustacchi     DbgBreakIf(cid > pdev->params.max_func_connections);
39*d14abf15SRobert Mustacchi     DbgBreakIf(pdev->context_info->array[cid].invalid != LM_CONTEXT_VALID);
40*d14abf15SRobert Mustacchi 
41*d14abf15SRobert Mustacchi     /* calculate which context page the CID is on*/
42*d14abf15SRobert Mustacchi     page = cid / (pdev->params.num_context_in_page);
43*d14abf15SRobert Mustacchi 
44*d14abf15SRobert Mustacchi     /* calculate at what offset inside the page CID is on*/
45*d14abf15SRobert Mustacchi     off = cid % (pdev->params.num_context_in_page);
46*d14abf15SRobert Mustacchi 
47*d14abf15SRobert Mustacchi     /* now goto page,off */
48*d14abf15SRobert Mustacchi     ret = (pdev->vars.context_cdu_phys_addr_table[page].as_u64 + (pdev->params.context_line_size * off));
49*d14abf15SRobert Mustacchi     /* warrning, this assumes context line size is in chars, need to check!!!*/
50*d14abf15SRobert Mustacchi 
51*d14abf15SRobert Mustacchi     return ret;
52*d14abf15SRobert Mustacchi }
53*d14abf15SRobert Mustacchi 
54*d14abf15SRobert Mustacchi extern u32_t LOG2(u32_t v);
lm_setup_searcher_hash_info(struct _lm_device_t * pdev)55*d14abf15SRobert Mustacchi static lm_status_t lm_setup_searcher_hash_info(struct _lm_device_t *pdev)
56*d14abf15SRobert Mustacchi {
57*d14abf15SRobert Mustacchi     u32_t                    num_con    = 0 ;
58*d14abf15SRobert Mustacchi     u32_t                    alloc_size = 0 ;
59*d14abf15SRobert Mustacchi     lm_context_info_t*       context    = NULL;
60*d14abf15SRobert Mustacchi     lm_searcher_hash_info_t* hash_info  = NULL;
61*d14abf15SRobert Mustacchi     int                      offset     = 0 ;
62*d14abf15SRobert Mustacchi 
63*d14abf15SRobert Mustacchi     /* sanity */
64*d14abf15SRobert Mustacchi     if ( CHK_NULL(pdev) || CHK_NULL( pdev->context_info ) )
65*d14abf15SRobert Mustacchi     {
66*d14abf15SRobert Mustacchi         DbgBreakMsg("Invalid Parameters") ;
67*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER ;
68*d14abf15SRobert Mustacchi     }
69*d14abf15SRobert Mustacchi     context   = pdev->context_info;
70*d14abf15SRobert Mustacchi     hash_info = &context->searcher_hash;
71*d14abf15SRobert Mustacchi 
72*d14abf15SRobert Mustacchi     DbgBreakIf(!pdev->params.max_func_connections);
73*d14abf15SRobert Mustacchi 
74*d14abf15SRobert Mustacchi     if CHK_NULL( hash_info->searcher_table)
75*d14abf15SRobert Mustacchi     {
76*d14abf15SRobert Mustacchi         DbgBreakIf(!( hash_info->searcher_table));
77*d14abf15SRobert Mustacchi         return LM_STATUS_FAILURE;
78*d14abf15SRobert Mustacchi     }
79*d14abf15SRobert Mustacchi     num_con    = pdev->params.max_func_connections;
80*d14abf15SRobert Mustacchi     alloc_size = sizeof(lm_searcher_hash_entry_t) * num_con;
81*d14abf15SRobert Mustacchi     mm_mem_zero(hash_info->searcher_table, alloc_size);
82*d14abf15SRobert Mustacchi 
83*d14abf15SRobert Mustacchi     /* init value for searcher key */
84*d14abf15SRobert Mustacchi     // TODO: for now a fixed key, need to change at runtime
85*d14abf15SRobert Mustacchi     *(u32_t *)(&hash_info->searcher_key[0])  = 0x63285672;
86*d14abf15SRobert Mustacchi     *(u32_t *)(&hash_info->searcher_key[4])  = 0x24B8F2CC;
87*d14abf15SRobert Mustacchi     *(u32_t *)(&hash_info->searcher_key[8])  = 0x223AEF9B;
88*d14abf15SRobert Mustacchi     *(u32_t *)(&hash_info->searcher_key[12]) = 0x26001E3A;
89*d14abf15SRobert Mustacchi     *(u32_t *)(&hash_info->searcher_key[16]) = 0x7AE91116;
90*d14abf15SRobert Mustacchi     *(u32_t *)(&hash_info->searcher_key[20]) = 0x5CE5230B;
91*d14abf15SRobert Mustacchi     *(u32_t *)(&hash_info->searcher_key[24]) = 0x298D8ADF;
92*d14abf15SRobert Mustacchi     *(u32_t *)(&hash_info->searcher_key[28]) = 0x6EB0FF09;
93*d14abf15SRobert Mustacchi     *(u32_t *)(&hash_info->searcher_key[32]) = 0x1830F82F;
94*d14abf15SRobert Mustacchi     *(u32_t *)(&hash_info->searcher_key[36]) = 0x1E46BE7;
95*d14abf15SRobert Mustacchi 
96*d14abf15SRobert Mustacchi     /* Microsoft's example key */
97*d14abf15SRobert Mustacchi //      *(u32_t *)(&hash_info->searcher_key[0]) = 0xda565a6d;
98*d14abf15SRobert Mustacchi //      *(u32_t *)(&hash_info->searcher_key[4]) = 0xc20e5b25;
99*d14abf15SRobert Mustacchi //      *(u32_t *)(&hash_info->searcher_key[8]) = 0x3d256741;
100*d14abf15SRobert Mustacchi //      *(u32_t *)(&hash_info->searcher_key[12]) = 0xb08fa343;
101*d14abf15SRobert Mustacchi //      *(u32_t *)(&hash_info->searcher_key[16]) = 0xcb2bcad0;
102*d14abf15SRobert Mustacchi //      *(u32_t *)(&hash_info->searcher_key[20]) = 0xb4307bae;
103*d14abf15SRobert Mustacchi //      *(u32_t *)(&hash_info->searcher_key[24]) = 0xa32dcb77;
104*d14abf15SRobert Mustacchi //      *(u32_t *)(&hash_info->searcher_key[28]) = 0x0cf23080;
105*d14abf15SRobert Mustacchi //      *(u32_t *)(&hash_info->searcher_key[32]) = 0x3bb7426a;
106*d14abf15SRobert Mustacchi //      *(u32_t *)(&hash_info->searcher_key[36]) = 0xfa01acbe;
107*d14abf15SRobert Mustacchi 
108*d14abf15SRobert Mustacchi     /* init searcher_key_bits array */
109*d14abf15SRobert Mustacchi     for (offset = 0; offset < 10; offset++)
110*d14abf15SRobert Mustacchi     {
111*d14abf15SRobert Mustacchi         int j,k;
112*d14abf15SRobert Mustacchi         u32_t bitsOffset = 32*offset;
113*d14abf15SRobert Mustacchi         u8_t _byte;
114*d14abf15SRobert Mustacchi 
115*d14abf15SRobert Mustacchi         for (j= 0; j < 4; j++)
116*d14abf15SRobert Mustacchi         {
117*d14abf15SRobert Mustacchi             _byte  = (u8_t)((*(u32_t *)(&hash_info->searcher_key[offset*4]) >> (j*8)) & 0xff);
118*d14abf15SRobert Mustacchi             for (k = 0; k < 8; k++)
119*d14abf15SRobert Mustacchi             {
120*d14abf15SRobert Mustacchi                 hash_info->searcher_key_bits[bitsOffset+(j*8)+k] = ((_byte<<(k%8))& 0x80) ? 1 : 0;
121*d14abf15SRobert Mustacchi             }
122*d14abf15SRobert Mustacchi         }
123*d14abf15SRobert Mustacchi     }
124*d14abf15SRobert Mustacchi 
125*d14abf15SRobert Mustacchi     /* init value for num hash bits */
126*d14abf15SRobert Mustacchi     hash_info->num_hash_bits = (u8_t)LOG2(num_con);
127*d14abf15SRobert Mustacchi 
128*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS ;
129*d14abf15SRobert Mustacchi }
130*d14abf15SRobert Mustacchi 
lm_alloc_searcher_hash_info(struct _lm_device_t * pdev)131*d14abf15SRobert Mustacchi static lm_status_t lm_alloc_searcher_hash_info(struct _lm_device_t *pdev)
132*d14abf15SRobert Mustacchi {
133*d14abf15SRobert Mustacchi     u32_t                    num_con    = 0 ;
134*d14abf15SRobert Mustacchi     u32_t                    alloc_size = 0 ;
135*d14abf15SRobert Mustacchi     lm_searcher_hash_info_t* hash_info  = NULL ;
136*d14abf15SRobert Mustacchi     u8_t                     mm_cli_idx = 0 ;
137*d14abf15SRobert Mustacchi 
138*d14abf15SRobert Mustacchi     if CHK_NULL(pdev)
139*d14abf15SRobert Mustacchi     {
140*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER ;
141*d14abf15SRobert Mustacchi     }
142*d14abf15SRobert Mustacchi 
143*d14abf15SRobert Mustacchi     mm_cli_idx = LM_RESOURCE_COMMON;//!!DP mm_cli_idx_to_um_idx(LM_CLI_IDX_MAX);
144*d14abf15SRobert Mustacchi 
145*d14abf15SRobert Mustacchi     /* searcher is defined with per-function #connections */
146*d14abf15SRobert Mustacchi     num_con    = pdev->params.max_func_connections;
147*d14abf15SRobert Mustacchi     alloc_size = sizeof(lm_searcher_hash_entry_t) * num_con;
148*d14abf15SRobert Mustacchi 
149*d14abf15SRobert Mustacchi     hash_info  = &pdev->context_info->searcher_hash;
150*d14abf15SRobert Mustacchi 
151*d14abf15SRobert Mustacchi     if CHK_NULL(hash_info)
152*d14abf15SRobert Mustacchi     {
153*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER ;
154*d14abf15SRobert Mustacchi     }
155*d14abf15SRobert Mustacchi 
156*d14abf15SRobert Mustacchi     /* allocate searcher mirror hash table */
157*d14abf15SRobert Mustacchi     hash_info->searcher_table = mm_alloc_mem(pdev, alloc_size, mm_cli_idx);
158*d14abf15SRobert Mustacchi 
159*d14abf15SRobert Mustacchi     if CHK_NULL( hash_info->searcher_table )
160*d14abf15SRobert Mustacchi     {
161*d14abf15SRobert Mustacchi         DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
162*d14abf15SRobert Mustacchi         return  LM_STATUS_RESOURCE ;
163*d14abf15SRobert Mustacchi     }
164*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS ;
165*d14abf15SRobert Mustacchi }
166*d14abf15SRobert Mustacchi 
lm_init_cid_resc(struct _lm_device_t * pdev,u32_t cid)167*d14abf15SRobert Mustacchi lm_status_t lm_init_cid_resc(struct _lm_device_t *pdev, u32_t cid)
168*d14abf15SRobert Mustacchi {
169*d14abf15SRobert Mustacchi     lm_cid_resc_t *cid_resc = NULL;
170*d14abf15SRobert Mustacchi     int            i        = 0;
171*d14abf15SRobert Mustacchi 
172*d14abf15SRobert Mustacchi     if CHK_NULL(pdev)
173*d14abf15SRobert Mustacchi     {
174*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER;
175*d14abf15SRobert Mustacchi     }
176*d14abf15SRobert Mustacchi 
177*d14abf15SRobert Mustacchi     cid_resc = &pdev->context_info->array[cid].cid_resc;
178*d14abf15SRobert Mustacchi     if CHK_NULL(cid_resc)
179*d14abf15SRobert Mustacchi     {
180*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER;
181*d14abf15SRobert Mustacchi     }
182*d14abf15SRobert Mustacchi 
183*d14abf15SRobert Mustacchi     for (i = 0; i < ARRSIZE(cid_resc->cookies); i++)
184*d14abf15SRobert Mustacchi     {
185*d14abf15SRobert Mustacchi         cid_resc->cookies[i] = NULL;
186*d14abf15SRobert Mustacchi     }
187*d14abf15SRobert Mustacchi 
188*d14abf15SRobert Mustacchi     cid_resc->cid_pending = LM_CID_STATE_VALID;
189*d14abf15SRobert Mustacchi     lm_sp_req_manager_init(pdev, cid);
190*d14abf15SRobert Mustacchi 
191*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS;
192*d14abf15SRobert Mustacchi }
193*d14abf15SRobert Mustacchi 
lm_setup_context_pool(struct _lm_device_t * pdev)194*d14abf15SRobert Mustacchi lm_status_t lm_setup_context_pool(struct _lm_device_t *pdev)
195*d14abf15SRobert Mustacchi {
196*d14abf15SRobert Mustacchi     u32_t                     num_con         = 0;
197*d14abf15SRobert Mustacchi     lm_context_info_t *       context         = NULL ;
198*d14abf15SRobert Mustacchi     u32_t                     i,j;
199*d14abf15SRobert Mustacchi     struct lm_context_cookie* array           = NULL ;
200*d14abf15SRobert Mustacchi     lm_searcher_hash_entry_t* searcher_table  = NULL ;
201*d14abf15SRobert Mustacchi 
202*d14abf15SRobert Mustacchi     if CHK_NULL(pdev)
203*d14abf15SRobert Mustacchi     {
204*d14abf15SRobert Mustacchi         DbgBreakIf(!pdev);
205*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER;
206*d14abf15SRobert Mustacchi     }
207*d14abf15SRobert Mustacchi 
208*d14abf15SRobert Mustacchi     context = pdev->context_info;
209*d14abf15SRobert Mustacchi 
210*d14abf15SRobert Mustacchi     if CHK_NULL(context)
211*d14abf15SRobert Mustacchi     {
212*d14abf15SRobert Mustacchi         DbgBreakIf( context == NULL );
213*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER;
214*d14abf15SRobert Mustacchi     }
215*d14abf15SRobert Mustacchi 
216*d14abf15SRobert Mustacchi     num_con = pdev->params.max_func_connections;
217*d14abf15SRobert Mustacchi 
218*d14abf15SRobert Mustacchi     array           = context->array ;
219*d14abf15SRobert Mustacchi     searcher_table  = context->searcher_hash.searcher_table ;
220*d14abf15SRobert Mustacchi 
221*d14abf15SRobert Mustacchi     mm_mem_zero( context, sizeof(lm_context_info_t) ) ;
222*d14abf15SRobert Mustacchi 
223*d14abf15SRobert Mustacchi     context->array                        = array ;
224*d14abf15SRobert Mustacchi     context->searcher_hash.searcher_table = searcher_table ;
225*d14abf15SRobert Mustacchi 
226*d14abf15SRobert Mustacchi     context->proto_start[ETH_CONNECTION_TYPE]   = 0;
227*d14abf15SRobert Mustacchi     context->proto_end  [ETH_CONNECTION_TYPE]   = pdev->params.max_eth_including_vfs_conns - 1;
228*d14abf15SRobert Mustacchi     context->proto_start[TOE_CONNECTION_TYPE]   = context->proto_end  [ETH_CONNECTION_TYPE]   + 1;
229*d14abf15SRobert Mustacchi     context->proto_end  [TOE_CONNECTION_TYPE]   = context->proto_start[TOE_CONNECTION_TYPE]   + pdev->params.max_func_toe_cons - 1;
230*d14abf15SRobert Mustacchi     context->proto_start[RDMA_CONNECTION_TYPE]  = context->proto_end  [TOE_CONNECTION_TYPE]   + 1;
231*d14abf15SRobert Mustacchi     context->proto_end  [RDMA_CONNECTION_TYPE]  = context->proto_start[RDMA_CONNECTION_TYPE]  + pdev->params.max_func_rdma_cons - 1;
232*d14abf15SRobert Mustacchi     context->proto_start[ISCSI_CONNECTION_TYPE] = context->proto_end  [RDMA_CONNECTION_TYPE]  + 1;
233*d14abf15SRobert Mustacchi     context->proto_end  [ISCSI_CONNECTION_TYPE] = context->proto_start[ISCSI_CONNECTION_TYPE] + pdev->params.max_func_iscsi_cons - 1;
234*d14abf15SRobert Mustacchi     context->proto_start[FCOE_CONNECTION_TYPE]  = context->proto_end  [ISCSI_CONNECTION_TYPE] + 1;
235*d14abf15SRobert Mustacchi     context->proto_end  [FCOE_CONNECTION_TYPE]  = context->proto_start[FCOE_CONNECTION_TYPE]  + pdev->params.max_func_fcoe_cons - 1;
236*d14abf15SRobert Mustacchi     DbgBreakIf(context->proto_end[MAX_PROTO - 1] > pdev->params.max_func_connections -1);
237*d14abf15SRobert Mustacchi 
238*d14abf15SRobert Mustacchi     if CHK_NULL(context->array)
239*d14abf15SRobert Mustacchi     {
240*d14abf15SRobert Mustacchi         DbgBreakIf(!( context->array));
241*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER;
242*d14abf15SRobert Mustacchi     }
243*d14abf15SRobert Mustacchi 
244*d14abf15SRobert Mustacchi     mm_mem_zero(context->array, sizeof(struct lm_context_cookie)*num_con);
245*d14abf15SRobert Mustacchi 
246*d14abf15SRobert Mustacchi     ASSERT_STATIC( ARRSIZE(context->proto_start) == ARRSIZE(context->proto_end) );
247*d14abf15SRobert Mustacchi 
248*d14abf15SRobert Mustacchi     /* zero cookies and populate the free lists */
249*d14abf15SRobert Mustacchi     for (i = 0; i < ARRSIZE(context->proto_start); i++ )
250*d14abf15SRobert Mustacchi     {
251*d14abf15SRobert Mustacchi         for (j = context->proto_start[i]; j <= context->proto_end[i]; j++)
252*d14abf15SRobert Mustacchi         {
253*d14abf15SRobert Mustacchi             context->array[j].next    = j+1;
254*d14abf15SRobert Mustacchi             context->array[j].invalid = LM_CONTEXT_VALID;
255*d14abf15SRobert Mustacchi             context->array[j].ip_type = 0;
256*d14abf15SRobert Mustacchi             context->array[j].h_val   = 0;
257*d14abf15SRobert Mustacchi             lm_init_cid_resc(pdev, j);
258*d14abf15SRobert Mustacchi         }
259*d14abf15SRobert Mustacchi         /* set the first free item if max_func_XX_cons > 0 */
260*d14abf15SRobert Mustacchi         if (context->proto_start[i] <= context->proto_end[i]) {
261*d14abf15SRobert Mustacchi             context->proto_ffree[i] = context->proto_start[i];
262*d14abf15SRobert Mustacchi         }
263*d14abf15SRobert Mustacchi         else
264*d14abf15SRobert Mustacchi         {
265*d14abf15SRobert Mustacchi             context->proto_ffree[i] = 0;
266*d14abf15SRobert Mustacchi         }
267*d14abf15SRobert Mustacchi         context->proto_pending[i] = 0;
268*d14abf15SRobert Mustacchi         /* put 0 (end of freelist in the last entry for the proto */
269*d14abf15SRobert Mustacchi         context->array[context->proto_end[i]].next = 0;
270*d14abf15SRobert Mustacchi     }
271*d14abf15SRobert Mustacchi     //The ETH cid doorbell space was remapped just fixing the pointers.
272*d14abf15SRobert Mustacchi     for (j = context->proto_start[ETH_CONNECTION_TYPE]; j <= context->proto_end[ETH_CONNECTION_TYPE]; j++)
273*d14abf15SRobert Mustacchi     {
274*d14abf15SRobert Mustacchi #ifdef VF_INVOLVED
275*d14abf15SRobert Mustacchi         if (IS_CHANNEL_VFDEV(pdev)) {
276*d14abf15SRobert Mustacchi             context->array[j].cid_resc.mapped_cid_bar_addr =
277*d14abf15SRobert Mustacchi                 (volatile void *)((u8_t*)pdev->vars.mapped_bar_addr[BAR_0] + j*lm_vf_get_doorbell_size(pdev) + VF_BAR0_DB_OFFSET);
278*d14abf15SRobert Mustacchi #ifdef __SunOS
279*d14abf15SRobert Mustacchi             context->array[j].cid_resc.reg_handle = pdev->vars.reg_handle[BAR_0];
280*d14abf15SRobert Mustacchi #endif /* __SunOS */
281*d14abf15SRobert Mustacchi         } else
282*d14abf15SRobert Mustacchi #endif /* VF_INVOLVED */
283*d14abf15SRobert Mustacchi         {
284*d14abf15SRobert Mustacchi             context->array[j].cid_resc.mapped_cid_bar_addr =
285*d14abf15SRobert Mustacchi                 (volatile void *)((u8_t*)pdev->vars.mapped_bar_addr[BAR_1] + j*LM_DQ_CID_SIZE);
286*d14abf15SRobert Mustacchi #ifdef __SunOS
287*d14abf15SRobert Mustacchi             context->array[j].cid_resc.reg_handle = pdev->vars.reg_handle[BAR_1];
288*d14abf15SRobert Mustacchi #endif /* __SunOS */
289*d14abf15SRobert Mustacchi         }
290*d14abf15SRobert Mustacchi     }
291*d14abf15SRobert Mustacchi     return lm_setup_searcher_hash_info(pdev) ;
292*d14abf15SRobert Mustacchi }
293*d14abf15SRobert Mustacchi 
294*d14abf15SRobert Mustacchi /* context pool initializer */
lm_alloc_context_pool(struct _lm_device_t * pdev)295*d14abf15SRobert Mustacchi lm_status_t lm_alloc_context_pool(struct _lm_device_t *pdev){
296*d14abf15SRobert Mustacchi 
297*d14abf15SRobert Mustacchi     u32_t               num_con    = 0 ;
298*d14abf15SRobert Mustacchi     lm_context_info_t * context    = NULL ;
299*d14abf15SRobert Mustacchi     u8_t                mm_cli_idx = 0;
300*d14abf15SRobert Mustacchi 
301*d14abf15SRobert Mustacchi     if CHK_NULL(pdev)
302*d14abf15SRobert Mustacchi     {
303*d14abf15SRobert Mustacchi         DbgBreakIf(!pdev);
304*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER ;
305*d14abf15SRobert Mustacchi     }
306*d14abf15SRobert Mustacchi 
307*d14abf15SRobert Mustacchi     /* must not be called if allready initialized */
308*d14abf15SRobert Mustacchi     if ERR_IF( NULL != pdev->context_info )
309*d14abf15SRobert Mustacchi     {
310*d14abf15SRobert Mustacchi         DbgBreakIf( pdev->context_info != NULL ) ;
311*d14abf15SRobert Mustacchi         return LM_STATUS_FAILURE ;
312*d14abf15SRobert Mustacchi     }
313*d14abf15SRobert Mustacchi 
314*d14abf15SRobert Mustacchi     mm_cli_idx = LM_RESOURCE_COMMON;//!!DP mm_cli_idx_to_um_idx(LM_CLI_IDX_MAX);
315*d14abf15SRobert Mustacchi 
316*d14abf15SRobert Mustacchi     /* 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
317*d14abf15SRobert Mustacchi      * the amount of memory actually allocated for the CDU matches max_func_connections. */
318*d14abf15SRobert Mustacchi     num_con = pdev->params.max_func_connections ;
319*d14abf15SRobert Mustacchi 
320*d14abf15SRobert Mustacchi     /* allocate context info and cookie array */
321*d14abf15SRobert Mustacchi     context = mm_alloc_mem(pdev, sizeof(lm_context_info_t), mm_cli_idx);
322*d14abf15SRobert Mustacchi     if CHK_NULL(context)
323*d14abf15SRobert Mustacchi     {
324*d14abf15SRobert Mustacchi         DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
325*d14abf15SRobert Mustacchi         return LM_STATUS_RESOURCE ;
326*d14abf15SRobert Mustacchi     }
327*d14abf15SRobert Mustacchi 
328*d14abf15SRobert Mustacchi     /* allocate list entries */
329*d14abf15SRobert Mustacchi     context->array = mm_alloc_mem(pdev, sizeof(struct lm_context_cookie)*num_con, mm_cli_idx);
330*d14abf15SRobert Mustacchi     if CHK_NULL(context->array)
331*d14abf15SRobert Mustacchi     {
332*d14abf15SRobert Mustacchi         DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
333*d14abf15SRobert Mustacchi         return LM_STATUS_RESOURCE ;
334*d14abf15SRobert Mustacchi     }
335*d14abf15SRobert Mustacchi 
336*d14abf15SRobert Mustacchi     /* initilize the lock */
337*d14abf15SRobert Mustacchi 
338*d14abf15SRobert Mustacchi     /* put the context where it belongs */
339*d14abf15SRobert Mustacchi     pdev->context_info = context;
340*d14abf15SRobert Mustacchi 
341*d14abf15SRobert Mustacchi     /* init searcher hash info */
342*d14abf15SRobert Mustacchi     return lm_alloc_searcher_hash_info(pdev);
343*d14abf15SRobert Mustacchi     /* return success */
344*d14abf15SRobert Mustacchi }
345*d14abf15SRobert Mustacchi 
346*d14abf15SRobert Mustacchi /* context pool release function */
lm_release_context_pool(struct _lm_device_t * pdev)347*d14abf15SRobert Mustacchi void lm_release_context_pool(struct _lm_device_t *pdev){
348*d14abf15SRobert Mustacchi 
349*d14abf15SRobert Mustacchi     lm_context_info_t* context = NULL;
350*d14abf15SRobert Mustacchi     u32_t i, j;
351*d14abf15SRobert Mustacchi 
352*d14abf15SRobert Mustacchi     /* must only be called if initialized */
353*d14abf15SRobert Mustacchi     DbgBreakIf( pdev->context_info == NULL );
354*d14abf15SRobert Mustacchi 
355*d14abf15SRobert Mustacchi     /* first make a copy and kill the original refference */
356*d14abf15SRobert Mustacchi     context            = pdev->context_info;
357*d14abf15SRobert Mustacchi     pdev->context_info = NULL;
358*d14abf15SRobert Mustacchi 
359*d14abf15SRobert Mustacchi     /* free context cookie array
360*d14abf15SRobert Mustacchi        sanity check: scan it and make sure it is empty */
361*d14abf15SRobert Mustacchi     for (i=0; i<(pdev->params.max_func_connections); i++  )
362*d14abf15SRobert Mustacchi     {
363*d14abf15SRobert Mustacchi         for (j = 0; j < MAX_PROTO; j++)
364*d14abf15SRobert Mustacchi         {
365*d14abf15SRobert Mustacchi             DbgBreakIf( context->array[i].cid_resc.cookies[j] != NULL );
366*d14abf15SRobert Mustacchi         }
367*d14abf15SRobert Mustacchi 
368*d14abf15SRobert Mustacchi         /* NirV: can't call from here, context_info is NULL */
369*d14abf15SRobert Mustacchi         /*DbgBreakIf(lm_sp_req_manager_shutdown(pdev, i) != LM_STATUS_SUCCESS);*/
370*d14abf15SRobert Mustacchi     }
371*d14abf15SRobert Mustacchi     /* mm_free_mem(context->array); */
372*d14abf15SRobert Mustacchi 
373*d14abf15SRobert Mustacchi     /* sanity check - searcher mirror hash must be empty */
374*d14abf15SRobert Mustacchi     DbgBreakIf(context->searcher_hash.num_tuples);
375*d14abf15SRobert Mustacchi 
376*d14abf15SRobert Mustacchi     /* de-initilize the lock? if in debug mode we can leave it taken to chatch errors */
377*d14abf15SRobert Mustacchi 
378*d14abf15SRobert Mustacchi     /* free context info */
379*d14abf15SRobert Mustacchi     /* mm_free_mem(context); */
380*d14abf15SRobert Mustacchi 
381*d14abf15SRobert Mustacchi 
382*d14abf15SRobert Mustacchi     /* return success */
383*d14abf15SRobert Mustacchi 
384*d14abf15SRobert Mustacchi }
385*d14abf15SRobert Mustacchi 
_lm_searcher_mirror_hash_calc(lm_searcher_hash_info_t * hash_info,lm_4tuple_t * tuple)386*d14abf15SRobert Mustacchi static u32_t _lm_searcher_mirror_hash_calc(lm_searcher_hash_info_t *hash_info, lm_4tuple_t *tuple)
387*d14abf15SRobert Mustacchi {
388*d14abf15SRobert Mustacchi     u8_t  in_str[MAX_SEARCHER_IN_STR] = {0};
389*d14abf15SRobert Mustacchi     u8_t* in_str_bits                 = hash_info->searcher_in_str_bits;
390*d14abf15SRobert Mustacchi     u8_t* key_bits                    = hash_info->searcher_key_bits;
391*d14abf15SRobert Mustacchi     u32_t in_bits                     = 0;
392*d14abf15SRobert Mustacchi     u32_t result                      = 0;
393*d14abf15SRobert Mustacchi     u16_t i                           = 0;
394*d14abf15SRobert Mustacchi     u16_t j                           = 0;
395*d14abf15SRobert Mustacchi 
396*d14abf15SRobert Mustacchi     /* prepare input string */
397*d14abf15SRobert Mustacchi     if (tuple->ip_type == LM_IP_TYPE_V4)
398*d14abf15SRobert Mustacchi     {
399*d14abf15SRobert Mustacchi         *(u32_t *)(&in_str[0])  = HTON32(tuple->src_ip[0]);
400*d14abf15SRobert Mustacchi         *(u32_t *)(&in_str[4])  = HTON32(tuple->dst_ip[0]);
401*d14abf15SRobert Mustacchi         *(u16_t *)(&in_str[8])  = tuple->src_port;
402*d14abf15SRobert Mustacchi         *(u16_t *)(&in_str[10]) = tuple->dst_port;
403*d14abf15SRobert Mustacchi         in_bits = 12 * 8;
404*d14abf15SRobert Mustacchi     }
405*d14abf15SRobert Mustacchi     else
406*d14abf15SRobert Mustacchi     {
407*d14abf15SRobert Mustacchi         *(u32_t *)(&in_str[0])   = HTON32(tuple->src_ip[0]);
408*d14abf15SRobert Mustacchi         *(u32_t *)(&in_str[4])   = HTON32(tuple->src_ip[1]);
409*d14abf15SRobert Mustacchi         *(u32_t *)(&in_str[8])   = HTON32(tuple->src_ip[2]);
410*d14abf15SRobert Mustacchi         *(u32_t *)(&in_str[12])  = HTON32(tuple->src_ip[3]);
411*d14abf15SRobert Mustacchi 
412*d14abf15SRobert Mustacchi         *(u32_t *)(&in_str[16])  = HTON32(tuple->dst_ip[0]);
413*d14abf15SRobert Mustacchi         *(u32_t *)(&in_str[20])  = HTON32(tuple->dst_ip[1]);
414*d14abf15SRobert Mustacchi         *(u32_t *)(&in_str[24])  = HTON32(tuple->dst_ip[2]);
415*d14abf15SRobert Mustacchi         *(u32_t *)(&in_str[28])  = HTON32(tuple->dst_ip[3]);
416*d14abf15SRobert Mustacchi 
417*d14abf15SRobert Mustacchi         *(u16_t *)(&in_str[32]) = tuple->src_port;
418*d14abf15SRobert Mustacchi         *(u16_t *)(&in_str[34]) = tuple->dst_port;
419*d14abf15SRobert Mustacchi         in_bits = 36 * 8;
420*d14abf15SRobert Mustacchi     }
421*d14abf15SRobert Mustacchi 
422*d14abf15SRobert Mustacchi     /* prepare searcher_in_str_bits from in_str */
423*d14abf15SRobert Mustacchi     for (i = 0; i < in_bits; i++)
424*d14abf15SRobert Mustacchi     {
425*d14abf15SRobert Mustacchi         /* 0x80 - the leftmost bit. */
426*d14abf15SRobert Mustacchi         in_str_bits[i] = ((in_str[i/8]<<(i%8)) & 0x80) ? 1 : 0;
427*d14abf15SRobert Mustacchi     }
428*d14abf15SRobert Mustacchi 
429*d14abf15SRobert Mustacchi     /* calc ToeplitzHash */
430*d14abf15SRobert Mustacchi     for (i = 0; i < 32; i++)
431*d14abf15SRobert Mustacchi     {
432*d14abf15SRobert Mustacchi         u8_t h = 0;
433*d14abf15SRobert Mustacchi 
434*d14abf15SRobert Mustacchi         for (j = 0; j < in_bits; j++)
435*d14abf15SRobert Mustacchi         {
436*d14abf15SRobert Mustacchi             h ^= key_bits[i+j] & in_str_bits[j];
437*d14abf15SRobert Mustacchi         }
438*d14abf15SRobert Mustacchi 
439*d14abf15SRobert Mustacchi         result |= (h<<(32-i-1));
440*d14abf15SRobert Mustacchi     }
441*d14abf15SRobert Mustacchi 
442*d14abf15SRobert Mustacchi     return result;
443*d14abf15SRobert Mustacchi }
444*d14abf15SRobert Mustacchi 
445*d14abf15SRobert Mustacchi /* assumption: CID lock NOT taken by caller */
lm_searcher_mirror_hash_insert(struct _lm_device_t * pdev,u32_t cid,lm_4tuple_t * tuple)446*d14abf15SRobert Mustacchi lm_status_t lm_searcher_mirror_hash_insert(struct _lm_device_t *pdev, u32_t cid, lm_4tuple_t *tuple)
447*d14abf15SRobert Mustacchi {
448*d14abf15SRobert Mustacchi     lm_context_info_t        *context    = NULL;
449*d14abf15SRobert Mustacchi     lm_searcher_hash_entry_t *hash_entry = NULL;
450*d14abf15SRobert Mustacchi     u32_t                    h_val       = 0;
451*d14abf15SRobert Mustacchi     u8_t temp_ipv6, temp_ipv4, temp_depth_ipv4, is_ipv4;
452*d14abf15SRobert Mustacchi     lm_status_t              lm_status   = LM_STATUS_SUCCESS;
453*d14abf15SRobert Mustacchi     #define SRC_HASH_DEPTH_TH 15 /* that is searcher's default MaxNumHops - 1 */
454*d14abf15SRobert Mustacchi 
455*d14abf15SRobert Mustacchi     /* take spinlock */
456*d14abf15SRobert Mustacchi     MM_ACQUIRE_CID_LOCK(pdev);
457*d14abf15SRobert Mustacchi 
458*d14abf15SRobert Mustacchi     context = pdev->context_info;
459*d14abf15SRobert Mustacchi     is_ipv4 = (tuple->ip_type == LM_IP_TYPE_V4 ? 1 : 0);
460*d14abf15SRobert Mustacchi 
461*d14abf15SRobert Mustacchi     /* calc hash val */
462*d14abf15SRobert Mustacchi     h_val = _lm_searcher_mirror_hash_calc(&context->searcher_hash, tuple);
463*d14abf15SRobert Mustacchi 
464*d14abf15SRobert Mustacchi     /* take only num_hash_bits LSBs */
465*d14abf15SRobert Mustacchi     h_val &= ((1 << context->searcher_hash.num_hash_bits) - 1);
466*d14abf15SRobert Mustacchi 
467*d14abf15SRobert Mustacchi     /* init num_hash_bits in the searcher: if the h_val is all FFFFs - set it to 0 */
468*d14abf15SRobert Mustacchi     if (h_val == ((1 << context->searcher_hash.num_hash_bits) - 1)) {
469*d14abf15SRobert Mustacchi         h_val = 0;
470*d14abf15SRobert Mustacchi     }
471*d14abf15SRobert Mustacchi 
472*d14abf15SRobert Mustacchi     /* get the hash entry */
473*d14abf15SRobert Mustacchi     hash_entry = &context->searcher_hash.searcher_table[h_val];
474*d14abf15SRobert Mustacchi 
475*d14abf15SRobert Mustacchi     /* start the alg. to find if there is a place available in that entry */
476*d14abf15SRobert Mustacchi     temp_ipv6 = hash_entry->num_ipv6 + (is_ipv4 ? 0 : 1);
477*d14abf15SRobert Mustacchi     temp_ipv4 = hash_entry->num_ipv4 + is_ipv4;
478*d14abf15SRobert Mustacchi 
479*d14abf15SRobert Mustacchi     /* tempDepthIpv4 = max ( depthIpv4(H), roundup(tempIpv4/2) ) */
480*d14abf15SRobert Mustacchi     temp_depth_ipv4 = (temp_ipv4 / 2) + (temp_ipv4 % 2);
481*d14abf15SRobert Mustacchi     if (temp_depth_ipv4 < hash_entry->depth_ipv4) {
482*d14abf15SRobert Mustacchi         temp_depth_ipv4 = hash_entry->depth_ipv4;
483*d14abf15SRobert Mustacchi     }
484*d14abf15SRobert Mustacchi 
485*d14abf15SRobert Mustacchi     if (temp_depth_ipv4 + temp_ipv6 > SRC_HASH_DEPTH_TH) {
486*d14abf15SRobert Mustacchi         /* each hash entry has SRC_HASH_DEPTH_TH available places.
487*d14abf15SRobert Mustacchi          * each place can contain 1 ipv6 connection or 2 ipv4 connections */
488*d14abf15SRobert Mustacchi         DbgBreakMsg("Reached searcher hash limit\n");
489*d14abf15SRobert Mustacchi         lm_status = LM_STATUS_FAILURE;
490*d14abf15SRobert Mustacchi     } else {
491*d14abf15SRobert Mustacchi         hash_entry->num_ipv6 = temp_ipv6;
492*d14abf15SRobert Mustacchi         hash_entry->num_ipv4 = temp_ipv4;
493*d14abf15SRobert Mustacchi         hash_entry->depth_ipv4 = temp_depth_ipv4;
494*d14abf15SRobert Mustacchi 
495*d14abf15SRobert Mustacchi         /* for debug, save the max depth reached */
496*d14abf15SRobert Mustacchi         if (context->searcher_hash.hash_depth_reached < hash_entry->depth_ipv4 + hash_entry->num_ipv6) {
497*d14abf15SRobert Mustacchi             context->searcher_hash.hash_depth_reached = hash_entry->depth_ipv4 + hash_entry->num_ipv6;
498*d14abf15SRobert Mustacchi         }
499*d14abf15SRobert Mustacchi         context->searcher_hash.num_tuples++;
500*d14abf15SRobert Mustacchi 
501*d14abf15SRobert Mustacchi         /* remeber the IP type and h_val to know where and how much
502*d14abf15SRobert Mustacchi          * to decrease upon CID recycling */
503*d14abf15SRobert Mustacchi         DbgBreakIf(context->array[cid].ip_type); /* cid can't be inserted twice */
504*d14abf15SRobert Mustacchi         context->array[cid].ip_type = tuple->ip_type;
505*d14abf15SRobert Mustacchi         context->array[cid].h_val = h_val;
506*d14abf15SRobert Mustacchi     }
507*d14abf15SRobert Mustacchi 
508*d14abf15SRobert Mustacchi     /* release spinlock */
509*d14abf15SRobert Mustacchi     MM_RELEASE_CID_LOCK(pdev);
510*d14abf15SRobert Mustacchi 
511*d14abf15SRobert Mustacchi     return lm_status;
512*d14abf15SRobert Mustacchi }
513*d14abf15SRobert Mustacchi 
514*d14abf15SRobert Mustacchi /* assumption: CID lock NOT taken by caller */
lm_searcher_mirror_hash_remove(struct _lm_device_t * pdev,u32_t cid)515*d14abf15SRobert Mustacchi void lm_searcher_mirror_hash_remove(struct _lm_device_t *pdev, u32_t cid)
516*d14abf15SRobert Mustacchi {
517*d14abf15SRobert Mustacchi     lm_context_info_t        *context    = NULL;
518*d14abf15SRobert Mustacchi     lm_searcher_hash_entry_t *hash_entry = NULL;
519*d14abf15SRobert Mustacchi     u32_t                    h_val       = 0;
520*d14abf15SRobert Mustacchi 
521*d14abf15SRobert Mustacchi     /* take spinlock */
522*d14abf15SRobert Mustacchi     MM_ACQUIRE_CID_LOCK(pdev);
523*d14abf15SRobert Mustacchi 
524*d14abf15SRobert Mustacchi     context = pdev->context_info;
525*d14abf15SRobert Mustacchi 
526*d14abf15SRobert Mustacchi     if(!context->array[cid].ip_type) {
527*d14abf15SRobert Mustacchi         /* i.e lm_searcher_mirror_hash_insert was not called for this cid */
528*d14abf15SRobert Mustacchi         DbgMessage(pdev, WARN,
529*d14abf15SRobert Mustacchi                    "not removing CID %d from SRC hash (hash insert was not called for this cid)\n"
530*d14abf15SRobert Mustacchi                    ,cid);
531*d14abf15SRobert Mustacchi 
532*d14abf15SRobert Mustacchi         /* release spinlock */
533*d14abf15SRobert Mustacchi         MM_RELEASE_CID_LOCK(pdev);
534*d14abf15SRobert Mustacchi 
535*d14abf15SRobert Mustacchi         return;
536*d14abf15SRobert Mustacchi     }
537*d14abf15SRobert Mustacchi 
538*d14abf15SRobert Mustacchi     h_val = context->array[cid].h_val;
539*d14abf15SRobert Mustacchi     hash_entry = &context->searcher_hash.searcher_table[h_val];
540*d14abf15SRobert Mustacchi 
541*d14abf15SRobert Mustacchi     if (context->array[cid].ip_type == LM_IP_TYPE_V6) {
542*d14abf15SRobert Mustacchi         DbgBreakIf(!hash_entry->num_ipv6);
543*d14abf15SRobert Mustacchi         hash_entry->num_ipv6--;
544*d14abf15SRobert Mustacchi     }
545*d14abf15SRobert Mustacchi     else
546*d14abf15SRobert Mustacchi     {
547*d14abf15SRobert Mustacchi         DbgBreakIf(!hash_entry->num_ipv4);
548*d14abf15SRobert Mustacchi         hash_entry->num_ipv4--;
549*d14abf15SRobert Mustacchi         if (hash_entry->num_ipv4 < hash_entry->depth_ipv4)
550*d14abf15SRobert Mustacchi         {
551*d14abf15SRobert Mustacchi             hash_entry->depth_ipv4 = hash_entry->num_ipv4;
552*d14abf15SRobert Mustacchi         }
553*d14abf15SRobert Mustacchi     }
554*d14abf15SRobert Mustacchi 
555*d14abf15SRobert Mustacchi     /* for debug */
556*d14abf15SRobert Mustacchi     context->searcher_hash.num_tuples--;
557*d14abf15SRobert Mustacchi 
558*d14abf15SRobert Mustacchi     /* clear the entry of the context */
559*d14abf15SRobert Mustacchi     context->array[cid].ip_type = 0;
560*d14abf15SRobert Mustacchi     context->array[cid].h_val = 0;
561*d14abf15SRobert Mustacchi 
562*d14abf15SRobert Mustacchi     /* release spinlock */
563*d14abf15SRobert Mustacchi     MM_RELEASE_CID_LOCK(pdev);
564*d14abf15SRobert Mustacchi }
565*d14abf15SRobert Mustacchi 
566*d14abf15SRobert Mustacchi /*  allocate a free context by type
567*d14abf15SRobert Mustacchi     returns CID in the out_cid param
568*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS for available cid
569*d14abf15SRobert Mustacchi     LM_STATUS_RESOURCE if no cids are available
570*d14abf15SRobert Mustacchi     LM_STATUS_PENDING if there is a pending cfc-delete cid
571*d14abf15SRobert Mustacchi     takes the list spinlock */
lm_allocate_cid(struct _lm_device_t * pdev,u32_t type,void * cookie,s32_t * out_cid)572*d14abf15SRobert Mustacchi lm_status_t lm_allocate_cid(struct _lm_device_t *pdev, u32_t type, void * cookie, s32_t * out_cid){
573*d14abf15SRobert Mustacchi 
574*d14abf15SRobert Mustacchi     lm_context_info_t  *context  = NULL;
575*d14abf15SRobert Mustacchi     lm_status_t        lm_status = LM_STATUS_SUCCESS;
576*d14abf15SRobert Mustacchi     u32_t              cid       = (u32_t)-1;
577*d14abf15SRobert Mustacchi     lm_address_t       phy_addr  = {{0}} ;
578*d14abf15SRobert Mustacchi 
579*d14abf15SRobert Mustacchi     if ( CHK_NULL(out_cid) ||
580*d14abf15SRobert Mustacchi          CHK_NULL(pdev) ||
581*d14abf15SRobert Mustacchi          CHK_NULL(pdev->context_info) ||
582*d14abf15SRobert Mustacchi          CHK_NULL(pdev->context_info->array) ||
583*d14abf15SRobert Mustacchi          CHK_NULL(cookie) ||
584*d14abf15SRobert Mustacchi          ERR_IF(type >= ARRSIZE(pdev->context_info->proto_pending)) )
585*d14abf15SRobert Mustacchi 
586*d14abf15SRobert Mustacchi     {
587*d14abf15SRobert Mustacchi         DbgBreakIf(!out_cid) ;
588*d14abf15SRobert Mustacchi         DbgBreakIf(!pdev);
589*d14abf15SRobert Mustacchi         DbgBreakIf(!pdev->context_info);
590*d14abf15SRobert Mustacchi         DbgBreakIf(!pdev->context_info->array);
591*d14abf15SRobert Mustacchi         DbgBreakIf(!cookie);
592*d14abf15SRobert Mustacchi         DbgBreakIf(type >= ARRSIZE(pdev->context_info->proto_pending)) ;
593*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER ;
594*d14abf15SRobert Mustacchi     }
595*d14abf15SRobert Mustacchi 
596*d14abf15SRobert Mustacchi     context = pdev->context_info;
597*d14abf15SRobert Mustacchi     *out_cid = 0;
598*d14abf15SRobert Mustacchi     /* take spinlock */
599*d14abf15SRobert Mustacchi     MM_ACQUIRE_CID_LOCK(pdev);
600*d14abf15SRobert Mustacchi 
601*d14abf15SRobert Mustacchi     // if the free list is empty return error
602*d14abf15SRobert Mustacchi     if (context->proto_ffree[type]==0) {
603*d14abf15SRobert Mustacchi         if ((pdev->params.cid_allocation_mode == LM_CID_ALLOC_REGULAR) || (context->proto_pending[type] == 0)) {
604*d14abf15SRobert Mustacchi             // if the free list is empty AND the pending list is empty return error OR
605*d14abf15SRobert Mustacchi             // the free list is empty and we're in the regular allocating mode
606*d14abf15SRobert Mustacchi             lm_status = LM_STATUS_RESOURCE;
607*d14abf15SRobert Mustacchi         }
608*d14abf15SRobert Mustacchi         else
609*d14abf15SRobert Mustacchi         {
610*d14abf15SRobert Mustacchi             /* pop pendinglist entry and place cookie */
611*d14abf15SRobert Mustacchi             /* we only use the cid to connect between the pending connection and this cid, but
612*d14abf15SRobert Mustacchi              * the connection can't know of this cid before it is acually freed, for this reason
613*d14abf15SRobert Mustacchi              * we return cid = 0, which means, 'pending' */
614*d14abf15SRobert Mustacchi             cid = context->proto_pending[type];
615*d14abf15SRobert Mustacchi             context->proto_pending[type] = context->array[cid].next;
616*d14abf15SRobert Mustacchi             context->array[cid].next = 0;
617*d14abf15SRobert Mustacchi             context->array[cid].cid_resc.cookies[type] = cookie;
618*d14abf15SRobert Mustacchi             context->array[cid].cid_resc.cid_pending = LM_CID_STATE_PENDING;
619*d14abf15SRobert Mustacchi             lm_sp_req_manager_init(pdev, cid);
620*d14abf15SRobert Mustacchi             *out_cid = cid;
621*d14abf15SRobert Mustacchi 
622*d14abf15SRobert Mustacchi             /* make sure the first cid previous is set correctly*/
623*d14abf15SRobert Mustacchi             cid = context->proto_pending[type];
624*d14abf15SRobert Mustacchi             if (cid) {
625*d14abf15SRobert Mustacchi                 context->array[cid].prev = 0;
626*d14abf15SRobert Mustacchi             }
627*d14abf15SRobert Mustacchi             lm_status = LM_STATUS_PENDING;
628*d14abf15SRobert Mustacchi         }
629*d14abf15SRobert Mustacchi     }else{
630*d14abf15SRobert Mustacchi         /* pop freelist entry and place cookie*/
631*d14abf15SRobert Mustacchi         cid = context->proto_ffree[type];
632*d14abf15SRobert Mustacchi         context->proto_ffree[type] = context->array[cid].next;
633*d14abf15SRobert Mustacchi         context->array[cid].next = 0;
634*d14abf15SRobert Mustacchi         context->array[cid].prev = 0;
635*d14abf15SRobert Mustacchi         context->array[cid].cid_resc.cookies[type] = cookie;
636*d14abf15SRobert Mustacchi         lm_sp_req_manager_init(pdev, cid);
637*d14abf15SRobert Mustacchi         *out_cid = cid;
638*d14abf15SRobert Mustacchi         lm_status = LM_STATUS_SUCCESS;
639*d14abf15SRobert Mustacchi     }
640*d14abf15SRobert Mustacchi 
641*d14abf15SRobert Mustacchi     MM_RELEASE_CID_LOCK(pdev);
642*d14abf15SRobert Mustacchi 
643*d14abf15SRobert Mustacchi     if(LM_STATUS_SUCCESS == lm_status)
644*d14abf15SRobert Mustacchi     {
645*d14abf15SRobert Mustacchi         //If the function allocated a new free CID, (not pending) the function MmMapIoSpace will be called
646*d14abf15SRobert Mustacchi         //to map the specific physical cid doorbell space to a virtual address.
647*d14abf15SRobert Mustacchi         //In case of a pending CID, the map doorbell space will not be remapped. The pending CID will use
648*d14abf15SRobert Mustacchi         //the old mapping cid doorbell space.
649*d14abf15SRobert Mustacchi         phy_addr.as_u32.low = (pdev->hw_info.mem_base[BAR_1].as_u32.low) & 0xfffffff0;
650*d14abf15SRobert Mustacchi         phy_addr.as_u32.high = pdev->hw_info.mem_base[BAR_1].as_u32.high;
651*d14abf15SRobert Mustacchi 
652*d14abf15SRobert Mustacchi         LM_INC64(&phy_addr,(cid*LM_DQ_CID_SIZE));
653*d14abf15SRobert Mustacchi 
654*d14abf15SRobert Mustacchi #ifdef __SunOS
655*d14abf15SRobert Mustacchi 
656*d14abf15SRobert Mustacchi         context->array[cid].cid_resc.mapped_cid_bar_addr =
657*d14abf15SRobert Mustacchi #ifdef VF_INVOLVED
658*d14abf15SRobert Mustacchi             (volatile void *)((u8_t*)pdev->vars.mapped_bar_addr[BAR_1] + cid*LM_DQ_CID_SIZE);
659*d14abf15SRobert Mustacchi         context->array[cid].cid_resc.reg_handle = pdev->vars.reg_handle[BAR_1];
660*d14abf15SRobert Mustacchi #else /* !VF_INVOLVED */
661*d14abf15SRobert Mustacchi             (volatile void *)mm_map_io_space_solaris(pdev,
662*d14abf15SRobert Mustacchi                                                      phy_addr,
663*d14abf15SRobert Mustacchi                                                      BAR_1,
664*d14abf15SRobert Mustacchi                                                      (cid * LM_DQ_CID_SIZE),
665*d14abf15SRobert Mustacchi                                                      LM_DQ_CID_SIZE,
666*d14abf15SRobert Mustacchi                                                      &context->array[cid].cid_resc.reg_handle);
667*d14abf15SRobert Mustacchi #endif /* VF_INVOLVED */
668*d14abf15SRobert Mustacchi 
669*d14abf15SRobert Mustacchi #else /* !__SunOS */
670*d14abf15SRobert Mustacchi 
671*d14abf15SRobert Mustacchi         context->array[cid].cid_resc.mapped_cid_bar_addr =
672*d14abf15SRobert Mustacchi #ifdef VF_INVOLVED
673*d14abf15SRobert Mustacchi             (volatile void *)((u8_t*)pdev->vars.mapped_bar_addr[BAR_1] + cid*LM_DQ_CID_SIZE);
674*d14abf15SRobert Mustacchi #else /* !VF_INVOLVED */
675*d14abf15SRobert Mustacchi             (volatile void *)mm_map_io_space(pdev, phy_addr, LM_DQ_CID_SIZE);
676*d14abf15SRobert Mustacchi #endif /* VF_INVOLVED */
677*d14abf15SRobert Mustacchi 
678*d14abf15SRobert Mustacchi #endif /* __SunOS */
679*d14abf15SRobert Mustacchi 
680*d14abf15SRobert Mustacchi         // If the mapping failed we will return LM_STATUS_RESOURCE and return the cid resource.
681*d14abf15SRobert Mustacchi         if CHK_NULL(context->array[cid].cid_resc.mapped_cid_bar_addr)
682*d14abf15SRobert Mustacchi         {
683*d14abf15SRobert Mustacchi             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 );
684*d14abf15SRobert Mustacchi 
685*d14abf15SRobert Mustacchi             /* take spinlock */
686*d14abf15SRobert Mustacchi             MM_ACQUIRE_CID_LOCK(pdev);
687*d14abf15SRobert Mustacchi             /* return the cid to free list */
688*d14abf15SRobert Mustacchi             context->array[cid].next = pdev->context_info->proto_ffree[type];
689*d14abf15SRobert Mustacchi             context->proto_ffree[type] = cid;
690*d14abf15SRobert Mustacchi             context->array[cid].invalid = LM_CONTEXT_VALID;
691*d14abf15SRobert Mustacchi             MM_RELEASE_CID_LOCK(pdev);
692*d14abf15SRobert Mustacchi 
693*d14abf15SRobert Mustacchi             lm_status = LM_STATUS_RESOURCE;
694*d14abf15SRobert Mustacchi             *out_cid =0;
695*d14abf15SRobert Mustacchi         }
696*d14abf15SRobert Mustacchi     }
697*d14abf15SRobert Mustacchi     return lm_status;
698*d14abf15SRobert Mustacchi }
699*d14abf15SRobert Mustacchi 
lm_cfc_delete(struct _lm_device_t * pdev,void * param)700*d14abf15SRobert Mustacchi void lm_cfc_delete(struct _lm_device_t *pdev, void *param)
701*d14abf15SRobert Mustacchi {
702*d14abf15SRobert Mustacchi     u32_t cid             = *((u32_t *)&param);
703*d14abf15SRobert Mustacchi     u8_t  flr_in_progress = lm_fl_reset_is_inprogress(pdev);
704*d14abf15SRobert Mustacchi 
705*d14abf15SRobert Mustacchi     if ( CHK_NULL(pdev) ||
706*d14abf15SRobert Mustacchi          ERR_IF(cid > pdev->params.max_func_connections) ||
707*d14abf15SRobert Mustacchi          ERR_IF(pdev->context_info->array[cid].invalid != LM_CONTEXT_INVALID_WAIT) )
708*d14abf15SRobert Mustacchi     {
709*d14abf15SRobert Mustacchi         DbgBreakIf(!pdev);
710*d14abf15SRobert Mustacchi         DbgBreakIf(cid > pdev->params.max_func_connections);
711*d14abf15SRobert Mustacchi 
712*d14abf15SRobert Mustacchi         if (!flr_in_progress)
713*d14abf15SRobert Mustacchi         {
714*d14abf15SRobert Mustacchi             DbgBreakIf(pdev->context_info->array[cid].invalid != LM_CONTEXT_INVALID_WAIT);
715*d14abf15SRobert Mustacchi         }
716*d14abf15SRobert Mustacchi         else
717*d14abf15SRobert Mustacchi         {
718*d14abf15SRobert Mustacchi             DbgMessage(pdev, FATAL, "lm_cfc_delete: invalid %d for cid=%d\n", pdev->context_info->array[cid].invalid,cid);
719*d14abf15SRobert Mustacchi 
720*d14abf15SRobert Mustacchi             if (pdev->context_info->array[cid].invalid != LM_CONTEXT_INVALID_DELETE)
721*d14abf15SRobert Mustacchi             {
722*d14abf15SRobert Mustacchi                 DbgBreakIf(1);
723*d14abf15SRobert Mustacchi             }
724*d14abf15SRobert Mustacchi         }
725*d14abf15SRobert Mustacchi     }
726*d14abf15SRobert Mustacchi 
727*d14abf15SRobert Mustacchi     DbgMessage(pdev, WARN, "lm_cfc_delete: cid=0x%x\n",cid);
728*d14abf15SRobert Mustacchi     pdev->context_info->array[cid].invalid = LM_CONTEXT_INVALID_DELETE;
729*d14abf15SRobert Mustacchi 
730*d14abf15SRobert Mustacchi     if (lm_fl_reset_is_inprogress(pdev))
731*d14abf15SRobert Mustacchi     {
732*d14abf15SRobert Mustacchi          lm_recycle_cid(pdev, cid);
733*d14abf15SRobert Mustacchi     }
734*d14abf15SRobert Mustacchi     else
735*d14abf15SRobert Mustacchi     {
736*d14abf15SRobert Mustacchi         /* use common bit */
737*d14abf15SRobert Mustacchi         lm_command_post(pdev,
738*d14abf15SRobert Mustacchi                         cid,
739*d14abf15SRobert Mustacchi                         RAMROD_CMD_ID_COMMON_CFC_DEL,
740*d14abf15SRobert Mustacchi                         CMD_PRIORITY_NORMAL,
741*d14abf15SRobert Mustacchi                         NONE_CONNECTION_TYPE,
742*d14abf15SRobert Mustacchi                         0 );
743*d14abf15SRobert Mustacchi     }
744*d14abf15SRobert Mustacchi     return;
745*d14abf15SRobert Mustacchi }
746*d14abf15SRobert Mustacchi 
747*d14abf15SRobert Mustacchi /* free a context
748*d14abf15SRobert Mustacchi    takes the list spinlock */
lm_free_cid(struct _lm_device_t * pdev,u32_t type,u32_t cid,u8_t notify_fw)749*d14abf15SRobert Mustacchi void lm_free_cid(struct _lm_device_t *pdev, u32_t type, u32_t cid, u8_t notify_fw){
750*d14abf15SRobert Mustacchi     u32_t delay_time  = 0;
751*d14abf15SRobert Mustacchi     u32_t curr_cid    = 0;
752*d14abf15SRobert Mustacchi     u8_t  recycle_now = 0;
753*d14abf15SRobert Mustacchi     u8_t  proto_idx   = 0;
754*d14abf15SRobert Mustacchi 
755*d14abf15SRobert Mustacchi     if ( CHK_NULL(pdev) ||
756*d14abf15SRobert Mustacchi          CHK_NULL(pdev->context_info) ||
757*d14abf15SRobert Mustacchi          ERR_IF(type >= ARRSIZE(pdev->context_info->proto_end)) ||
758*d14abf15SRobert Mustacchi          ERR_IF(cid > (pdev->context_info->proto_end[type])) ||
759*d14abf15SRobert Mustacchi          ERR_IF(cid < (pdev->context_info->proto_start[type])) ||
760*d14abf15SRobert Mustacchi          (!lm_fl_reset_is_inprogress(pdev) && (pdev->context_info->array[cid].invalid != LM_CONTEXT_VALID)))
761*d14abf15SRobert Mustacchi     {
762*d14abf15SRobert Mustacchi         DbgBreakIf(!pdev);
763*d14abf15SRobert Mustacchi         DbgBreakIf(!pdev->context_info);
764*d14abf15SRobert Mustacchi         DbgBreakIf(type >= ARRSIZE(pdev->context_info->proto_end));
765*d14abf15SRobert Mustacchi         DbgBreakIf(cid > (pdev->context_info->proto_end[type]));
766*d14abf15SRobert Mustacchi         DbgBreakIf(cid < (pdev->context_info->proto_start[type]));
767*d14abf15SRobert Mustacchi         DbgBreakIf(pdev->context_info->array[cid].invalid != LM_CONTEXT_VALID);
768*d14abf15SRobert Mustacchi         return;
769*d14abf15SRobert Mustacchi     }
770*d14abf15SRobert Mustacchi     MM_ACQUIRE_CID_LOCK(pdev);
771*d14abf15SRobert Mustacchi 
772*d14abf15SRobert Mustacchi     for (proto_idx = 0; proto_idx < MAX_PROTO; proto_idx++)
773*d14abf15SRobert Mustacchi     {
774*d14abf15SRobert Mustacchi         DbgBreakIf(pdev->context_info->array[cid].cid_resc.cookies[proto_idx]);
775*d14abf15SRobert Mustacchi     }
776*d14abf15SRobert Mustacchi 
777*d14abf15SRobert Mustacchi     lm_sp_req_manager_shutdown(pdev, cid);
778*d14abf15SRobert Mustacchi 
779*d14abf15SRobert Mustacchi     if (notify_fw)
780*d14abf15SRobert Mustacchi     {
781*d14abf15SRobert Mustacchi         /* Vladz: Added in order to optimize CID release in DOS */
782*d14abf15SRobert Mustacchi #if !(defined(DOS) || defined(__LINUX))
783*d14abf15SRobert Mustacchi         delay_time = LM_FREE_CID_DELAY_TIME(pdev);
784*d14abf15SRobert Mustacchi #else
785*d14abf15SRobert Mustacchi         delay_time = 0;
786*d14abf15SRobert Mustacchi #endif
787*d14abf15SRobert Mustacchi 
788*d14abf15SRobert Mustacchi         pdev->context_info->array[cid].invalid = LM_CONTEXT_INVALID_WAIT;
789*d14abf15SRobert Mustacchi 
790*d14abf15SRobert Mustacchi         recycle_now = FALSE;
791*d14abf15SRobert Mustacchi         /* add the cid to proto-pending: it'll be freed soon when cfc-delete is done */
792*d14abf15SRobert Mustacchi         curr_cid = pdev->context_info->proto_pending[type];
793*d14abf15SRobert Mustacchi         pdev->context_info->array[cid].next = curr_cid;
794*d14abf15SRobert Mustacchi         pdev->context_info->array[cid].prev = 0;
795*d14abf15SRobert Mustacchi         if (curr_cid != 0)
796*d14abf15SRobert Mustacchi         {
797*d14abf15SRobert Mustacchi             pdev->context_info->array[curr_cid].prev = cid;
798*d14abf15SRobert Mustacchi         }
799*d14abf15SRobert Mustacchi         pdev->context_info->proto_pending[type] = cid;
800*d14abf15SRobert Mustacchi     }
801*d14abf15SRobert Mustacchi     else
802*d14abf15SRobert Mustacchi     {
803*d14abf15SRobert Mustacchi         pdev->context_info->array[cid].invalid = LM_CONTEXT_INVALID_DELETE;
804*d14abf15SRobert Mustacchi         recycle_now = TRUE;
805*d14abf15SRobert Mustacchi         /* If we're recylcing now, there's no point in adding it to the pending list */
806*d14abf15SRobert Mustacchi     }
807*d14abf15SRobert Mustacchi 
808*d14abf15SRobert Mustacchi     MM_RELEASE_CID_LOCK(pdev);
809*d14abf15SRobert Mustacchi 
810*d14abf15SRobert Mustacchi     if (recycle_now) {
811*d14abf15SRobert Mustacchi         lm_recycle_cid(pdev, cid);
812*d14abf15SRobert Mustacchi     }
813*d14abf15SRobert Mustacchi     else
814*d14abf15SRobert Mustacchi     {
815*d14abf15SRobert Mustacchi         if (type == TOE_CONNECTION_TYPE)
816*d14abf15SRobert Mustacchi         {
817*d14abf15SRobert Mustacchi             DbgMessage(pdev, WARN, "lm_free_cid: CFC delete: cid=0x%x\n",cid);
818*d14abf15SRobert Mustacchi             lm_cfc_delete(pdev,*((void **)&cid));
819*d14abf15SRobert Mustacchi         }
820*d14abf15SRobert Mustacchi         else
821*d14abf15SRobert Mustacchi         {
822*d14abf15SRobert Mustacchi             DbgMessage(pdev, WARN, "lm_free_cid: schedule CFC delete: cid=0x%x\n",cid);
823*d14abf15SRobert Mustacchi             mm_schedule_task(pdev,delay_time,lm_cfc_delete,*((void **)&cid));
824*d14abf15SRobert Mustacchi         }
825*d14abf15SRobert Mustacchi     }
826*d14abf15SRobert Mustacchi 
827*d14abf15