1 #include "lm5710.h"
2 #include "command.h"
3 
4 /* Zeros all attn_bits/ack back to the start, along with the state and the original mask of AEU lines
5  *
6  * Parameters:
7  * pdev      - this is the LM device
8  */
9 static void dbg_zero_all_attn(lm_device_t *pdev)
10 {
11 	volatile struct host_def_status_block *def_sb = NULL;
12 
13 	DbgMessage(pdev, INFORMi, "dbg_zero_all_attn() inside!\n");
14 
15     def_sb = lm_get_default_status_block(pdev);
16     DbgBreakIf(!def_sb);
17 
18     def_sb->atten_status_block.attn_bits     = 0;
19     def_sb->atten_status_block.attn_bits_ack = 0;
20     pdev->vars.aeu_mask_attn_func            = 0x303;
21     pdev->vars.attn_state                    = 0;
22 }
23 
24 /* modifies attn_bits to '1' asserted state
25  *
26  * Parameters:
27  * pdev      - this is the LM device
28  * lines_to_assert - lines which goes up (asserted)
29  */
30 static void dbg_assert_attn_lines(lm_device_t *pdev, u16_t lines_to_assert)
31 {
32 	volatile struct host_def_status_block *def_sb = NULL;
33 
34 	DbgMessage1(pdev, INFORMi, "dbg_assert_attn_lines() inside! lines_to_assert:0x%x\n", lines_to_assert);
35 
36     def_sb = lm_get_default_status_block(pdev);
37     DbgBreakIf(!def_sb);
38     DbgBreakIf(mm_le32_to_cpu(def_sb->atten_status_block.attn_bits) & lines_to_assert);
39 
40     /*
41     attns bits  line_to_assert
42         1           1             -> ERROR
43         1           0             -> 1
44         0           0             -> 0
45         0           1             -> 1
46     */
47     def_sb->atten_status_block.attn_bits |= mm_cpu_to_le32(lines_to_assert);
48 }
49 
50 /* modifies attn_bits to '0' deasserted state
51  *
52  * Parameters:
53  * pdev      - this is the LM device
54  * lines_to_deassert - lines which goes down (deasserted)
55  */
56 static void dbg_deassert_attn_lines(lm_device_t *pdev, u16_t lines_to_deassert)
57 {
58 	volatile struct host_def_status_block *def_sb = NULL;
59 
60 	DbgMessage1(pdev, INFORMi, "dbg_deassert_attn_lines() inside! lines_to_deassert:0x%x\n", lines_to_deassert);
61 
62     def_sb = lm_get_default_status_block(pdev);
63     DbgBreakIf(!def_sb);
64     DbgBreakIf(~mm_le32_to_cpu(def_sb->atten_status_block.attn_bits) & lines_to_deassert);
65 /*
66     attns bits  line_to_deassert
67         1           1             -> 0
68         1           0             -> 1
69         0           0             -> 0
70         0           1             -> ERROR
71 */
72     def_sb->atten_status_block.attn_bits ^= mm_cpu_to_le32(lines_to_deassert);
73 }
74 
75 /* modifies attn_ack to '1' asserted state
76  *
77  * Parameters:
78  * pdev      - this is the LM device
79  * assert_lines_to_ack - lines for which we simulate a write of '1' to the attn_ack (asserted)
80  */
81 static void dbg_ack_assert_attn_lines(lm_device_t *pdev, u16_t assert_lines_to_ack)
82 {
83 	volatile struct host_def_status_block *def_sb = NULL;
84 
85 	DbgMessage1(pdev, INFORMi, "dbg_ack_assert_attn_lines() inside! assert_lines_to_ack:0x%x\n", assert_lines_to_ack);
86 
87     def_sb = lm_get_default_status_block(pdev);
88     DbgBreakIf(!def_sb);
89     DbgBreakIf(mm_le32_to_cpu(def_sb->atten_status_block.attn_bits_ack) & assert_lines_to_ack);
90 /*
91     attns bits ack  assert_lines_to_ack
92         1                1             -> ERROR
93         1                0             -> 1
94         0                0             -> 0
95         0                1             -> 1
96 */
97     def_sb->atten_status_block.attn_bits_ack ^= mm_cpu_to_le32(assert_lines_to_ack);
98 }
99 
100 /* modifies attn_ack to '0' deasserted state
101  *
102  * Parameters:
103  * pdev      - this is the LM device
104  * deassert_lines_to_ack - lines for which we simulate a write of '0' to the attn_ack (deasserted)
105  */
106 /*
107 static void dbg_ack_deassert_attn_lines(lm_device_t *pdev, u16_t deassert_lines_to_ack)
108 {
109 	volatile struct host_def_status_block *def_sb = NULL;
110 
111 	DbgMessage1(pdev, INFORMi, "dbg_ack_deassert_attn_lines() inside! deassert_lines_to_ack:0x%x\n", deassert_lines_to_ack);
112 
113     def_sb = lm_get_default_status_block(pdev);
114     DbgBreakIf(!def_sb);
115     DbgBreakIf(~def_sb->atten_status_block.attn_bits_ack & deassert_lines_to_ack);
116 
117     //attns bits ack  deassert_lines_to_ack
118     //    1                1             -> 0
119     //    1                0             -> 1
120     //    0                0             -> 0
121     //    0                1             -> ERROR
122 
123     def_sb->atten_status_block.attn_bits_ack ^= deassert_lines_to_ack;
124 }
125 */
126 
127 static void dbg_change_sb_index(lm_device_t *pdev, u8_t rss_id)
128 {
129 	volatile struct host_status_block *rss_sb	  = NULL;
130 	volatile struct host_def_status_block *def_sb = NULL;
131 
132 	DbgBreakIf(!pdev || rss_id > MAX_RSS_CHAINS);
133 	DbgMessage(pdev, INFORMi, "dbg_change_sb_index() inside!\n");
134 	//this is the default status block
135 	if(rss_id == DEF_STATUS_BLOCK_INDEX)
136 	{
137 		def_sb = lm_get_default_status_block(pdev);
138 		DbgBreakIf(!def_sb);
139 		//increment the status index of all storms for this status block
140 		def_sb->c_def_status_block.status_block_index = mm_cpu_to_le16(mm_le16_to_cpu(def_sb->c_def_status_block.status_block_index) + 1);
141 		def_sb->u_def_status_block.status_block_index = mm_cpu_to_le16(mm_le16_to_cpu(def_sb->u_def_status_block.status_block_index) + 1);
142 		def_sb->x_def_status_block.status_block_index = mm_cpu_to_le16(mm_le16_to_cpu(def_sb->x_def_status_block.status_block_index) + 1);
143 		def_sb->t_def_status_block.status_block_index = mm_cpu_to_le16(mm_le16_to_cpu(def_sb->t_def_status_block.status_block_index) + 1);
144 		def_sb->atten_status_block.attn_bits_index    = mm_cpu_to_le16(mm_le16_to_cpu(def_sb->atten_status_block.attn_bits_index) + 1);
145 
146 		DbgMessage6(pdev, INFORMi, "dbg_change_sb_index():sb#%d indices are now: c_def_prod_idx:%d, u_def_prod_idx:%d, x_def_prod_idx:%d, t_def_prod_idx:%d\n",
147 			rss_id,
148 			mm_le16_to_cpu(def_sb->c_def_status_block.status_block_index),
149 			mm_le16_to_cpu(def_sb->u_def_status_block.status_block_index),
150 			mm_le16_to_cpu(def_sb->x_def_status_block.status_block_index),
151 			mm_le16_to_cpu(def_sb->t_def_status_block.status_block_index),
152 			mm_le16_to_cpu(def_sb->atten_status_block.attn_bits_index));
153 	}
154 	//it is one of the non-default status block
155 	else
156 	{
157 		rss_sb = lm_get_status_block(pdev, rss_id);
158 		DbgBreakIf(!rss_sb);
159 		//increment the status index of all storms for this status block
160 		rss_sb->c_status_block.status_block_index = mm_cpu_to_le16(mm_le16_to_cpu(rss_sb->c_status_block.status_block_index) + 1);
161 		rss_sb->u_status_block.status_block_index = mm_cpu_to_le16(mm_le16_to_cpu(rss_sb->u_status_block.status_block_index) + 1);
162 
163 		DbgMessage3(pdev, INFORMi, "dbg_change_sb_index():sb#%d indices are now: c_rss_prod_idx:%d, u_rss_prod_idx:%d\n",
164 			rss_id,
165 			mm_le16_to_cpu(rss_sb->c_status_block.status_block_index),
166 			mm_le16_to_cpu(rss_sb->u_status_block.status_block_index));
167 	}
168 }
169 
170 /* UM calls this in case there was a change in the default status block.
171  * This function does the work of the DPC.
172  * Parameters:
173  * pdev   - this is the LM device
174  * sb_idx - this is the index where the status block lies in the array under the lm_device
175  */
176 static void dbg_def_sb_dpc(lm_device_t *pdev)
177 {
178 	u8_t is_updated               = 0;
179     u32_t cnt                     = 0;
180     //Attntion vars
181     u32_t total_activ_to_ack      = 0;
182     u32_t cnt_acks                = 0;
183     u32_t activity_flg            = 0;
184     u16_t lcl_attn_bits           = 0;
185     u16_t lcl_attn_ack            = 0;
186     u16_t asserted_proc_grps      = 0;
187     u16_t deasserted_proc_grps    = 0;
188     u32_t dpc_loop_cnt            = 1; //hard-coded! part of the UM device params.
189 
190 	DbgBreakIf(!pdev);
191 	DbgMessage(pdev, INFORMi, "dbg_def_sb_dpc(): inside!\n");
192 
193 	//check if the default status block has changed, thus have a new status index.
194 	//it is possible that even here, there is no difference in the index due to hw queues races(the DMA op is delayed)so bail out.
195 	if ((is_updated = lm_is_def_sb_updated(pdev)) == 0)
196 	{
197 		//Agreed with Shay that we don't need to ack the index in case it matches the local copy, just enable ints
198 		DbgMessage(pdev, INFORMi, "dbg_def_sb_dpc(): no change in status index so get out!\n");
199 		lm_int_ack_sb(pdev, DEF_STATUS_BLOCK_INDEX, TSTORM_ID, DEF_SB_INDEX_OF_TSTORM(pdev), IGU_INT_ENABLE, 0);
200 
201 
202 		return;
203 	}
204 	for(cnt = 0; cnt < dpc_loop_cnt; cnt++)
205 	{
206         //update the local copy of indices with the newly fresh indices values just read from the default status block
207 		lm_update_hc_indices(pdev, DEF_STATUS_BLOCK_INDEX, &activity_flg);
208 
209         DbgBreakIf(!(activity_flg & LM_DEF_EVENT_MASK));
210 
211         total_activ_to_ack |= activity_flg;
212 
213         //attn bits handling
214         if (activity_flg & LM_DEF_ATTN_ACTIVE)
215         {
216             lcl_attn_bits = 0;
217             lcl_attn_ack  = 0;
218             lm_get_attn_info(pdev, &lcl_attn_bits, &lcl_attn_ack);
219 
220             GET_ATTN_CHNG_GROUPS(pdev, lcl_attn_bits, lcl_attn_ack, &asserted_proc_grps, &deasserted_proc_grps);
221 
222             DbgMessage2(pdev, INFORMi, "dbg_def_sb_dpc(): asserted_proc_grps:0x%x, deasserted_proc_grps:0x%x\n", asserted_proc_grps, deasserted_proc_grps);
223 
224             if (asserted_proc_grps)
225                 lm_handle_assertion_processing(pdev, asserted_proc_grps);
226 
227             if (deasserted_proc_grps)
228                 lm_handle_deassertion_processing(pdev, deasserted_proc_grps);
229         }
230 
231         if (activity_flg & LM_DEF_USTORM_ACTIVE)
232         {
233             //TODO: USTORM protocol indices processing processing
234         }
235         if (activity_flg & LM_DEF_CSTORM_ACTIVE)
236         {
237             //TODO: CSTORM protocol indices processing processing
238         }
239         activity_flg = 0;
240         //if no change beneath our legs, get out.
241         if ((is_updated = lm_is_def_sb_updated(pdev)) == 0)
242         {
243             break;
244         }
245 	}
246     //optimization to ack only the relevant parts to chip, and the last one must enable ints.
247     cnt_acks = count_bits(total_activ_to_ack);
248 
249     DbgMessage2(pdev, INFORMi, "um_bdrv_def_dpc(): cnt_acks:%d, total_activ_to_ack:0x%x\n", cnt_acks, total_activ_to_ack);
250 
251     if (total_activ_to_ack & LM_DEF_ATTN_ACTIVE)
252         lm_int_ack_sb(pdev, DEF_STATUS_BLOCK_INDEX, ATTENTION_ID, DEF_SB_INDEX_OF_ATTN(pdev), --cnt_acks ? IGU_INT_NOP : IGU_INT_ENABLE, 1);
253 
254     if (total_activ_to_ack & LM_DEF_USTORM_ACTIVE)
255         lm_int_ack_sb(pdev, DEF_STATUS_BLOCK_INDEX, USTORM_ID, DEF_SB_INDEX_OF_USTORM(pdev), --cnt_acks ? IGU_INT_NOP : IGU_INT_ENABLE, 1);
256 
257     if (total_activ_to_ack & LM_DEF_CSTORM_ACTIVE)
258         lm_int_ack_sb(pdev, DEF_STATUS_BLOCK_INDEX, CSTORM_ID, DEF_SB_INDEX_OF_CSTORM(pdev), --cnt_acks ? IGU_INT_NOP : IGU_INT_ENABLE, 1);
259 
260     if (total_activ_to_ack & LM_DEF_XSTORM_ACTIVE)
261         lm_int_ack_sb(pdev, DEF_STATUS_BLOCK_INDEX, XSTORM_ID, DEF_SB_INDEX_OF_XSTORM(pdev), --cnt_acks ? IGU_INT_NOP : IGU_INT_ENABLE, 1);
262 
263     if (total_activ_to_ack & LM_DEF_TSTORM_ACTIVE)
264 		lm_int_ack_sb(pdev, DEF_STATUS_BLOCK_INDEX, TSTORM_ID, DEF_SB_INDEX_OF_TSTORM(pdev), --cnt_acks ? IGU_INT_NOP : IGU_INT_ENABLE, 1);
265 
266 		DbgMessage(pdev, INFORMi, "dbg_def_sb_dpc(): FINISH _______________________________________________\n");
267 }
268 
269 /* UM calls this in case there was a change in the status block.
270  * This function does the work of the DPC.
271  * Parameters:
272  * pdev   - this is the LM device
273  * sb_idx - this is the index where the status block lies in the array under the lm_device
274  */
275 static void dbg_sb_dpc(lm_device_t *pdev, u8_t rss_id)
276 {
277 	u8_t is_updated               = 0;
278     u32_t activity_flg            = 0;
279     u32_t total_activ_to_ack      = 0;
280     u32_t cnt_acks                = 0;
281     u32_t cnt                     = 0;
282     u32_t dpc_loop_cnt            = 1; //hardcoded! - part of original UM device params.
283 
284 	DbgBreakIf(!pdev);
285 	DbgBreakIf(rss_id >= MAX_RSS_CHAINS);
286 
287 	DbgMessage1(pdev, INFORMi, "dbg_sb_dpc(): handling RSS status block #%d\n", rss_id);
288 
289 	//check if the non-default status block has changed, thus have a new status index.
290 	//it is possible that even here, there is no difference in the index due to hw queues races(the DMA op is delayed)so bail out.
291 	if ((is_updated = lm_is_sb_updated(pdev, rss_id)) == 0)
292 	{
293 		//Agreed with Shay that we don't need to ack the index in case it matches the local copy, just enable ints
294 		DbgMessage(pdev, INFORMi, "handle_sb(): no change is status index so get out!\n");
295 		lm_int_ack_sb(pdev, rss_id, CSTORM_ID, SB_INDEX_OF_CSTORM(pdev,rss_id), IGU_INT_ENABLE, 0);
296 
297 		return;
298 	}
299 	for(cnt = 0; cnt < dpc_loop_cnt; cnt++)
300 	{
301         //update the local copy of indices with the newly fresh indices values just read from the status block
302 		lm_update_hc_indices(pdev, rss_id, &activity_flg);
303 
304         DbgBreakIf(!(activity_flg & LM_NON_DEF_EVENT_MASK));
305 
306         total_activ_to_ack |= activity_flg;
307 
308         if (activity_flg & LM_NON_DEF_USTORM_ACTIVE)
309         {
310             //Check for Rx completions
311     		if (lm_is_rx_completion(pdev, rss_id))
312     		{
313     			//Call here service_rx_intr(pdev, rss_id);
314     		}
315         }
316 
317         if (activity_flg & LM_NON_DEF_CSTORM_ACTIVE)
318         {
319             //Check for Tx completions
320     		if (lm_is_tx_completion(pdev, rss_id))
321     		{
322     			//Call here service_tx_intr(pdev, rss_id);
323     		}
324         }
325         activity_flg = 0;
326 		//check whether the status block has been change meanwhile, if so, lets process again
327 		if ((is_updated = lm_is_sb_updated(pdev, rss_id)) == 0)
328         {
329             break;
330         }
331 	}
332     //optimization to ack only the relevant parts to chip, and the last one must enable ints.
333     cnt_acks = count_bits(total_activ_to_ack);
334     DbgMessage2(pdev, INFORMi, "dbg_sb_dpc(): cnt_acks:%d, total_activ_to_ack:0x%x\n", cnt_acks, total_activ_to_ack);
335 
336     if (total_activ_to_ack & LM_NON_DEF_USTORM_ACTIVE)
337         lm_int_ack_sb(pdev, rss_id, USTORM_ID, SB_INDEX_OF_USTORM(pdev,rss_id), --cnt_acks ? IGU_INT_NOP : IGU_INT_ENABLE, 1);
338 
339     if (total_activ_to_ack & LM_NON_DEF_CSTORM_ACTIVE)
340         lm_int_ack_sb(pdev, rss_id, CSTORM_ID, SB_INDEX_OF_CSTORM(pdev,rss_id), --cnt_acks ? IGU_INT_NOP : IGU_INT_ENABLE, 1);
341 
342 	//after all fast-path processing done, call this to enable posting pending requests to the SQ
343 	lm_sq_post_pending(pdev);
344 	DbgMessage(pdev, INFORMi, "handle_sb(): FINISH _______________________________________________\n");
345 }
346 
347 static u8_t dbg_isr(lm_device_t *pdev, u32_t intr_status)
348 {
349     u8_t intr_recognized;
350 	u8_t rss_id = 0;
351 
352     intr_recognized = FALSE;
353 
354 	DbgBreakIf(!pdev);
355 	DbgMessage(pdev, INFORMi, "dbg_isr() inside!\n");
356 
357 	//get the relevant status blocks for which we need to schedule the appropriate DPC
358 	//please note this implicitly de-asserts the interrupt line, which must not be forgotten to be enabled via the DPC
359 	//the LSB(bit 0) describes the default status blocks and bit 1-16 describe the RSS non-default status blocks.
360 	//In case RSS not supported, everything will arrive on RSS 0, that means that lm_get_interrupt_status()
361 	//will return on the maximum bit0 and bit1 toggled in that case.
362 
363     //intr_status = lm_get_interrupt_status(pdev);
364 
365 	//this is not our interrupt so bail out!
366 	if (!intr_status)
367 	{
368 		return intr_recognized;
369 	}
370 
371     //TODO: In Windows, must assure that there is only one DPC running!
372 	//TODO: Get the CPU number on which this ISR is running (needed for RSS)
373 
374 	//go over all the status blocks updates we received from reading the single ISR/multiple DPCs register,
375 	//and queue the corresponding DPCs for them.
376 	//Currently, RSS is not supported, but still, a scenario might occur where we need to queue both the fast-path DPC as well as
377 	//the slow-path DPC
378 	while(intr_status)
379     {
380         if(intr_status & 1)
381         {
382 			//this means that there is a change in the default sb, so queue the relevant DPC of the default sb.
383 			if (rss_id == 0)
384 			{
385 				//This is the interface for Xdiag. In Windows, this will be the function which will get queued
386 				//within the DPC object.
387 				dbg_def_sb_dpc(pdev);
388 			}
389 
390 			//take care of the non-default sb according to RSS.
391 			else
392 			{
393 				//(rss_id - 1) is used since the non-default sbs are located in lm_device at indices 0-15
394 				dbg_sb_dpc(pdev, rss_id - 1);
395 			}
396         }
397 
398 		intr_status >>= 1;
399         rss_id++;
400     }
401 
402 	intr_recognized = TRUE;
403 
404 	DbgMessage1(pdev, INFORMi, "dbg_isr(): intr_recognized is:%s\n", intr_recognized ? "TRUE" : "FALSE");
405 
406     return intr_recognized;
407 } /* dbg_isr */
408 
409 
410 void dbg_sb_ints_test_suite(lm_device_t *pdev)
411 {
412 	u8_t index;
413 	volatile struct host_def_status_block *def_sb = NULL;
414     def_sb = lm_get_default_status_block(pdev);
415 
416     //This part is dedicated to checking the entire status block mechanism and Interrupts API.
417 	//The test should change the default/non-defualt status block parameters and print as debug information
418 	//the whole status block fields.
419 
420 	//print entire info of all status blocks!
421 	print_sb_info(pdev);
422 
423 	//handle default status block (=DPC of status block) - nothing should happen yet!
424 	dbg_def_sb_dpc(pdev);
425 
426 	//handle all rss non-default status blocks - nothing should happen yet
427 	for(index = 0; index < MAX_RSS_CHAINS; index++)
428 	{
429 		dbg_sb_dpc(pdev, index);
430 	}
431 
432 	//now it's time to change the status index of "some" of the status block as if there
433 	//was a change regarding them
434 	for(index = 0; index <= MAX_RSS_CHAINS; index++)
435 	{
436 		//do update only for odd index status blocks and the default status block
437 		if((index % 2) || (index == MAX_RSS_CHAINS))
438 		{
439 			dbg_change_sb_index(pdev, index);
440 		}
441 	}
442     //assert groups: 0,1
443     dbg_assert_attn_lines(pdev, 0x3);
444 
445     //This part is hardcoded for simulating a change on the default status block(0) and RSS sb: 1,3,5,7,9,11,13,15
446     dbg_isr(pdev, 0x15555);
447 
448     //now we have for groups 0,1:
449     //             attn_bits: 1 1
450     //             attn_ack:  0 0
451     //             mask:      0 0
452     //             state:     1 1
453 
454     //simulate as if the chip wrote 1 1 to the attn_ack
455     dbg_ack_assert_attn_lines(pdev, 0x3);
456 
457     //now we have for groups 0,1:
458     //             attn_bits: 1 1
459     //             attn_ack:  1 1
460     //             mask:      0 0
461     //             state:     1 1
462 
463     //simulate as if due to the mask of the AEU line, 0 has arrived at the line and written by chip to attn_bits
464     dbg_deassert_attn_lines(pdev, 0x3);
465 
466     //now we have for groups 0,1:
467     //             attn_bits: 0 0
468     //             attn_ack:  1 1
469     //             mask:      0 0
470     //             state:     1 1
471 
472     //simulate an increment of the attn producer by chip due to change in attn bits/attn_ack from monitored state.
473     def_sb->atten_status_block.attn_bits_index = mm_cpu_to_le16(mm_le16_to_cpu(def_sb->atten_status_block.attn_bits_index) + 1) ;
474 
475     //Call the dbg ISR routine to simulate lines de-asserted at the default sb DPC only!
476 	dbg_isr(pdev, 0x1);
477 
478     //Set everything back to zero to start all over again!
479     dbg_zero_all_attn(pdev);
480 
481     // **************************   Create an unacceptable state! ***************************
482 
483     //assert groups: 0,1
484     dbg_assert_attn_lines(pdev, 0x3);
485 
486     //simulate as if the chip wrote 1 1 to the attn_ack
487     dbg_ack_assert_attn_lines(pdev, 0x3);
488 
489     //now we have for groups 0,1:
490     //             attn_bits: 1 1
491     //             attn_ack:  1 1
492     //             mask:      0 0
493     //             state:     0 0
494 
495     def_sb->atten_status_block.attn_bits_index = mm_cpu_to_le16(mm_le16_to_cpu(def_sb->atten_status_block.attn_bits_index) + 1);
496 
497     dbg_isr(pdev, 0x1);
498 }
499