1 /*******************************************************************************
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright 2014 QLogic Corporation
22 * The contents of this file are subject to the terms of the
23 * QLogic End User License (the "License").
24 * You may not use this file except in compliance with the License.
25 *
26 * You can obtain a copy of the License at
27 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
28 * QLogic_End_User_Software_License.txt
29 * See the License for the specific language governing permissions
30 * and limitations under the License.
31 *
32 *
33 * Module Description:
34 *
35 *
36 * History:
37 * 11/26/07 Alon Elhanani Inception.
38 ******************************************************************************/
39
40 #include "lm5710.h"
41 #include "license.h"
42 #include "mcp_shmem.h"
43 #include "debug.h"
44
45 #define MCP_EMUL_TIMEOUT 200000 /* 200 ms (in us) */
46 #define MCP_TIMEOUT 5000000 /* 5 seconds (in us) */
47 #define MCP_ONE_TIMEOUT 100000 /* 100 ms (in us) */
48
49 /**
50 * Waits for MCP_ONE_TIMEOUT or MCP_ONE_TIMEOUT*10,
51 * depending on the HW type.
52 *
53 * @param pdev
54 */
lm_mcp_wait_one(IN struct _lm_device_t * pdev)55 static __inline void lm_mcp_wait_one (
56 IN struct _lm_device_t * pdev
57 )
58 {
59 /* special handling for emulation and FPGA,
60 wait 10 times longer */
61 if (CHIP_REV_IS_SLOW(pdev)) {
62 mm_wait(pdev, MCP_ONE_TIMEOUT*10);
63 } else {
64 mm_wait(pdev, MCP_ONE_TIMEOUT);
65 }
66 }
67
68
69 #if !defined(b710)
70
71 /**
72 * Prepare CLP to MCP reset.
73 *
74 * @param pdev Device handle
75 * @param magic_val Old value of `magic' bit.
76 */
lm_clp_reset_prep(IN struct _lm_device_t * pdev,OUT u32_t * magic_val)77 void lm_clp_reset_prep(
78 IN struct _lm_device_t * pdev,
79 OUT u32_t * magic_val
80 )
81 {
82 u32_t val = 0;
83 u32_t offset;
84
85 #define SHARED_MF_CLP_MAGIC 0x80000000 /* `magic' bit */
86
87 ASSERT_STATIC(sizeof(struct mf_cfg) % sizeof(u32_t) == 0);
88
89 /* Do some magic... */
90 offset = OFFSETOF(mf_cfg_t, shared_mf_config.clp_mb);
91 LM_MFCFG_READ(pdev, offset, &val);
92 *magic_val = val & SHARED_MF_CLP_MAGIC;
93 LM_MFCFG_WRITE(pdev, offset, val | SHARED_MF_CLP_MAGIC);
94 }
95
96 /**
97 * Restore the value of the `magic' bit.
98 *
99 * @param pdev Device handle.
100 * @param magic_val Old value of the `magic' bit.
101 */
lm_clp_reset_done(IN struct _lm_device_t * pdev,IN u32_t magic_val)102 void lm_clp_reset_done(
103 IN struct _lm_device_t * pdev,
104 IN u32_t magic_val
105 )
106 {
107 u32_t val = 0;
108 u32_t offset;
109
110 /* Restore the `magic' bit value... */
111 offset = OFFSETOF(mf_cfg_t, shared_mf_config.clp_mb);
112 LM_MFCFG_READ(pdev, offset, &val);
113 LM_MFCFG_WRITE(pdev, offset, (val & (~SHARED_MF_CLP_MAGIC)) | magic_val);
114 }
115
116 #endif // !b710
117
lm_is_mcp_detected(IN struct _lm_device_t * pdev)118 u8_t lm_is_mcp_detected(
119 IN struct _lm_device_t *pdev
120 )
121 {
122 return pdev->hw_info.mcp_detected;
123 }
124
125 /**
126 * @Description
127 * Prepares for MCP reset: takes care of CLP configurations
128 * (saves it aside to resotre later) .
129 *
130 * @param pdev
131 * @param magic_val Old value of 'magic' bit.
132 */
lm_reset_mcp_prep(lm_device_t * pdev,u32_t * magic_val)133 lm_status_t lm_reset_mcp_prep(lm_device_t *pdev, u32_t * magic_val)
134 {
135 u32_t shmem;
136 u32_t validity_offset;
137
138 /* Set `magic' bit in order to save MF config */
139 if (!CHIP_IS_E1(pdev))
140 {
141 lm_clp_reset_prep(pdev, magic_val);
142 }
143
144 /* Get shmem offset */
145 shmem = REG_RD(pdev, MISC_REG_SHARED_MEM_ADDR);
146 validity_offset = OFFSETOF(shmem_region_t, validity_map[0]);
147
148 /* Clear validity map flags */
149 if( shmem > 0 )
150 {
151 REG_WR(pdev, shmem + validity_offset, 0);
152 }
153
154 return LM_STATUS_SUCCESS;
155 }
156
lm_reset_mcp_comp(lm_device_t * pdev,u32_t magic_val)157 lm_status_t lm_reset_mcp_comp(lm_device_t *pdev, u32_t magic_val)
158 {
159 lm_status_t lm_status = LM_STATUS_SUCCESS;
160 u32_t shmem_sig_timeout = 0;
161 u32_t validity_offset = 0;
162 u32_t shmem = 0;
163 u32_t val = 0;
164 u32_t cnt = 0;
165
166 #ifdef _VBD_CMD_
167 return LM_STATUS_SUCCESS;
168 #endif
169
170 /* Get shmem offset */
171 shmem = REG_RD(pdev, MISC_REG_SHARED_MEM_ADDR);
172 if( shmem == 0 ) {
173 DbgMessage(pdev, FATAL, "Shmem 0 return failure\n");
174 lm_status = LM_STATUS_FAILURE;
175 goto exit_lbl;
176 }
177
178 ASSERT_STATIC(0 != MCP_ONE_TIMEOUT);
179
180 if (CHIP_REV_IS_EMUL(pdev))
181 shmem_sig_timeout = MCP_EMUL_TIMEOUT / MCP_ONE_TIMEOUT; // 200ms
182 else
183 shmem_sig_timeout = MCP_TIMEOUT / MCP_ONE_TIMEOUT; // 5sec
184
185 validity_offset = OFFSETOF(shmem_region_t, validity_map[0]);
186
187 /* Wait for MCP to come up */
188 for(cnt = 0; cnt < shmem_sig_timeout; cnt++)
189 {
190 /* TBD: its best to check validity map of last port. currently checks on port 0. */
191 val = REG_RD(pdev, shmem + validity_offset);
192 DbgMessage(pdev, INFORM, "shmem 0x%x validity map(0x%x)=0x%x\n", shmem, shmem + validity_offset, val);
193
194 /* check that shared memory is valid. */
195 if((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) ==
196 (SHR_MEM_VALIDITY_DEV_INFO|SHR_MEM_VALIDITY_MB)) {
197 break;
198 }
199
200 lm_mcp_wait_one(pdev);
201 }
202
203 DbgMessage(pdev, INFORM , "Cnt=%d Shmem validity map 0x%x\n",cnt, val);
204
205 /* Check that shared memory is valid. This indicates that MCP is up. */
206 if((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) !=
207 (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
208 {
209 DbgMessage(pdev, FATAL, "Shmem signature not present. MCP is not up !!\n");
210 lm_status = LM_STATUS_FAILURE;
211 goto exit_lbl;
212 }
213
214 exit_lbl:
215
216 if (!CHIP_IS_E1(pdev))
217 {
218 /* Restore `magic' bit value */
219 lm_clp_reset_done(pdev, magic_val);
220 }
221
222 return lm_status;
223 }
224
lm_reset_mcp(IN struct _lm_device_t * pdev)225 lm_status_t lm_reset_mcp(
226 IN struct _lm_device_t *pdev
227 )
228 {
229
230 u32_t magic_val = 0;
231 u32_t val, retries=0;
232 lm_status_t lm_status = LM_STATUS_SUCCESS;
233
234 DbgMessage(pdev, VERBOSE, "Entered lm_reset_mcp\n");
235
236 lm_reset_mcp_prep(pdev, &magic_val);
237
238 /* wait up to 3 seconds to get all locks. Whatsoever, reset mcp afterwards */
239 do {
240 REG_WR(pdev, MISC_REG_DRIVER_CONTROL_15 + 4, 0xffffffff);
241 val = REG_RD(pdev, MISC_REG_DRIVER_CONTROL_15);
242 mm_wait(pdev, 1);
243 } while ((val != 0xffffffff) && (++retries < 3000000));
244
245 /* Reset the MCP */
246 REG_WR(pdev, GRCBASE_MISC+ MISC_REGISTERS_RESET_REG_2_CLEAR,
247 MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE |
248 MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B |
249 MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU |
250 MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE);
251
252 /* release the locks taken */
253 REG_WR(pdev, MISC_REG_DRIVER_CONTROL_15, 0xffffffff);
254
255 mm_wait(pdev, 100000);
256
257 // No need to wait here a minimum time, since the mcp_comp will
258 // returns only when mcp is ready.
259 lm_status = lm_reset_mcp_comp(pdev, magic_val);
260
261 return lm_status;
262 }
263
264 //acquire split MCP access lock register
265 lm_status_t
acquire_split_alr(lm_device_t * pdev)266 acquire_split_alr(
267 lm_device_t *pdev)
268 {
269 lm_status_t lm_status;
270 u32_t j, cnt;
271 u32_t val_wr, val_rd;
272
273 DbgMessage(pdev, INFORM, "acquire_split_alr() - %d START!\n", FUNC_ID(pdev) );
274
275 //Adjust timeout for our emulation needs
276 cnt = 30000 * 100;
277 val_wr = 1UL << 31;
278 val_rd = 0;
279
280 //acquire lock using mcpr_access_lock SPLIT register
281
282 for(j = 0; j < cnt*10; j++)
283 {
284 REG_WR(pdev, GRCBASE_MCP + 0x9c, val_wr);
285 val_rd = REG_RD(pdev, GRCBASE_MCP + 0x9c);
286 if (val_rd & (1UL << 31))
287 {
288 break;
289 }
290
291 mm_wait(pdev, 5);
292 }
293
294 if(val_rd & (1UL << 31))
295 {
296 lm_status = LM_STATUS_SUCCESS;
297 }
298 else
299 {
300 DbgBreakMsg("Cannot get access to nvram interface.\n");
301
302 lm_status = LM_STATUS_BUSY;
303 }
304
305 DbgMessage(pdev, INFORM, "acquire_split_alr() - %d END!\n", FUNC_ID(pdev) );
306
307 return lm_status;
308 }
309
310 //Release split MCP access lock register
311 void
release_split_alr(lm_device_t * pdev)312 release_split_alr(
313 lm_device_t *pdev)
314 {
315 u32_t val = 0;
316
317 DbgMessage(pdev, INFORM, "release_split_alr() - %d START!\n", FUNC_ID(pdev) );
318
319 //This is only a sanity check, can remove later in free build.
320 val= REG_RD(pdev, GRCBASE_MCP + 0x9c);
321 DbgBreakIf(!(val & (1L << 31)));
322
323 val = 0;
324
325 //release mcpr_access_lock SPLIT register
326 REG_WR(pdev, GRCBASE_MCP + 0x9c, val);
327 DbgMessage(pdev, INFORM, "release_split_alr() - %d END!\n", FUNC_ID(pdev) );
328 } /* release_nvram_lock */
329
330 /*******************************************************************************
331 * Description:
332 * sends the mcp a keepalive to known registers
333 * Return:
334 ******************************************************************************/
lm_send_driver_pulse(lm_device_t * pdev)335 lm_status_t lm_send_driver_pulse( lm_device_t* pdev )
336 {
337 u32_t msg_code = 0;
338 u32_t drv_pulse = 0;
339 u32_t mcp_pulse = 0;
340
341 if CHK_NULL(pdev)
342 {
343 return LM_STATUS_INVALID_PARAMETER ;
344 }
345
346 if GET_FLAGS(pdev->params.test_mode, TEST_MODE_NO_MCP)
347 {
348 return LM_STATUS_SUCCESS ;
349 }
350
351 ++pdev->vars.drv_pulse_wr_seq;
352 msg_code = pdev->vars.drv_pulse_wr_seq & DRV_PULSE_SEQ_MASK;
353 if (GET_FLAGS(pdev->params.test_mode, TEST_MODE_DRIVER_PULSE_ALWAYS_ALIVE)
354 || IS_DRIVER_PULSE_ALWAYS_ALIVE(pdev))
355 {
356 SET_FLAGS( msg_code, DRV_PULSE_ALWAYS_ALIVE ) ;
357 }
358
359 drv_pulse = msg_code;
360
361 LM_SHMEM_WRITE(pdev,
362 OFFSETOF(shmem_region_t,
363 func_mb[FUNC_MAILBOX_ID(pdev)].drv_pulse_mb),msg_code);
364 LM_SHMEM_READ(pdev,
365 OFFSETOF(shmem_region_t,
366 func_mb[FUNC_MAILBOX_ID(pdev)].mcp_pulse_mb),
367 &mcp_pulse);
368
369 mcp_pulse&= MCP_PULSE_SEQ_MASK ;
370 /* The delta between driver pulse and mcp response
371 * should be 1 (before mcp response) or 0 (after mcp response)
372 */
373 if ((drv_pulse != mcp_pulse) &&
374 (drv_pulse != ((mcp_pulse + 1) & MCP_PULSE_SEQ_MASK)))
375 {
376 DbgMessage(pdev, FATAL, "drv_pulse (0x%x) != mcp_pulse (0x%x)\n", drv_pulse, mcp_pulse );
377 return LM_STATUS_FAILURE ;
378 }
379 DbgMessage(pdev, INFORMi , "Sent driver pulse cmd to MCP\n");
380 return LM_STATUS_SUCCESS ;
381 }
382 /*******************************************************************************
383 * Description:
384 * Set driver pulse to MCP to always alive
385 * Return:
386 ******************************************************************************/
lm_driver_pulse_always_alive(struct _lm_device_t * pdev)387 void lm_driver_pulse_always_alive(struct _lm_device_t* pdev)
388 {
389 if CHK_NULL(pdev)
390 {
391 return;
392 }
393 if GET_FLAGS(pdev->params.test_mode, TEST_MODE_NO_MCP)
394 {
395 return ;
396 }
397 // Reset the MCP pulse to always alive
398 LM_SHMEM_WRITE( pdev,
399 OFFSETOF(shmem_region_t,
400 func_mb[FUNC_MAILBOX_ID(pdev)].drv_pulse_mb),
401 DRV_PULSE_ALWAYS_ALIVE );
402 }
403 // entry that represents a function in the loader objcet
404 typedef struct _lm_loader_func_entry_t
405 {
406 u8_t b_loaded ; // does this function was loaded
407 } lm_loader_func_entry_t ;
408 // global object represents MCP - should be one per CHIP (boards)
409 typedef struct _lm_loader_path_obj_t
410 {
411 u32_t* lock_ctx ; // reserved - lock object context (currently not in use)
412 lm_loader_func_entry_t func_arr[E1H_FUNC_MAX] ; // array of function entries
413 } lm_loader_path_obj_t ;
414
415 typedef struct _lm_loader_obj_t
416 {
417 u8_t lock_owner ; // is a function acquire the lock? (1 based)
418 lm_loader_path_obj_t path_arr[MAX_PATH_NUM] ;
419 } lm_loader_obj_t ;
420
421 lm_loader_obj_t g_lm_loader = {0};
422
423 // TRUE if the function is first on the port
424 #define LM_LOADER_IS_FIRST_ON_PORT(_pdev,_path_idx,_port_idx) \
425 ( (FALSE == g_lm_loader.path_arr[_path_idx].func_arr[_port_idx+0].b_loaded) && \
426 (FALSE == g_lm_loader.path_arr[_path_idx].func_arr[_port_idx+2].b_loaded) && \
427 (FALSE == g_lm_loader.path_arr[_path_idx].func_arr[_port_idx+4].b_loaded) && \
428 (FALSE == g_lm_loader.path_arr[_path_idx].func_arr[_port_idx+6].b_loaded) )
429
430 // TRUE if the function is last on the port
431 #define LM_LOADER_IS_LAST_ON_PORT(_pdev,_path_idx,_port_idx) \
432 ( ( ( FUNC_ID(_pdev) == (_port_idx+0) ) ? TRUE : (FALSE == g_lm_loader.path_arr[_path_idx].func_arr[(_port_idx+0)].b_loaded) ) && \
433 ( ( FUNC_ID(_pdev) == (_port_idx+2) ) ? TRUE : (FALSE == g_lm_loader.path_arr[_path_idx].func_arr[(_port_idx+2)].b_loaded) ) && \
434 ( ( FUNC_ID(_pdev) == (_port_idx+4) ) ? TRUE : (FALSE == g_lm_loader.path_arr[_path_idx].func_arr[(_port_idx+4)].b_loaded) ) && \
435 ( ( FUNC_ID(_pdev) == (_port_idx+6) ) ? TRUE : (_port_idx == 0)?(FALSE == g_lm_loader.path_arr[_path_idx].func_arr[6].b_loaded):(FALSE == g_lm_loader.path_arr[_path_idx].func_arr[7].b_loaded) ) )
436
437
438 #define LM_LOADER_IS_FIRST_ON_COMMON(_pdev,_path_idx) (LM_LOADER_IS_FIRST_ON_PORT(_pdev,_path_idx,0) && LM_LOADER_IS_FIRST_ON_PORT(_pdev,_path_idx,1))
439 #define LM_LOADER_IS_LAST_ON_COMMON(_pdev,_path_idx) (LM_LOADER_IS_LAST_ON_PORT(_pdev,_path_idx,0) && LM_LOADER_IS_LAST_ON_PORT(_pdev,_path_idx,1))
440
441 #define LM_LOADER_IS_FIRST_ON_CHIP(_pdev) (LM_LOADER_IS_FIRST_ON_COMMON(_pdev,0) && LM_LOADER_IS_FIRST_ON_COMMON(_pdev,1))
442 #define LM_LOADER_IS_LAST_ON_CHIP(_pdev) (LM_LOADER_IS_LAST_ON_COMMON(_pdev,0) && LM_LOADER_IS_LAST_ON_COMMON(_pdev,1))
443
444 // Accessed only with lock!
445 // TRUE if any device is currently locked
446 #define LM_LOADER_IS_LOCKED(_chip_idx) ( (FALSE != g_lm_loader.lock_owner) )
447
448 /*
449 *Function Name:lm_loader_opcode_to_mcp_msg
450 *
451 *Parameters:
452 * b_lock - true if it is lock false if unlock
453 *Description:
454 * LM_LOADER_OPCODE_XXX-->DRV_MSG_CODE_XXX
455 *Returns:
456 *
457 */
lm_loader_opcode_to_mcp_msg(lm_loader_opcode opcode,u8_t b_lock)458 static u32_t lm_loader_opcode_to_mcp_msg( lm_loader_opcode opcode, u8_t b_lock )
459 {
460 u32_t mcp_msg = 0xffffffff ;
461
462 switch(opcode)
463 {
464 case LM_LOADER_OPCODE_LOAD:
465 mcp_msg = b_lock ? DRV_MSG_CODE_LOAD_REQ : DRV_MSG_CODE_LOAD_DONE ;
466 break;
467 case LM_LOADER_OPCODE_UNLOAD_WOL_EN:
468 mcp_msg = b_lock ? DRV_MSG_CODE_UNLOAD_REQ_WOL_EN : DRV_MSG_CODE_UNLOAD_DONE ;
469 break;
470 case LM_LOADER_OPCODE_UNLOAD_WOL_DIS:
471 mcp_msg = b_lock ? DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS : DRV_MSG_CODE_UNLOAD_DONE ;
472 break;
473 case LM_LOADER_OPCODE_UNLOAD_WOL_MCP:
474 mcp_msg = b_lock ? DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP : DRV_MSG_CODE_UNLOAD_DONE ;
475 break;
476 default:
477 DbgBreakIf(1) ;
478 break;
479 }
480 return mcp_msg ;
481 }
482 /*
483 *Function Name:mcp_resp_to_lm_loader_resp
484 *
485 *Parameters:
486 *
487 *Description:
488 * Translates mcp response to loader response FW_MSG_CODE_DRV_XXX->LM_LOADER_RESPONSE_XX
489 *Returns:
490 *
491 */
mcp_resp_to_lm_loader_resp(u32_t mcp_resp)492 lm_loader_response mcp_resp_to_lm_loader_resp( u32_t mcp_resp )
493 {
494 lm_loader_response resp = LM_LOADER_RESPONSE_INVALID ;
495 switch(mcp_resp)
496 {
497 case FW_MSG_CODE_DRV_LOAD_COMMON:
498 resp = LM_LOADER_RESPONSE_LOAD_COMMON ;
499 break;
500 case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
501 resp = LM_LOADER_RESPONSE_LOAD_COMMON_CHIP ;
502 break;
503 case FW_MSG_CODE_DRV_LOAD_PORT:
504 resp = LM_LOADER_RESPONSE_LOAD_PORT ;
505 break;
506 case FW_MSG_CODE_DRV_LOAD_FUNCTION:
507 resp = LM_LOADER_RESPONSE_LOAD_FUNCTION ;
508 break;
509 case FW_MSG_CODE_DRV_UNLOAD_COMMON:
510 resp = LM_LOADER_RESPONSE_UNLOAD_COMMON ;
511 break;
512 case FW_MSG_CODE_DRV_UNLOAD_PORT:
513 resp = LM_LOADER_RESPONSE_UNLOAD_PORT ;
514 break;
515 case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
516 resp = LM_LOADER_RESPONSE_UNLOAD_FUNCTION ;
517 break;
518 case FW_MSG_CODE_DRV_LOAD_DONE:
519 resp = LM_LOADER_RESPONSE_LOAD_DONE ;
520 break;
521 case FW_MSG_CODE_DRV_UNLOAD_DONE:
522 resp = LM_LOADER_RESPONSE_UNLOAD_DONE ;
523 break;
524 default:
525 DbgMessage(NULL, FATAL, "mcp_resp=0x%x\n", mcp_resp );
526 DbgBreakIf(1) ;
527 break;
528 }
529 return resp ;
530 }
531 // TBD - should it be the only indication??
532 #define IS_MCP_ON(_pdev) ( TEST_MODE_NO_MCP != GET_FLAGS(_pdev->params.test_mode, TEST_MODE_NO_MCP ) )
533
534 /*
535 *Function Name:lm_loader_lock
536 *
537 *Parameters:
538 *
539 *Description:
540 * sync loading/unloading of port/funciton
541 *Returns:
542 *
543 */
lm_loader_lock(lm_device_t * pdev,lm_loader_opcode opcode)544 lm_loader_response lm_loader_lock( lm_device_t* pdev, lm_loader_opcode opcode )
545 {
546 u32_t mcp_msg = 0;
547 u32_t param = 0;
548 u32_t fw_resp = 0;
549 lm_loader_response resp = LM_LOADER_RESPONSE_INVALID ;
550 lm_status_t lm_status = LM_STATUS_SUCCESS ;
551 u32_t wait_cnt = 0;
552 u32_t wait_cnt_limit = 5000;
553 const u32_t feature_flags = mm_get_feature_flags( pdev );
554 const u8_t is_suspend = opcode & LM_LOADER_OPCODE_UNLOAD_SUSPEND;
555
556 opcode &= LM_LOADER_OPCODE_MASK;
557 if( IS_MCP_ON(pdev) )
558 {
559 mcp_msg = lm_loader_opcode_to_mcp_msg( opcode, TRUE ) ;
560
561 // in case it is load (and not unload)
562 // send mfw LFA param
563 if ( DRV_MSG_CODE_LOAD_REQ == mcp_msg )
564 {
565 SET_FLAGS(param, DRV_MSG_CODE_LOAD_REQ_WITH_LFA );
566
567 // in case BFS, set FORCE_LFA flag on
568 if( GET_FLAGS( feature_flags, FEATURE_ETH_BOOTMODE_PXE ) ||
569 GET_FLAGS( feature_flags, FEATURE_ETH_BOOTMODE_ISCSI ) ||
570 GET_FLAGS( feature_flags, FEATURE_ETH_BOOTMODE_FCOE ) )
571 {
572 SET_FLAGS( param, DRV_MSG_CODE_LOAD_REQ_FORCE_LFA );
573 }
574
575 }
576 else if (is_suspend)
577 {
578 SET_FLAGS( param, DRV_MSG_CODE_UNLOAD_NON_D3_POWER ); //temporary
579 }
580
581 //we do this with no locks because acquiring the loader lock may take a long time (e.g in case another function takes a
582 //long time to initialize we will only get a response from the MCP when it's done). We don't need a lock because interrupts
583 //are disabled at this point and we won't get any IOCTLs.
584 lm_status = lm_mcp_cmd_send_recieve_non_atomic( pdev, lm_mcp_mb_header, mcp_msg, param, MCP_CMD_DEFAULT_TIMEOUT, &fw_resp ) ;
585 if ( LM_STATUS_SUCCESS == lm_status )
586 {
587 resp = mcp_resp_to_lm_loader_resp( fw_resp ) ;
588 pdev->vars.b_in_init_reset_flow = TRUE;
589 }
590 }
591 else // MCP_SIM
592 {
593 if( ERR_IF(PORT_ID(pdev) > 1) || ERR_IF(( FUNC_ID(pdev)) >= ARRSIZE(g_lm_loader.path_arr[PATH_ID(pdev)].func_arr)) )
594 {
595 DbgBreakMsg("Invalid PORT_ID/FUNC_ID\n");
596 return resp ;
597 }
598 do
599 {
600 MM_ACQUIRE_LOADER_LOCK();
601 if( LM_LOADER_IS_LOCKED(PATH_ID(pdev)) )
602 {
603 MM_RELEASE_LOADER_LOCK();
604 mm_wait(pdev,20) ;
605 DbgBreakIfAll( ++wait_cnt > wait_cnt_limit ) ;
606 }
607 else
608 {
609 // we'll release the lock when we are finish the work
610 break;
611 }
612 }while(1) ;
613 // Verify no one hold the lock, if so - it's a bug!
614 DbgBreakIf( 0 != g_lm_loader.lock_owner ) ;
615
616 // mark our current function id as owner
617 g_lm_loader.lock_owner = FUNC_ID(pdev)+1 ;
618
619 switch( opcode )
620 {
621 case LM_LOADER_OPCODE_LOAD:
622 if( LM_LOADER_IS_FIRST_ON_CHIP(pdev) )
623 {
624 resp = LM_LOADER_RESPONSE_LOAD_COMMON_CHIP;
625 }
626 else if( LM_LOADER_IS_FIRST_ON_COMMON(pdev,PATH_ID(pdev)) )
627 {
628 resp = LM_LOADER_RESPONSE_LOAD_COMMON ;
629 }
630 else if( LM_LOADER_IS_FIRST_ON_PORT( pdev, PATH_ID(pdev), PORT_ID(pdev) ) )
631 {
632 resp = LM_LOADER_RESPONSE_LOAD_PORT ;
633 }
634 else
635 {
636 resp = LM_LOADER_RESPONSE_LOAD_FUNCTION ;
637 }
638 break;
639 case LM_LOADER_OPCODE_UNLOAD_WOL_EN:
640 case LM_LOADER_OPCODE_UNLOAD_WOL_DIS:
641 case LM_LOADER_OPCODE_UNLOAD_WOL_MCP:
642 if( LM_LOADER_IS_LAST_ON_COMMON(pdev,PATH_ID(pdev)) )
643 {
644 resp = LM_LOADER_RESPONSE_UNLOAD_COMMON ;
645 }
646 else if( LM_LOADER_IS_LAST_ON_PORT( pdev, PATH_ID(pdev), PORT_ID(pdev) ) )
647 {
648 resp = LM_LOADER_RESPONSE_UNLOAD_PORT ;
649 }
650 else
651 {
652 resp = LM_LOADER_RESPONSE_UNLOAD_FUNCTION ;
653 }
654 break;
655 default:
656 DbgBreakIf(1) ;
657 break;
658 } // switch
659 pdev->vars.b_in_init_reset_flow = TRUE;
660 MM_RELEASE_LOADER_LOCK();
661 } // MCP_SIM
662 return resp ;
663 }
664 /*
665 *Function Name:lm_loader_unlock
666 *
667 *Parameters:
668 *
669 *Description:
670 * sync loading/unloading of port/funciton
671 *Returns:
672 *
673 */
lm_loader_unlock(struct _lm_device_t * pdev,lm_loader_opcode opcode,OPTIONAL const u32_t * IN p_param)674 lm_loader_response lm_loader_unlock( struct _lm_device_t *pdev, lm_loader_opcode opcode, OPTIONAL const u32_t* IN p_param )
675 {
676 u32_t mcp_msg = 0 ;
677 u32_t param = p_param ? (*p_param) : 0 ;
678 lm_loader_response resp = LM_LOADER_RESPONSE_INVALID ;
679 u32_t fw_resp = 0 ;
680 lm_status_t lm_status = LM_STATUS_SUCCESS ;
681 u8_t b_new_state = 0xff ;
682 if CHK_NULL(pdev)
683 {
684 return resp ;
685 }
686 opcode &= LM_LOADER_OPCODE_MASK;
687 if( IS_MCP_ON(pdev) )
688 {
689 mcp_msg = lm_loader_opcode_to_mcp_msg( opcode, FALSE );
690 //we do this with no locks because acquiring the loader lock may take a long time (e.g in case another function takes a
691 //long time to initialize we will only get a response from the MCP when it's done). We don't need a lock because interrupts
692 //are disabled at this point and we won't get any IOCTLs.
693 lm_status = lm_mcp_cmd_send_recieve_non_atomic(pdev, lm_mcp_mb_header, mcp_msg, param, MCP_CMD_DEFAULT_TIMEOUT, &fw_resp ) ;
694 if ( LM_STATUS_SUCCESS == lm_status )
695 {
696 resp = mcp_resp_to_lm_loader_resp( fw_resp ) ;
697 pdev->vars.b_in_init_reset_flow = FALSE;
698 }
699 }
700 else // MCP_SIM
701 {
702 MM_ACQUIRE_LOADER_LOCK();
703
704 // Verify current function id is the owner
705 DbgBreakIf( g_lm_loader.lock_owner != FUNC_ID(pdev)+1 ) ;
706
707 switch( opcode )
708 {
709 case LM_LOADER_OPCODE_LOAD:
710 b_new_state = TRUE ;
711 resp = LM_LOADER_RESPONSE_LOAD_DONE ;
712 break;
713 case LM_LOADER_OPCODE_UNLOAD_WOL_EN:
714 case LM_LOADER_OPCODE_UNLOAD_WOL_DIS:
715 case LM_LOADER_OPCODE_UNLOAD_WOL_MCP:
716 b_new_state = FALSE ;
717 resp = LM_LOADER_RESPONSE_UNLOAD_DONE ;
718 break;
719 default:
720 DbgBreakIf(1) ;
721 break;
722 } // switch
723 // verify new state differs than current
724 DbgBreakIf(g_lm_loader.path_arr[PATH_ID(pdev)].func_arr[FUNC_ID(pdev)].b_loaded == b_new_state);
725
726 // assign new state
727 g_lm_loader.path_arr[PATH_ID(pdev)].func_arr[FUNC_ID(pdev)].b_loaded = b_new_state ;
728
729 // mark we don't own the lock anymore
730 g_lm_loader.lock_owner = FALSE ;
731
732 pdev->vars.b_in_init_reset_flow = FALSE;
733 MM_RELEASE_LOADER_LOCK();
734 } // MCP_SIM
735 return resp ;
736 }
737
738 /* Used for simulating a mcp reset where the mcp no longer knows the state of the uploaded drivers... */
lm_loader_reset(struct _lm_device_t * pdev)739 void lm_loader_reset ( struct _lm_device_t *pdev )
740 {
741 mm_memset(&g_lm_loader, 0, sizeof(g_lm_loader));
742 }
743
744 /*
745 *Function Name:lm_mcp_cmd_init
746 *
747 *Parameters:
748 *
749 *Description:
750 * initiate sequence of mb + verify boot code version
751 *Returns:
752 *
753 */
lm_mcp_cmd_init(struct _lm_device_t * pdev)754 lm_status_t lm_mcp_cmd_init( struct _lm_device_t *pdev)
755 {
756 u32_t val = 0 ;
757 u32_t bc_rev = 0 ;
758 u32_t offset = 0 ;
759 u8_t func_mb_id = 0;
760
761 DbgMessage(pdev, INFORMi , "### mcp_cmd_init\n");
762
763 if CHK_NULL(pdev)
764 {
765 return LM_STATUS_FAILURE ;
766 }
767
768 // we are on NO_MCP mode - nothing to do
769 if( 0 != GET_FLAGS(pdev->params.test_mode, TEST_MODE_NO_MCP ) )
770 {
771 return LM_STATUS_SUCCESS ;
772 }
773
774 //validtae bc version
775 bc_rev = LM_GET_BC_REV_MAJOR(pdev);
776
777 if (bc_rev < BC_REV_SUPPORTED)
778 {
779 DbgMessage(pdev, FATAL,"bc version is less than 0x%x equal to 0x%x.\n", BC_REV_SUPPORTED, bc_rev );
780 DbgBreakMsg("Please upgrade the bootcode version.\n");
781 // TODO add event log
782 return LM_STATUS_INVALID_PARAMETER;
783 }
784
785 // enable optic module verification according to BC version
786 if (bc_rev >= REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL)
787 {
788 SET_FLAGS(pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY);
789 }
790
791 if (bc_rev >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL)
792 {
793 SET_FLAGS(pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY);
794 }
795
796 if (bc_rev >= REQ_BC_VER_4_VRFY_AFEX_SUPPORTED)
797 {
798 SET_FLAGS(pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_BC_SUPPORTS_AFEX);
799 }
800
801 if (bc_rev >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED)
802 {
803 SET_FLAGS(pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED);
804 }
805
806 if (bc_rev >= REQ_BC_VER_4_MT_SUPPORTED)
807 {
808 SET_FLAGS(pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_MT_SUPPORT);
809 }
810
811 // regular MCP mode
812 func_mb_id = pdev->params.pfunc_mb_id;
813
814 // read first seq number from shared memory
815 offset = OFFSETOF(shmem_region_t, func_mb[func_mb_id].drv_mb_header);
816 LM_SHMEM_READ(pdev, offset, &val);
817 pdev->vars.fw_wr_seq = (u16_t)(val & DRV_MSG_SEQ_NUMBER_MASK);
818
819 // read current mcp_pulse value
820 offset = OFFSETOF(shmem_region_t,func_mb[func_mb_id].mcp_pulse_mb) ;
821 LM_SHMEM_READ(pdev, offset ,&val);
822 pdev->vars.drv_pulse_wr_seq = (u16_t)(val & MCP_PULSE_SEQ_MASK);
823
824 return LM_STATUS_SUCCESS;
825 }
826
lm_mcp_set_mf_bw(struct _lm_device_t * pdev,IN u8_t min_bw,IN u8_t max_bw)827 lm_status_t lm_mcp_set_mf_bw(struct _lm_device_t *pdev, IN u8_t min_bw, IN u8_t max_bw)
828 {
829 u32_t minmax_param = 0;
830 u32_t resp = 0;
831 lm_status_t lm_status = LM_STATUS_SUCCESS;
832 const u32_t bc_rev = LM_GET_BC_REV_MAJOR(pdev);
833
834 //if in no MCP mode, don't do anything
835 if(!lm_is_mcp_detected(pdev))
836 {
837 DbgMessage(pdev, WARNmi, "No MCP detected.\n");
838 return LM_STATUS_SUCCESS;
839 }
840 //if bootcode is less then REQ_BC_VER_4_SET_MF_BW, fail
841 if( bc_rev < REQ_BC_VER_4_SET_MF_BW )
842 {
843 DbgMessage(pdev, WARNmi, "Invalid bootcode version.\n");
844 return LM_STATUS_INVALID_PARAMETER;
845 }
846 //if not E2 or not MF mode, fail
847 if(CHIP_IS_E1x(pdev) || !IS_MULTI_VNIC(pdev))
848 {
849 DbgMessage(pdev, WARNmi, "Device is E1/E1.5 or in SF mode.\n");
850 return LM_STATUS_INVALID_PARAMETER;
851 }
852 //if the parameters are not valid, fail
853 if (max_bw > 100)
854 {
855 DbgMessage(pdev, WARNmi, "Invalid parameters.\n");
856 return LM_STATUS_INVALID_PARAMETER;
857 }
858 //build MCP command parameter from min_bw/max_bw
859 //we use FUNC_MF_CFG_MIN_BW_SHIFT because the param structure is supposed to
860 //be equivalent for this opcode and for the DCC opcode, but there is no define
861 //for this opcode.
862 ASSERT_STATIC(FUNC_MF_CFG_MIN_BW_MASK == DRV_MSG_CODE_SET_MF_BW_MIN_MASK);
863 ASSERT_STATIC(FUNC_MF_CFG_MAX_BW_MASK == DRV_MSG_CODE_SET_MF_BW_MAX_MASK);
864 minmax_param = (min_bw << FUNC_MF_CFG_MIN_BW_SHIFT)|
865 (max_bw << FUNC_MF_CFG_MAX_BW_SHIFT);
866
867 //call lm_mcp_cmd_send_recieve with DRV_MSG_CODE_SET_MF_BW opcode and the parameter
868 lm_mcp_cmd_send_recieve(pdev, lm_mcp_mb_header, DRV_MSG_CODE_SET_MF_BW, minmax_param, MCP_CMD_DEFAULT_TIMEOUT, &resp);
869
870 //make sure that the response is FW_MSG_CODE_SET_MF_BW_SENT
871 if(resp != FW_MSG_CODE_SET_MF_BW_SENT)
872 {
873 DbgBreakIf(resp != FW_MSG_CODE_SET_MF_BW_SENT);
874 return LM_STATUS_FAILURE;
875 }
876
877 //return what lm_mcp_cmd_send_recieve returned
878 return lm_status;
879 }
880
881 /*
882 *Function Name:lm_mcp_cmd_send
883 *
884 *Parameters:
885 *
886 *Description:
887 * send
888 *Returns:
889 *
890 */
lm_mcp_cmd_send(struct _lm_device_t * pdev,lm_mcp_mb_type mb_type,u32_t drv_msg,u32_t param)891 lm_status_t lm_mcp_cmd_send( struct _lm_device_t *pdev, lm_mcp_mb_type mb_type, u32_t drv_msg, u32_t param )
892 {
893 u16_t* p_seq = NULL ;
894 u32_t offset = 0 ;
895 u32_t drv_mask = 0 ;
896 const u8_t func_mb_id = pdev->params.pfunc_mb_id;
897
898 DbgMessage(pdev, INFORMi , "### mcp_cmd_send mb_type=0x%x drv_msg=0x%x param=0x%x\n", mb_type, drv_msg, param );
899
900 // we are on NO_MCP mode - nothing to do
901 if( 0 != GET_FLAGS(pdev->params.test_mode, TEST_MODE_NO_MCP ) )
902 {
903 return LM_STATUS_SUCCESS ;
904 }
905
906 switch( mb_type )
907 {
908 case lm_mcp_mb_header:
909 p_seq = &pdev->vars.fw_wr_seq ;
910 drv_mask = DRV_MSG_SEQ_NUMBER_MASK ;
911 offset = OFFSETOF(shmem_region_t, func_mb[func_mb_id].drv_mb_header) ;
912 /* Write the parameter to the mcp */
913 if (p_seq)
914 {
915 LM_SHMEM_WRITE(pdev,OFFSETOF(shmem_region_t, func_mb[func_mb_id].drv_mb_param),param);
916 }
917 break;
918
919 case lm_mcp_mb_pulse:
920 p_seq = &pdev->vars.drv_pulse_wr_seq ;
921 drv_mask = DRV_PULSE_SEQ_MASK ;
922 offset = OFFSETOF(shmem_region_t, func_mb[func_mb_id].mcp_pulse_mb) ;
923 break;
924 case lm_mcp_mb_param:
925 default:
926 break;
927 }
928
929 if CHK_NULL( p_seq )
930 {
931 return LM_STATUS_INVALID_PARAMETER ;
932 }
933
934 // incremant sequence
935 ++(*p_seq);
936
937 // prepare message
938 drv_msg |= ( (*p_seq) & drv_mask );
939
940 LM_SHMEM_WRITE(pdev,offset,drv_msg);
941
942 DbgMessage(pdev, INFORMi , "mcp_cmd_send: Sent driver load cmd to MCP at 0x%x\n", drv_msg);
943
944 return LM_STATUS_SUCCESS ;
945 }
946
947 /*
948 *Function Name:lm_mcp_cmd_response
949 *
950 *Parameters:
951 * TBD - add timeout value
952 *Description:
953 * assumption - only one request can be sent simultaneously
954 *Returns:
955 *
956 */
lm_mcp_cmd_response(struct _lm_device_t * pdev,lm_mcp_mb_type mcp_mb_type,u32_t drv_msg,u32_t timeout,OUT u32_t * p_fw_resp)957 lm_status_t lm_mcp_cmd_response( struct _lm_device_t *pdev,
958 lm_mcp_mb_type mcp_mb_type,
959 u32_t drv_msg,
960 u32_t timeout,
961 OUT u32_t* p_fw_resp )
962 {
963 u16_t* p_seq = NULL ;
964 u32_t offset = 0 ;
965 u32_t drv_mask = 0 ;
966 u32_t fw_mask = 0 ;
967 u32_t cnt = 0 ;
968 u32_t wait_itr = 0 ;
969 u32_t resp_mask = 0xffffffff ;
970 lm_status_t lm_status = LM_STATUS_SUCCESS ;
971 const u8_t func_mb_id = pdev->params.pfunc_mb_id;
972
973 UNREFERENCED_PARAMETER_(timeout);
974
975 DbgMessage(pdev, INFORMi, "### mcp_cmd_response mb_type=0x%x drv_msg=0x%x\n", mcp_mb_type, drv_msg );
976
977 if ( CHK_NULL(p_fw_resp) )
978 {
979 return LM_STATUS_FAILURE ;
980 }
981
982 switch( mcp_mb_type )
983 {
984 case lm_mcp_mb_header:
985 p_seq = &pdev->vars.fw_wr_seq ;
986 drv_mask = DRV_MSG_SEQ_NUMBER_MASK ;
987 fw_mask = FW_MSG_SEQ_NUMBER_MASK ;
988 resp_mask = FW_MSG_CODE_MASK ;
989 offset = OFFSETOF(shmem_region_t, func_mb[func_mb_id].fw_mb_header) ;
990 break;
991
992 // TBD - is it needed ??
993 case lm_mcp_mb_pulse:
994 p_seq = &pdev->vars.drv_pulse_wr_seq ;
995 drv_mask = DRV_PULSE_SEQ_MASK ;
996 fw_mask = MCP_PULSE_SEQ_MASK ;
997 offset = OFFSETOF(shmem_region_t, func_mb[func_mb_id].mcp_pulse_mb) ;
998 break;
999
1000 case lm_mcp_mb_param:
1001 default:
1002 break;
1003 }
1004
1005 if CHK_NULL( p_seq )
1006 {
1007 return LM_STATUS_INVALID_PARAMETER ;
1008 }
1009
1010 lm_status = LM_STATUS_TIMEOUT ;
1011
1012 // Wait for reply 5 sec per unloading function
1013 //TODO exponential back off
1014 wait_itr = 240 * FW_ACK_NUM_OF_POLL * PORT_MAX * (u32_t)(IS_MULTI_VNIC(pdev) ? MAX_VNIC_NUM : 1);
1015 for(cnt = 0; cnt < wait_itr; cnt++)
1016 {
1017 mm_wait(pdev, FW_ACK_POLL_TIME_MS * 50);
1018
1019 LM_SHMEM_READ(pdev, offset, p_fw_resp);
1020
1021 if(( (*p_fw_resp) & fw_mask) == ( (*p_seq) & drv_mask))
1022 {
1023 lm_status = LM_STATUS_SUCCESS ;
1024 break;
1025 }
1026 }
1027
1028 *p_fw_resp = (*p_fw_resp & resp_mask);
1029
1030 return lm_status ;
1031 }
1032
lm_mcp_cmd_send_recieve_non_atomic(struct _lm_device_t * pdev,lm_mcp_mb_type mcp_mb_type,u32_t drv_msg,u32_t param,u32_t timeout,OUT u32_t * p_fw_resp)1033 lm_status_t lm_mcp_cmd_send_recieve_non_atomic( struct _lm_device_t *pdev,
1034 lm_mcp_mb_type mcp_mb_type,
1035 u32_t drv_msg,
1036 u32_t param,
1037 u32_t timeout,
1038 OUT u32_t* p_fw_resp )
1039 {
1040 lm_status_t lm_status = LM_STATUS_FAILURE;
1041 u32_t val = 0;
1042
1043 lm_status = lm_mcp_cmd_send( pdev, mcp_mb_type, drv_msg, param) ;
1044
1045 if( LM_STATUS_SUCCESS != lm_status )
1046 {
1047 val = lm_mcp_check(pdev);
1048 DbgMessage(pdev, FATAL, "mcp_cmd_send_and_recieve: mcp_cmd_send drv_msg=0x%x failed. lm_status=0x%x mcp_check=0x%x\n", drv_msg, lm_status, val);
1049 DbgBreakMsg("mcp_cmd_send_and_recieve: mcp_cmd_send failed!\n");
1050 return lm_status;
1051 }
1052
1053 DbgMessage(pdev, INFORMi , "mcp_cmd_send_and_recieve: Sent driver cmd=0x%x to MCP\n", drv_msg );
1054
1055 lm_status = lm_mcp_cmd_response( pdev, mcp_mb_type, drv_msg, timeout, p_fw_resp ) ;
1056
1057 if( LM_STATUS_SUCCESS != lm_status )
1058 {
1059 val = lm_mcp_check(pdev);
1060 DbgMessage(pdev, FATAL, "mcp_cmd_send_and_recieve: mcp_cmd_response drv_msg=0x%x failed. lm_status=0x%x mcp_check=0x%x\n", drv_msg, lm_status, val);
1061 DbgBreakMsg("mcp_cmd_send_and_recieve: mcp_cmd_response failed!\n");
1062 return lm_status;
1063 }
1064
1065 DbgMessage(pdev, INFORMi , "mcp_cmd_send_and_recieve: Got response 0x%x from MCP\n", *p_fw_resp );
1066
1067 return LM_STATUS_SUCCESS;
1068 }
1069
1070 /*
1071 *Function Name:lm_mcp_cmd_send_recieve
1072 *
1073 *Parameters:
1074 *
1075 *Description:
1076 *
1077 *Returns: lm_status_t
1078 *
1079 */
lm_mcp_cmd_send_recieve(struct _lm_device_t * pdev,lm_mcp_mb_type mcp_mb_type,u32_t drv_msg,u32_t param,u32_t timeout,OUT u32_t * p_fw_resp)1080 lm_status_t lm_mcp_cmd_send_recieve( struct _lm_device_t *pdev,
1081 lm_mcp_mb_type mcp_mb_type,
1082 u32_t drv_msg,
1083 u32_t param,
1084 u32_t timeout,
1085 OUT u32_t* p_fw_resp )
1086 {
1087 lm_status_t lm_status = LM_STATUS_SUCCESS ;
1088
1089 MM_ACQUIRE_MCP_LOCK(pdev);
1090
1091 lm_status = lm_mcp_cmd_send_recieve_non_atomic(pdev, mcp_mb_type, drv_msg, param, timeout, p_fw_resp);
1092
1093 MM_RELEASE_MCP_LOCK(pdev);
1094
1095 return lm_status ;
1096 }
1097
1098
1099 // check if mcp program counter is advancing, In case it doesn't return the value in case it does, return 0
lm_mcp_check(struct _lm_device_t * pdev)1100 u32_t lm_mcp_check( struct _lm_device_t *pdev)
1101 {
1102 static u32_t const offset = MCP_REG_MCPR_CPU_PROGRAM_COUNTER ;
1103 u32_t reg = 0 ;
1104 u32_t i = 0 ;
1105
1106 reg = REG_RD(pdev, offset);
1107
1108 for( i = 0; i<4; i++ )
1109 {
1110 if( REG_RD(pdev, offset) != reg )
1111 {
1112 return 0; // OK
1113 }
1114 }
1115 return reg; // mcp is hang on this value as program counter!
1116 }
1117
1118 /**lm_mcp_cli_idx_to_drv_cap_flag
1119 * Get the flag to set in drv_capabilities_flag for a given LM
1120 * client.
1121 *
1122 * @param cli_id the LM client index.
1123 *
1124 * @return u32_t the appropriate flag for cli_id, or 0 if there
1125 * is no matching flag.
1126 */
lm_mcp_cli_idx_to_drv_cap_flag(IN const lm_cli_idx_t cli_id)1127 static u32_t lm_mcp_cli_idx_to_drv_cap_flag(IN const lm_cli_idx_t cli_id)
1128 {
1129 switch(cli_id)
1130 {
1131 case LM_CLI_IDX_NDIS:
1132 return DRV_FLAGS_CAPABILITIES_LOADED_L2;
1133 case LM_CLI_IDX_ISCSI:
1134 return DRV_FLAGS_CAPABILITIES_LOADED_ISCSI;
1135 case LM_CLI_IDX_FCOE:
1136 return DRV_FLAGS_CAPABILITIES_LOADED_FCOE;
1137 case LM_CLI_IDX_MAX://may happen for UM clients that have no matching LM client, such as diag.
1138 return 0;
1139 case LM_CLI_IDX_FWD://fallthrough - this client has no bind/unbind flow and no matching UM client
1140 case LM_CLI_IDX_OOO://fallthrough - this client has no bind/unbind flow and no matching UM client
1141 default:
1142 DbgBreakMsg("Invalid client type");
1143 return 0;
1144 }
1145 }
1146
lm_mcp_indicate_client_imp(struct _lm_device_t * pdev,IN const lm_cli_idx_t cli_id,IN const u8_t b_bind)1147 void lm_mcp_indicate_client_imp(struct _lm_device_t *pdev, IN const lm_cli_idx_t cli_id, IN const u8_t b_bind )
1148 {
1149 const u32_t drv_cap_client = lm_mcp_cli_idx_to_drv_cap_flag(cli_id);
1150 const u32_t func_mb_id = FUNC_MAILBOX_ID(pdev);
1151 const u32_t shmem_offset = OFFSETOF(shmem2_region_t, drv_capabilities_flag[func_mb_id]);
1152 u32_t drv_cap_shmem = 0;
1153
1154 if (CHIP_IS_E1x(pdev) ||
1155 !LM_SHMEM2_HAS(pdev, drv_capabilities_flag))
1156 {
1157 return;
1158 }
1159
1160 if (0 == drv_cap_client)
1161 {
1162 //this is a client that does not require updating the SHMEM
1163 return;
1164 }
1165
1166 LM_SHMEM2_READ(pdev, shmem_offset, &drv_cap_shmem);
1167
1168 if( b_bind )
1169 {
1170 SET_FLAGS( drv_cap_shmem, drv_cap_client );
1171 }
1172 else
1173 {
1174 RESET_FLAGS( drv_cap_shmem, drv_cap_client );
1175 }
1176
1177 LM_SHMEM2_WRITE(pdev, shmem_offset, drv_cap_shmem);
1178 }
1179
lm_mcp_indicate_client_bind(struct _lm_device_t * pdev,IN const lm_cli_idx_t cli_id)1180 void lm_mcp_indicate_client_bind(struct _lm_device_t *pdev, IN const lm_cli_idx_t cli_id)
1181 {
1182 lm_mcp_indicate_client_imp(pdev, cli_id, TRUE);
1183 }
1184
lm_mcp_indicate_client_unbind(struct _lm_device_t * pdev,IN const lm_cli_idx_t cli_id)1185 void lm_mcp_indicate_client_unbind(struct _lm_device_t *pdev, IN const lm_cli_idx_t cli_id)
1186 {
1187 lm_mcp_indicate_client_imp(pdev, cli_id, FALSE);
1188 }
1189