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 */
dbg_zero_all_attn(lm_device_t * pdev)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 */
dbg_assert_attn_lines(lm_device_t * pdev,u16_t lines_to_assert)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 */
dbg_deassert_attn_lines(lm_device_t * pdev,u16_t lines_to_deassert)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 */
dbg_ack_assert_attn_lines(lm_device_t * pdev,u16_t assert_lines_to_ack)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
dbg_change_sb_index(lm_device_t * pdev,u8_t rss_id)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 */
dbg_def_sb_dpc(lm_device_t * pdev)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 */
dbg_sb_dpc(lm_device_t * pdev,u8_t rss_id)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
dbg_isr(lm_device_t * pdev,u32_t intr_status)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
dbg_sb_ints_test_suite(lm_device_t * pdev)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