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