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