xref: /freebsd/sys/dev/ixgbe/ixgbe_e610.c (revision dea5f973d0c8d29a79b433283d0a2de8f4615957)
1*dea5f973SBhosale, Yogeshnull /******************************************************************************
2*dea5f973SBhosale, Yogeshnull   SPDX-License-Identifier: BSD-3-Clause
3*dea5f973SBhosale, Yogeshnull 
4*dea5f973SBhosale, Yogeshnull   Copyright (c) 2025, Intel Corporation
5*dea5f973SBhosale, Yogeshnull   All rights reserved.
6*dea5f973SBhosale, Yogeshnull 
7*dea5f973SBhosale, Yogeshnull   Redistribution and use in source and binary forms, with or without
8*dea5f973SBhosale, Yogeshnull   modification, are permitted provided that the following conditions are met:
9*dea5f973SBhosale, Yogeshnull 
10*dea5f973SBhosale, Yogeshnull    1. Redistributions of source code must retain the above copyright notice,
11*dea5f973SBhosale, Yogeshnull       this list of conditions and the following disclaimer.
12*dea5f973SBhosale, Yogeshnull 
13*dea5f973SBhosale, Yogeshnull    2. Redistributions in binary form must reproduce the above copyright
14*dea5f973SBhosale, Yogeshnull       notice, this list of conditions and the following disclaimer in the
15*dea5f973SBhosale, Yogeshnull       documentation and/or other materials provided with the distribution.
16*dea5f973SBhosale, Yogeshnull 
17*dea5f973SBhosale, Yogeshnull    3. Neither the name of the Intel Corporation nor the names of its
18*dea5f973SBhosale, Yogeshnull       contributors may be used to endorse or promote products derived from
19*dea5f973SBhosale, Yogeshnull       this software without specific prior written permission.
20*dea5f973SBhosale, Yogeshnull 
21*dea5f973SBhosale, Yogeshnull   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22*dea5f973SBhosale, Yogeshnull   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*dea5f973SBhosale, Yogeshnull   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*dea5f973SBhosale, Yogeshnull   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25*dea5f973SBhosale, Yogeshnull   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26*dea5f973SBhosale, Yogeshnull   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27*dea5f973SBhosale, Yogeshnull   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*dea5f973SBhosale, Yogeshnull   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29*dea5f973SBhosale, Yogeshnull   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30*dea5f973SBhosale, Yogeshnull   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31*dea5f973SBhosale, Yogeshnull   POSSIBILITY OF SUCH DAMAGE.
32*dea5f973SBhosale, Yogeshnull 
33*dea5f973SBhosale, Yogeshnull ******************************************************************************/
34*dea5f973SBhosale, Yogeshnull 
35*dea5f973SBhosale, Yogeshnull #include "ixgbe_type.h"
36*dea5f973SBhosale, Yogeshnull #include "ixgbe_e610.h"
37*dea5f973SBhosale, Yogeshnull #include "ixgbe_x550.h"
38*dea5f973SBhosale, Yogeshnull #include "ixgbe_common.h"
39*dea5f973SBhosale, Yogeshnull #include "ixgbe_phy.h"
40*dea5f973SBhosale, Yogeshnull #include "ixgbe_api.h"
41*dea5f973SBhosale, Yogeshnull 
42*dea5f973SBhosale, Yogeshnull /**
43*dea5f973SBhosale, Yogeshnull  * ixgbe_init_aci - initialization routine for Admin Command Interface
44*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hardware structure
45*dea5f973SBhosale, Yogeshnull  *
46*dea5f973SBhosale, Yogeshnull  * Initialize the ACI lock.
47*dea5f973SBhosale, Yogeshnull  */
ixgbe_init_aci(struct ixgbe_hw * hw)48*dea5f973SBhosale, Yogeshnull void ixgbe_init_aci(struct ixgbe_hw *hw)
49*dea5f973SBhosale, Yogeshnull {
50*dea5f973SBhosale, Yogeshnull 	ixgbe_init_lock(&hw->aci.lock);
51*dea5f973SBhosale, Yogeshnull }
52*dea5f973SBhosale, Yogeshnull 
53*dea5f973SBhosale, Yogeshnull /**
54*dea5f973SBhosale, Yogeshnull  * ixgbe_shutdown_aci - shutdown routine for Admin Command Interface
55*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hardware structure
56*dea5f973SBhosale, Yogeshnull  *
57*dea5f973SBhosale, Yogeshnull  * Destroy the ACI lock.
58*dea5f973SBhosale, Yogeshnull  */
ixgbe_shutdown_aci(struct ixgbe_hw * hw)59*dea5f973SBhosale, Yogeshnull void ixgbe_shutdown_aci(struct ixgbe_hw *hw)
60*dea5f973SBhosale, Yogeshnull {
61*dea5f973SBhosale, Yogeshnull 	ixgbe_destroy_lock(&hw->aci.lock);
62*dea5f973SBhosale, Yogeshnull }
63*dea5f973SBhosale, Yogeshnull 
64*dea5f973SBhosale, Yogeshnull /**
65*dea5f973SBhosale, Yogeshnull  * ixgbe_should_retry_aci_send_cmd_execute - decide if ACI command should
66*dea5f973SBhosale, Yogeshnull  * be resent
67*dea5f973SBhosale, Yogeshnull  * @opcode: ACI opcode
68*dea5f973SBhosale, Yogeshnull  *
69*dea5f973SBhosale, Yogeshnull  * Check if ACI command should be sent again depending on the provided opcode.
70*dea5f973SBhosale, Yogeshnull  *
71*dea5f973SBhosale, Yogeshnull  * Return: true if the sending command routine should be repeated,
72*dea5f973SBhosale, Yogeshnull  * otherwise false.
73*dea5f973SBhosale, Yogeshnull  */
ixgbe_should_retry_aci_send_cmd_execute(u16 opcode)74*dea5f973SBhosale, Yogeshnull static bool ixgbe_should_retry_aci_send_cmd_execute(u16 opcode)
75*dea5f973SBhosale, Yogeshnull {
76*dea5f973SBhosale, Yogeshnull 	switch (opcode) {
77*dea5f973SBhosale, Yogeshnull 	case ixgbe_aci_opc_disable_rxen:
78*dea5f973SBhosale, Yogeshnull 	case ixgbe_aci_opc_get_phy_caps:
79*dea5f973SBhosale, Yogeshnull 	case ixgbe_aci_opc_get_link_status:
80*dea5f973SBhosale, Yogeshnull 	case ixgbe_aci_opc_get_link_topo:
81*dea5f973SBhosale, Yogeshnull 		return true;
82*dea5f973SBhosale, Yogeshnull 	}
83*dea5f973SBhosale, Yogeshnull 
84*dea5f973SBhosale, Yogeshnull 	return false;
85*dea5f973SBhosale, Yogeshnull }
86*dea5f973SBhosale, Yogeshnull 
87*dea5f973SBhosale, Yogeshnull /**
88*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_send_cmd_execute - execute sending FW Admin Command to FW Admin
89*dea5f973SBhosale, Yogeshnull  * Command Interface
90*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
91*dea5f973SBhosale, Yogeshnull  * @desc: descriptor describing the command
92*dea5f973SBhosale, Yogeshnull  * @buf: buffer to use for indirect commands (NULL for direct commands)
93*dea5f973SBhosale, Yogeshnull  * @buf_size: size of buffer for indirect commands (0 for direct commands)
94*dea5f973SBhosale, Yogeshnull  *
95*dea5f973SBhosale, Yogeshnull  * Admin Command is sent using CSR by setting descriptor and buffer in specific
96*dea5f973SBhosale, Yogeshnull  * registers.
97*dea5f973SBhosale, Yogeshnull  *
98*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
99*dea5f973SBhosale, Yogeshnull  * * - IXGBE_SUCCESS - success.
100*dea5f973SBhosale, Yogeshnull  * * - IXGBE_ERR_ACI_DISABLED - CSR mechanism is not enabled.
101*dea5f973SBhosale, Yogeshnull  * * - IXGBE_ERR_ACI_BUSY - CSR mechanism is busy.
102*dea5f973SBhosale, Yogeshnull  * * - IXGBE_ERR_PARAM - buf_size is too big or
103*dea5f973SBhosale, Yogeshnull  * invalid argument buf or buf_size.
104*dea5f973SBhosale, Yogeshnull  * * - IXGBE_ERR_ACI_TIMEOUT - Admin Command X command timeout.
105*dea5f973SBhosale, Yogeshnull  * * - IXGBE_ERR_ACI_ERROR - Admin Command X invalid state of HICR register or
106*dea5f973SBhosale, Yogeshnull  * Admin Command failed because of bad opcode was returned or
107*dea5f973SBhosale, Yogeshnull  * Admin Command failed with error Y.
108*dea5f973SBhosale, Yogeshnull  */
109*dea5f973SBhosale, Yogeshnull static s32
ixgbe_aci_send_cmd_execute(struct ixgbe_hw * hw,struct ixgbe_aci_desc * desc,void * buf,u16 buf_size)110*dea5f973SBhosale, Yogeshnull ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
111*dea5f973SBhosale, Yogeshnull 			   void *buf, u16 buf_size)
112*dea5f973SBhosale, Yogeshnull {
113*dea5f973SBhosale, Yogeshnull 	u32 hicr = 0, tmp_buf_size = 0, i = 0;
114*dea5f973SBhosale, Yogeshnull 	u32 *raw_desc = (u32 *)desc;
115*dea5f973SBhosale, Yogeshnull 	s32 status = IXGBE_SUCCESS;
116*dea5f973SBhosale, Yogeshnull 	bool valid_buf = false;
117*dea5f973SBhosale, Yogeshnull 	u32 *tmp_buf = NULL;
118*dea5f973SBhosale, Yogeshnull 	u16 opcode = 0;
119*dea5f973SBhosale, Yogeshnull 
120*dea5f973SBhosale, Yogeshnull 	do {
121*dea5f973SBhosale, Yogeshnull 		hw->aci.last_status = IXGBE_ACI_RC_OK;
122*dea5f973SBhosale, Yogeshnull 
123*dea5f973SBhosale, Yogeshnull 		/* It's necessary to check if mechanism is enabled */
124*dea5f973SBhosale, Yogeshnull 		hicr = IXGBE_READ_REG(hw, PF_HICR);
125*dea5f973SBhosale, Yogeshnull 		if (!(hicr & PF_HICR_EN)) {
126*dea5f973SBhosale, Yogeshnull 			status = IXGBE_ERR_ACI_DISABLED;
127*dea5f973SBhosale, Yogeshnull 			break;
128*dea5f973SBhosale, Yogeshnull 		}
129*dea5f973SBhosale, Yogeshnull 		if (hicr & PF_HICR_C) {
130*dea5f973SBhosale, Yogeshnull 			hw->aci.last_status = IXGBE_ACI_RC_EBUSY;
131*dea5f973SBhosale, Yogeshnull 			status = IXGBE_ERR_ACI_BUSY;
132*dea5f973SBhosale, Yogeshnull 			break;
133*dea5f973SBhosale, Yogeshnull 		}
134*dea5f973SBhosale, Yogeshnull 		opcode = desc->opcode;
135*dea5f973SBhosale, Yogeshnull 
136*dea5f973SBhosale, Yogeshnull 		if (buf_size > IXGBE_ACI_MAX_BUFFER_SIZE) {
137*dea5f973SBhosale, Yogeshnull 			status = IXGBE_ERR_PARAM;
138*dea5f973SBhosale, Yogeshnull 			break;
139*dea5f973SBhosale, Yogeshnull 		}
140*dea5f973SBhosale, Yogeshnull 
141*dea5f973SBhosale, Yogeshnull 		if (buf)
142*dea5f973SBhosale, Yogeshnull 			desc->flags |= IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_BUF);
143*dea5f973SBhosale, Yogeshnull 
144*dea5f973SBhosale, Yogeshnull 		/* Check if buf and buf_size are proper params */
145*dea5f973SBhosale, Yogeshnull 		if (desc->flags & IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_BUF)) {
146*dea5f973SBhosale, Yogeshnull 			if ((buf && buf_size == 0) ||
147*dea5f973SBhosale, Yogeshnull 			    (buf == NULL && buf_size)) {
148*dea5f973SBhosale, Yogeshnull 				status = IXGBE_ERR_PARAM;
149*dea5f973SBhosale, Yogeshnull 				break;
150*dea5f973SBhosale, Yogeshnull 			}
151*dea5f973SBhosale, Yogeshnull 			if (buf && buf_size)
152*dea5f973SBhosale, Yogeshnull 				valid_buf = true;
153*dea5f973SBhosale, Yogeshnull 		}
154*dea5f973SBhosale, Yogeshnull 
155*dea5f973SBhosale, Yogeshnull 		if (valid_buf == true) {
156*dea5f973SBhosale, Yogeshnull 			if (buf_size % 4 == 0)
157*dea5f973SBhosale, Yogeshnull 				tmp_buf_size = buf_size;
158*dea5f973SBhosale, Yogeshnull 			else
159*dea5f973SBhosale, Yogeshnull 				tmp_buf_size = (buf_size & (u16)(~0x03)) + 4;
160*dea5f973SBhosale, Yogeshnull 
161*dea5f973SBhosale, Yogeshnull 			tmp_buf = (u32*)ixgbe_malloc(hw, tmp_buf_size);
162*dea5f973SBhosale, Yogeshnull 			if (!tmp_buf)
163*dea5f973SBhosale, Yogeshnull 				return IXGBE_ERR_OUT_OF_MEM;
164*dea5f973SBhosale, Yogeshnull 
165*dea5f973SBhosale, Yogeshnull 			/* tmp_buf will be firstly filled with 0xFF and after
166*dea5f973SBhosale, Yogeshnull 			 * that the content of buf will be written into it.
167*dea5f973SBhosale, Yogeshnull 			 * This approach lets us use valid buf_size and
168*dea5f973SBhosale, Yogeshnull 			 * prevents us from reading past buf area
169*dea5f973SBhosale, Yogeshnull 			 * when buf_size mod 4 not equal to 0.
170*dea5f973SBhosale, Yogeshnull 			 */
171*dea5f973SBhosale, Yogeshnull 			memset(tmp_buf, 0xFF, tmp_buf_size);
172*dea5f973SBhosale, Yogeshnull 			memcpy(tmp_buf, buf, buf_size);
173*dea5f973SBhosale, Yogeshnull 
174*dea5f973SBhosale, Yogeshnull 			if (tmp_buf_size > IXGBE_ACI_LG_BUF)
175*dea5f973SBhosale, Yogeshnull 				desc->flags |=
176*dea5f973SBhosale, Yogeshnull 				IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_LB);
177*dea5f973SBhosale, Yogeshnull 
178*dea5f973SBhosale, Yogeshnull 			desc->datalen = IXGBE_CPU_TO_LE16(buf_size);
179*dea5f973SBhosale, Yogeshnull 
180*dea5f973SBhosale, Yogeshnull 			if (desc->flags & IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_RD)) {
181*dea5f973SBhosale, Yogeshnull 				for (i = 0; i < tmp_buf_size / 4; i++) {
182*dea5f973SBhosale, Yogeshnull 					IXGBE_WRITE_REG(hw, PF_HIBA(i),
183*dea5f973SBhosale, Yogeshnull 						IXGBE_LE32_TO_CPU(tmp_buf[i]));
184*dea5f973SBhosale, Yogeshnull 				}
185*dea5f973SBhosale, Yogeshnull 			}
186*dea5f973SBhosale, Yogeshnull 		}
187*dea5f973SBhosale, Yogeshnull 
188*dea5f973SBhosale, Yogeshnull 		/* Descriptor is written to specific registers */
189*dea5f973SBhosale, Yogeshnull 		for (i = 0; i < IXGBE_ACI_DESC_SIZE_IN_DWORDS; i++)
190*dea5f973SBhosale, Yogeshnull 			IXGBE_WRITE_REG(hw, PF_HIDA(i),
191*dea5f973SBhosale, Yogeshnull 					IXGBE_LE32_TO_CPU(raw_desc[i]));
192*dea5f973SBhosale, Yogeshnull 
193*dea5f973SBhosale, Yogeshnull 		/* SW has to set PF_HICR.C bit and clear PF_HICR.SV and
194*dea5f973SBhosale, Yogeshnull 		 * PF_HICR_EV
195*dea5f973SBhosale, Yogeshnull 		 */
196*dea5f973SBhosale, Yogeshnull 		hicr = IXGBE_READ_REG(hw, PF_HICR);
197*dea5f973SBhosale, Yogeshnull 		hicr = (hicr | PF_HICR_C) & ~(PF_HICR_SV | PF_HICR_EV);
198*dea5f973SBhosale, Yogeshnull 		IXGBE_WRITE_REG(hw, PF_HICR, hicr);
199*dea5f973SBhosale, Yogeshnull 
200*dea5f973SBhosale, Yogeshnull 		/* Wait for sync Admin Command response */
201*dea5f973SBhosale, Yogeshnull 		for (i = 0; i < IXGBE_ACI_SYNC_RESPONSE_TIMEOUT; i += 1) {
202*dea5f973SBhosale, Yogeshnull 			hicr = IXGBE_READ_REG(hw, PF_HICR);
203*dea5f973SBhosale, Yogeshnull 			if ((hicr & PF_HICR_SV) || !(hicr & PF_HICR_C))
204*dea5f973SBhosale, Yogeshnull 				break;
205*dea5f973SBhosale, Yogeshnull 
206*dea5f973SBhosale, Yogeshnull 			msec_delay(1);
207*dea5f973SBhosale, Yogeshnull 		}
208*dea5f973SBhosale, Yogeshnull 
209*dea5f973SBhosale, Yogeshnull 		/* Wait for async Admin Command response */
210*dea5f973SBhosale, Yogeshnull 		if ((hicr & PF_HICR_SV) && (hicr & PF_HICR_C)) {
211*dea5f973SBhosale, Yogeshnull 			for (i = 0; i < IXGBE_ACI_ASYNC_RESPONSE_TIMEOUT;
212*dea5f973SBhosale, Yogeshnull 			     i += 1) {
213*dea5f973SBhosale, Yogeshnull 				hicr = IXGBE_READ_REG(hw, PF_HICR);
214*dea5f973SBhosale, Yogeshnull 				if ((hicr & PF_HICR_EV) || !(hicr & PF_HICR_C))
215*dea5f973SBhosale, Yogeshnull 					break;
216*dea5f973SBhosale, Yogeshnull 
217*dea5f973SBhosale, Yogeshnull 				msec_delay(1);
218*dea5f973SBhosale, Yogeshnull 			}
219*dea5f973SBhosale, Yogeshnull 		}
220*dea5f973SBhosale, Yogeshnull 
221*dea5f973SBhosale, Yogeshnull 		/* Read sync Admin Command response */
222*dea5f973SBhosale, Yogeshnull 		if ((hicr & PF_HICR_SV)) {
223*dea5f973SBhosale, Yogeshnull 			for (i = 0; i < IXGBE_ACI_DESC_SIZE_IN_DWORDS; i++) {
224*dea5f973SBhosale, Yogeshnull 				raw_desc[i] = IXGBE_READ_REG(hw, PF_HIDA(i));
225*dea5f973SBhosale, Yogeshnull 				raw_desc[i] = IXGBE_CPU_TO_LE32(raw_desc[i]);
226*dea5f973SBhosale, Yogeshnull 			}
227*dea5f973SBhosale, Yogeshnull 		}
228*dea5f973SBhosale, Yogeshnull 
229*dea5f973SBhosale, Yogeshnull 		/* Read async Admin Command response */
230*dea5f973SBhosale, Yogeshnull 		if ((hicr & PF_HICR_EV) && !(hicr & PF_HICR_C)) {
231*dea5f973SBhosale, Yogeshnull 			for (i = 0; i < IXGBE_ACI_DESC_SIZE_IN_DWORDS; i++) {
232*dea5f973SBhosale, Yogeshnull 				raw_desc[i] = IXGBE_READ_REG(hw, PF_HIDA_2(i));
233*dea5f973SBhosale, Yogeshnull 				raw_desc[i] = IXGBE_CPU_TO_LE32(raw_desc[i]);
234*dea5f973SBhosale, Yogeshnull 			}
235*dea5f973SBhosale, Yogeshnull 		}
236*dea5f973SBhosale, Yogeshnull 
237*dea5f973SBhosale, Yogeshnull 		/* Handle timeout and invalid state of HICR register */
238*dea5f973SBhosale, Yogeshnull 		if (hicr & PF_HICR_C) {
239*dea5f973SBhosale, Yogeshnull 			status = IXGBE_ERR_ACI_TIMEOUT;
240*dea5f973SBhosale, Yogeshnull 			break;
241*dea5f973SBhosale, Yogeshnull 		} else if (!(hicr & PF_HICR_SV) && !(hicr & PF_HICR_EV)) {
242*dea5f973SBhosale, Yogeshnull 			status = IXGBE_ERR_ACI_ERROR;
243*dea5f973SBhosale, Yogeshnull 			break;
244*dea5f973SBhosale, Yogeshnull 		}
245*dea5f973SBhosale, Yogeshnull 
246*dea5f973SBhosale, Yogeshnull 		/* For every command other than 0x0014 treat opcode mismatch
247*dea5f973SBhosale, Yogeshnull 		 * as an error. Response to 0x0014 command read from HIDA_2
248*dea5f973SBhosale, Yogeshnull 		 * is a descriptor of an event which is expected to contain
249*dea5f973SBhosale, Yogeshnull 		 * different opcode than the command.
250*dea5f973SBhosale, Yogeshnull 		 */
251*dea5f973SBhosale, Yogeshnull 		if (desc->opcode != opcode &&
252*dea5f973SBhosale, Yogeshnull 		    opcode != IXGBE_CPU_TO_LE16(ixgbe_aci_opc_get_fw_event)) {
253*dea5f973SBhosale, Yogeshnull 			status = IXGBE_ERR_ACI_ERROR;
254*dea5f973SBhosale, Yogeshnull 			break;
255*dea5f973SBhosale, Yogeshnull 		}
256*dea5f973SBhosale, Yogeshnull 
257*dea5f973SBhosale, Yogeshnull 		if (desc->retval != IXGBE_ACI_RC_OK) {
258*dea5f973SBhosale, Yogeshnull 			hw->aci.last_status = (enum ixgbe_aci_err)desc->retval;
259*dea5f973SBhosale, Yogeshnull 			status = IXGBE_ERR_ACI_ERROR;
260*dea5f973SBhosale, Yogeshnull 			break;
261*dea5f973SBhosale, Yogeshnull 		}
262*dea5f973SBhosale, Yogeshnull 
263*dea5f973SBhosale, Yogeshnull 		/* Write a response values to a buf */
264*dea5f973SBhosale, Yogeshnull 		if (valid_buf && (desc->flags &
265*dea5f973SBhosale, Yogeshnull 				  IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_BUF))) {
266*dea5f973SBhosale, Yogeshnull 			for (i = 0; i < tmp_buf_size / 4; i++) {
267*dea5f973SBhosale, Yogeshnull 				tmp_buf[i] = IXGBE_READ_REG(hw, PF_HIBA(i));
268*dea5f973SBhosale, Yogeshnull 				tmp_buf[i] = IXGBE_CPU_TO_LE32(tmp_buf[i]);
269*dea5f973SBhosale, Yogeshnull 			}
270*dea5f973SBhosale, Yogeshnull 			memcpy(buf, tmp_buf, buf_size);
271*dea5f973SBhosale, Yogeshnull 		}
272*dea5f973SBhosale, Yogeshnull 	} while (0);
273*dea5f973SBhosale, Yogeshnull 
274*dea5f973SBhosale, Yogeshnull 	if (tmp_buf)
275*dea5f973SBhosale, Yogeshnull 		ixgbe_free(hw, tmp_buf);
276*dea5f973SBhosale, Yogeshnull 
277*dea5f973SBhosale, Yogeshnull 	return status;
278*dea5f973SBhosale, Yogeshnull }
279*dea5f973SBhosale, Yogeshnull 
280*dea5f973SBhosale, Yogeshnull /**
281*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_send_cmd - send FW Admin Command to FW Admin Command Interface
282*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
283*dea5f973SBhosale, Yogeshnull  * @desc: descriptor describing the command
284*dea5f973SBhosale, Yogeshnull  * @buf: buffer to use for indirect commands (NULL for direct commands)
285*dea5f973SBhosale, Yogeshnull  * @buf_size: size of buffer for indirect commands (0 for direct commands)
286*dea5f973SBhosale, Yogeshnull  *
287*dea5f973SBhosale, Yogeshnull  * Helper function to send FW Admin Commands to the FW Admin Command Interface.
288*dea5f973SBhosale, Yogeshnull  *
289*dea5f973SBhosale, Yogeshnull  * Retry sending the FW Admin Command multiple times to the FW ACI
290*dea5f973SBhosale, Yogeshnull  * if the EBUSY Admin Command error is returned.
291*dea5f973SBhosale, Yogeshnull  *
292*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
293*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_send_cmd(struct ixgbe_hw * hw,struct ixgbe_aci_desc * desc,void * buf,u16 buf_size)294*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_send_cmd(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
295*dea5f973SBhosale, Yogeshnull 		       void *buf, u16 buf_size)
296*dea5f973SBhosale, Yogeshnull {
297*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc_cpy;
298*dea5f973SBhosale, Yogeshnull 	enum ixgbe_aci_err last_status;
299*dea5f973SBhosale, Yogeshnull 	bool is_cmd_for_retry;
300*dea5f973SBhosale, Yogeshnull 	u8 *buf_cpy = NULL;
301*dea5f973SBhosale, Yogeshnull 	s32 status;
302*dea5f973SBhosale, Yogeshnull 	u16 opcode;
303*dea5f973SBhosale, Yogeshnull 	u8 idx = 0;
304*dea5f973SBhosale, Yogeshnull 
305*dea5f973SBhosale, Yogeshnull 	opcode = IXGBE_LE16_TO_CPU(desc->opcode);
306*dea5f973SBhosale, Yogeshnull 	is_cmd_for_retry = ixgbe_should_retry_aci_send_cmd_execute(opcode);
307*dea5f973SBhosale, Yogeshnull 	memset(&desc_cpy, 0, sizeof(desc_cpy));
308*dea5f973SBhosale, Yogeshnull 
309*dea5f973SBhosale, Yogeshnull 	if (is_cmd_for_retry) {
310*dea5f973SBhosale, Yogeshnull 		if (buf) {
311*dea5f973SBhosale, Yogeshnull 			buf_cpy = (u8 *)ixgbe_malloc(hw, buf_size);
312*dea5f973SBhosale, Yogeshnull 			if (!buf_cpy)
313*dea5f973SBhosale, Yogeshnull 				return IXGBE_ERR_OUT_OF_MEM;
314*dea5f973SBhosale, Yogeshnull 		}
315*dea5f973SBhosale, Yogeshnull 		memcpy(&desc_cpy, desc, sizeof(desc_cpy));
316*dea5f973SBhosale, Yogeshnull 	}
317*dea5f973SBhosale, Yogeshnull 
318*dea5f973SBhosale, Yogeshnull 	do {
319*dea5f973SBhosale, Yogeshnull 		ixgbe_acquire_lock(&hw->aci.lock);
320*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_send_cmd_execute(hw, desc, buf, buf_size);
321*dea5f973SBhosale, Yogeshnull 		last_status = hw->aci.last_status;
322*dea5f973SBhosale, Yogeshnull 		ixgbe_release_lock(&hw->aci.lock);
323*dea5f973SBhosale, Yogeshnull 
324*dea5f973SBhosale, Yogeshnull 		if (!is_cmd_for_retry || status == IXGBE_SUCCESS ||
325*dea5f973SBhosale, Yogeshnull 		    (last_status != IXGBE_ACI_RC_EBUSY && status != IXGBE_ERR_ACI_ERROR))
326*dea5f973SBhosale, Yogeshnull 			break;
327*dea5f973SBhosale, Yogeshnull 
328*dea5f973SBhosale, Yogeshnull 		if (buf)
329*dea5f973SBhosale, Yogeshnull 			memcpy(buf, buf_cpy, buf_size);
330*dea5f973SBhosale, Yogeshnull 		memcpy(desc, &desc_cpy, sizeof(desc_cpy));
331*dea5f973SBhosale, Yogeshnull 
332*dea5f973SBhosale, Yogeshnull 		msec_delay(IXGBE_ACI_SEND_DELAY_TIME_MS);
333*dea5f973SBhosale, Yogeshnull 	} while (++idx < IXGBE_ACI_SEND_MAX_EXECUTE);
334*dea5f973SBhosale, Yogeshnull 
335*dea5f973SBhosale, Yogeshnull 	if (buf_cpy)
336*dea5f973SBhosale, Yogeshnull 		ixgbe_free(hw, buf_cpy);
337*dea5f973SBhosale, Yogeshnull 
338*dea5f973SBhosale, Yogeshnull 	return status;
339*dea5f973SBhosale, Yogeshnull }
340*dea5f973SBhosale, Yogeshnull 
341*dea5f973SBhosale, Yogeshnull /**
342*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_check_event_pending - check if there are any pending events
343*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
344*dea5f973SBhosale, Yogeshnull  *
345*dea5f973SBhosale, Yogeshnull  * Determine if there are any pending events.
346*dea5f973SBhosale, Yogeshnull  *
347*dea5f973SBhosale, Yogeshnull  * Return: true if there are any currently pending events
348*dea5f973SBhosale, Yogeshnull  * otherwise false.
349*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_check_event_pending(struct ixgbe_hw * hw)350*dea5f973SBhosale, Yogeshnull bool ixgbe_aci_check_event_pending(struct ixgbe_hw *hw)
351*dea5f973SBhosale, Yogeshnull {
352*dea5f973SBhosale, Yogeshnull 	u32 ep_bit_mask;
353*dea5f973SBhosale, Yogeshnull 	u32 fwsts;
354*dea5f973SBhosale, Yogeshnull 
355*dea5f973SBhosale, Yogeshnull 	ep_bit_mask = hw->bus.func ? GL_FWSTS_EP_PF1 : GL_FWSTS_EP_PF0;
356*dea5f973SBhosale, Yogeshnull 
357*dea5f973SBhosale, Yogeshnull 	/* Check state of Event Pending (EP) bit */
358*dea5f973SBhosale, Yogeshnull 	fwsts = IXGBE_READ_REG(hw, GL_FWSTS);
359*dea5f973SBhosale, Yogeshnull 	return (fwsts & ep_bit_mask) ? true : false;
360*dea5f973SBhosale, Yogeshnull }
361*dea5f973SBhosale, Yogeshnull 
362*dea5f973SBhosale, Yogeshnull /**
363*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_get_event - get an event from ACI
364*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
365*dea5f973SBhosale, Yogeshnull  * @e: event information structure
366*dea5f973SBhosale, Yogeshnull  * @pending: optional flag signaling that there are more pending events
367*dea5f973SBhosale, Yogeshnull  *
368*dea5f973SBhosale, Yogeshnull  * Obtain an event from ACI and return its content
369*dea5f973SBhosale, Yogeshnull  * through 'e' using ACI command (0x0014).
370*dea5f973SBhosale, Yogeshnull  * Provide information if there are more events
371*dea5f973SBhosale, Yogeshnull  * to retrieve through 'pending'.
372*dea5f973SBhosale, Yogeshnull  *
373*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
374*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_get_event(struct ixgbe_hw * hw,struct ixgbe_aci_event * e,bool * pending)375*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_get_event(struct ixgbe_hw *hw, struct ixgbe_aci_event *e,
376*dea5f973SBhosale, Yogeshnull 			bool *pending)
377*dea5f973SBhosale, Yogeshnull {
378*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
379*dea5f973SBhosale, Yogeshnull 	s32 status;
380*dea5f973SBhosale, Yogeshnull 
381*dea5f973SBhosale, Yogeshnull 	if (!e || (!e->msg_buf && e->buf_len) || (e->msg_buf && !e->buf_len))
382*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
383*dea5f973SBhosale, Yogeshnull 
384*dea5f973SBhosale, Yogeshnull 	ixgbe_acquire_lock(&hw->aci.lock);
385*dea5f973SBhosale, Yogeshnull 
386*dea5f973SBhosale, Yogeshnull 	/* Check if there are any events pending */
387*dea5f973SBhosale, Yogeshnull 	if (!ixgbe_aci_check_event_pending(hw)) {
388*dea5f973SBhosale, Yogeshnull 		status = IXGBE_ERR_ACI_NO_EVENTS;
389*dea5f973SBhosale, Yogeshnull 		goto aci_get_event_exit;
390*dea5f973SBhosale, Yogeshnull 	}
391*dea5f973SBhosale, Yogeshnull 
392*dea5f973SBhosale, Yogeshnull 	/* Obtain pending event */
393*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_fw_event);
394*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd_execute(hw, &desc, e->msg_buf, e->buf_len);
395*dea5f973SBhosale, Yogeshnull 	if (status)
396*dea5f973SBhosale, Yogeshnull 		goto aci_get_event_exit;
397*dea5f973SBhosale, Yogeshnull 
398*dea5f973SBhosale, Yogeshnull 	/* Returned 0x0014 opcode indicates that no event was obtained */
399*dea5f973SBhosale, Yogeshnull 	if (desc.opcode == IXGBE_CPU_TO_LE16(ixgbe_aci_opc_get_fw_event)) {
400*dea5f973SBhosale, Yogeshnull 		status = IXGBE_ERR_ACI_NO_EVENTS;
401*dea5f973SBhosale, Yogeshnull 		goto aci_get_event_exit;
402*dea5f973SBhosale, Yogeshnull 	}
403*dea5f973SBhosale, Yogeshnull 
404*dea5f973SBhosale, Yogeshnull 	/* Determine size of event data */
405*dea5f973SBhosale, Yogeshnull 	e->msg_len = MIN_T(u16, IXGBE_LE16_TO_CPU(desc.datalen), e->buf_len);
406*dea5f973SBhosale, Yogeshnull 	/* Write event descriptor to event info structure */
407*dea5f973SBhosale, Yogeshnull 	memcpy(&e->desc, &desc, sizeof(e->desc));
408*dea5f973SBhosale, Yogeshnull 
409*dea5f973SBhosale, Yogeshnull 	/* Check if there are any further events pending */
410*dea5f973SBhosale, Yogeshnull 	if (pending) {
411*dea5f973SBhosale, Yogeshnull 		*pending = ixgbe_aci_check_event_pending(hw);
412*dea5f973SBhosale, Yogeshnull 	}
413*dea5f973SBhosale, Yogeshnull 
414*dea5f973SBhosale, Yogeshnull aci_get_event_exit:
415*dea5f973SBhosale, Yogeshnull 	ixgbe_release_lock(&hw->aci.lock);
416*dea5f973SBhosale, Yogeshnull 
417*dea5f973SBhosale, Yogeshnull 	return status;
418*dea5f973SBhosale, Yogeshnull }
419*dea5f973SBhosale, Yogeshnull 
420*dea5f973SBhosale, Yogeshnull /**
421*dea5f973SBhosale, Yogeshnull  * ixgbe_fill_dflt_direct_cmd_desc - fill ACI descriptor with default values.
422*dea5f973SBhosale, Yogeshnull  * @desc: pointer to the temp descriptor (non DMA mem)
423*dea5f973SBhosale, Yogeshnull  * @opcode: the opcode can be used to decide which flags to turn off or on
424*dea5f973SBhosale, Yogeshnull  *
425*dea5f973SBhosale, Yogeshnull  * Helper function to fill the descriptor desc with default values
426*dea5f973SBhosale, Yogeshnull  * and the provided opcode.
427*dea5f973SBhosale, Yogeshnull  */
ixgbe_fill_dflt_direct_cmd_desc(struct ixgbe_aci_desc * desc,u16 opcode)428*dea5f973SBhosale, Yogeshnull void ixgbe_fill_dflt_direct_cmd_desc(struct ixgbe_aci_desc *desc, u16 opcode)
429*dea5f973SBhosale, Yogeshnull {
430*dea5f973SBhosale, Yogeshnull 	/* zero out the desc */
431*dea5f973SBhosale, Yogeshnull 	memset(desc, 0, sizeof(*desc));
432*dea5f973SBhosale, Yogeshnull 	desc->opcode = IXGBE_CPU_TO_LE16(opcode);
433*dea5f973SBhosale, Yogeshnull 	desc->flags = IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_SI);
434*dea5f973SBhosale, Yogeshnull }
435*dea5f973SBhosale, Yogeshnull 
436*dea5f973SBhosale, Yogeshnull /**
437*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_get_fw_ver - get the firmware version
438*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
439*dea5f973SBhosale, Yogeshnull  *
440*dea5f973SBhosale, Yogeshnull  * Get the firmware version using ACI command (0x0001).
441*dea5f973SBhosale, Yogeshnull  *
442*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
443*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_get_fw_ver(struct ixgbe_hw * hw)444*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_get_fw_ver(struct ixgbe_hw *hw)
445*dea5f973SBhosale, Yogeshnull {
446*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_ver *resp;
447*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
448*dea5f973SBhosale, Yogeshnull 	s32 status;
449*dea5f973SBhosale, Yogeshnull 
450*dea5f973SBhosale, Yogeshnull 	resp = &desc.params.get_ver;
451*dea5f973SBhosale, Yogeshnull 
452*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_ver);
453*dea5f973SBhosale, Yogeshnull 
454*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
455*dea5f973SBhosale, Yogeshnull 
456*dea5f973SBhosale, Yogeshnull 	if (!status) {
457*dea5f973SBhosale, Yogeshnull 		hw->fw_branch = resp->fw_branch;
458*dea5f973SBhosale, Yogeshnull 		hw->fw_maj_ver = resp->fw_major;
459*dea5f973SBhosale, Yogeshnull 		hw->fw_min_ver = resp->fw_minor;
460*dea5f973SBhosale, Yogeshnull 		hw->fw_patch = resp->fw_patch;
461*dea5f973SBhosale, Yogeshnull 		hw->fw_build = IXGBE_LE32_TO_CPU(resp->fw_build);
462*dea5f973SBhosale, Yogeshnull 		hw->api_branch = resp->api_branch;
463*dea5f973SBhosale, Yogeshnull 		hw->api_maj_ver = resp->api_major;
464*dea5f973SBhosale, Yogeshnull 		hw->api_min_ver = resp->api_minor;
465*dea5f973SBhosale, Yogeshnull 		hw->api_patch = resp->api_patch;
466*dea5f973SBhosale, Yogeshnull 	}
467*dea5f973SBhosale, Yogeshnull 
468*dea5f973SBhosale, Yogeshnull 	return status;
469*dea5f973SBhosale, Yogeshnull }
470*dea5f973SBhosale, Yogeshnull 
471*dea5f973SBhosale, Yogeshnull /**
472*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_send_driver_ver - send the driver version to firmware
473*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
474*dea5f973SBhosale, Yogeshnull  * @dv: driver's major, minor version
475*dea5f973SBhosale, Yogeshnull  *
476*dea5f973SBhosale, Yogeshnull  * Send the driver version to the firmware
477*dea5f973SBhosale, Yogeshnull  * using the ACI command (0x0002).
478*dea5f973SBhosale, Yogeshnull  *
479*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
480*dea5f973SBhosale, Yogeshnull  * Returns IXGBE_ERR_PARAM, if dv is NULL.
481*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_send_driver_ver(struct ixgbe_hw * hw,struct ixgbe_driver_ver * dv)482*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_send_driver_ver(struct ixgbe_hw *hw, struct ixgbe_driver_ver *dv)
483*dea5f973SBhosale, Yogeshnull {
484*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_driver_ver *cmd;
485*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
486*dea5f973SBhosale, Yogeshnull 	u16 len;
487*dea5f973SBhosale, Yogeshnull 
488*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.driver_ver;
489*dea5f973SBhosale, Yogeshnull 
490*dea5f973SBhosale, Yogeshnull 	if (!dv)
491*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
492*dea5f973SBhosale, Yogeshnull 
493*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_driver_ver);
494*dea5f973SBhosale, Yogeshnull 
495*dea5f973SBhosale, Yogeshnull 	desc.flags |= IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_RD);
496*dea5f973SBhosale, Yogeshnull 	cmd->major_ver = dv->major_ver;
497*dea5f973SBhosale, Yogeshnull 	cmd->minor_ver = dv->minor_ver;
498*dea5f973SBhosale, Yogeshnull 	cmd->build_ver = dv->build_ver;
499*dea5f973SBhosale, Yogeshnull 	cmd->subbuild_ver = dv->subbuild_ver;
500*dea5f973SBhosale, Yogeshnull 
501*dea5f973SBhosale, Yogeshnull 	len = 0;
502*dea5f973SBhosale, Yogeshnull 	while (len < sizeof(dv->driver_string) &&
503*dea5f973SBhosale, Yogeshnull 	       IS_ASCII(dv->driver_string[len]) && dv->driver_string[len])
504*dea5f973SBhosale, Yogeshnull 		len++;
505*dea5f973SBhosale, Yogeshnull 
506*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, dv->driver_string, len);
507*dea5f973SBhosale, Yogeshnull }
508*dea5f973SBhosale, Yogeshnull 
509*dea5f973SBhosale, Yogeshnull /**
510*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_req_res - request a common resource
511*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
512*dea5f973SBhosale, Yogeshnull  * @res: resource ID
513*dea5f973SBhosale, Yogeshnull  * @access: access type
514*dea5f973SBhosale, Yogeshnull  * @sdp_number: resource number
515*dea5f973SBhosale, Yogeshnull  * @timeout: the maximum time in ms that the driver may hold the resource
516*dea5f973SBhosale, Yogeshnull  *
517*dea5f973SBhosale, Yogeshnull  * Requests a common resource using the ACI command (0x0008).
518*dea5f973SBhosale, Yogeshnull  * Specifies the maximum time the driver may hold the resource.
519*dea5f973SBhosale, Yogeshnull  * If the requested resource is currently occupied by some other driver,
520*dea5f973SBhosale, Yogeshnull  * a busy return value is returned and the timeout field value indicates the
521*dea5f973SBhosale, Yogeshnull  * maximum time the current owner has to free it.
522*dea5f973SBhosale, Yogeshnull  *
523*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
524*dea5f973SBhosale, Yogeshnull  */
525*dea5f973SBhosale, Yogeshnull static s32
ixgbe_aci_req_res(struct ixgbe_hw * hw,enum ixgbe_aci_res_ids res,enum ixgbe_aci_res_access_type access,u8 sdp_number,u32 * timeout)526*dea5f973SBhosale, Yogeshnull ixgbe_aci_req_res(struct ixgbe_hw *hw, enum ixgbe_aci_res_ids res,
527*dea5f973SBhosale, Yogeshnull 		  enum ixgbe_aci_res_access_type access, u8 sdp_number,
528*dea5f973SBhosale, Yogeshnull 		  u32 *timeout)
529*dea5f973SBhosale, Yogeshnull {
530*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_req_res *cmd_resp;
531*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
532*dea5f973SBhosale, Yogeshnull 	s32 status;
533*dea5f973SBhosale, Yogeshnull 
534*dea5f973SBhosale, Yogeshnull 	cmd_resp = &desc.params.res_owner;
535*dea5f973SBhosale, Yogeshnull 
536*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_req_res);
537*dea5f973SBhosale, Yogeshnull 
538*dea5f973SBhosale, Yogeshnull 	cmd_resp->res_id = IXGBE_CPU_TO_LE16(res);
539*dea5f973SBhosale, Yogeshnull 	cmd_resp->access_type = IXGBE_CPU_TO_LE16(access);
540*dea5f973SBhosale, Yogeshnull 	cmd_resp->res_number = IXGBE_CPU_TO_LE32(sdp_number);
541*dea5f973SBhosale, Yogeshnull 	cmd_resp->timeout = IXGBE_CPU_TO_LE32(*timeout);
542*dea5f973SBhosale, Yogeshnull 	*timeout = 0;
543*dea5f973SBhosale, Yogeshnull 
544*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
545*dea5f973SBhosale, Yogeshnull 
546*dea5f973SBhosale, Yogeshnull 	/* The completion specifies the maximum time in ms that the driver
547*dea5f973SBhosale, Yogeshnull 	 * may hold the resource in the Timeout field.
548*dea5f973SBhosale, Yogeshnull 	 * If the resource is held by some other driver, the command completes
549*dea5f973SBhosale, Yogeshnull 	 * with a busy return value and the timeout field indicates the maximum
550*dea5f973SBhosale, Yogeshnull 	 * time the current owner of the resource has to free it.
551*dea5f973SBhosale, Yogeshnull 	 */
552*dea5f973SBhosale, Yogeshnull 	if (!status || hw->aci.last_status == IXGBE_ACI_RC_EBUSY)
553*dea5f973SBhosale, Yogeshnull 		*timeout = IXGBE_LE32_TO_CPU(cmd_resp->timeout);
554*dea5f973SBhosale, Yogeshnull 
555*dea5f973SBhosale, Yogeshnull 	return status;
556*dea5f973SBhosale, Yogeshnull }
557*dea5f973SBhosale, Yogeshnull 
558*dea5f973SBhosale, Yogeshnull /**
559*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_release_res - release a common resource using ACI
560*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
561*dea5f973SBhosale, Yogeshnull  * @res: resource ID
562*dea5f973SBhosale, Yogeshnull  * @sdp_number: resource number
563*dea5f973SBhosale, Yogeshnull  *
564*dea5f973SBhosale, Yogeshnull  * Release a common resource using ACI command (0x0009).
565*dea5f973SBhosale, Yogeshnull  *
566*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
567*dea5f973SBhosale, Yogeshnull  */
568*dea5f973SBhosale, Yogeshnull static s32
ixgbe_aci_release_res(struct ixgbe_hw * hw,enum ixgbe_aci_res_ids res,u8 sdp_number)569*dea5f973SBhosale, Yogeshnull ixgbe_aci_release_res(struct ixgbe_hw *hw, enum ixgbe_aci_res_ids res,
570*dea5f973SBhosale, Yogeshnull 		      u8 sdp_number)
571*dea5f973SBhosale, Yogeshnull {
572*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_req_res *cmd;
573*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
574*dea5f973SBhosale, Yogeshnull 
575*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.res_owner;
576*dea5f973SBhosale, Yogeshnull 
577*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_release_res);
578*dea5f973SBhosale, Yogeshnull 
579*dea5f973SBhosale, Yogeshnull 	cmd->res_id = IXGBE_CPU_TO_LE16(res);
580*dea5f973SBhosale, Yogeshnull 	cmd->res_number = IXGBE_CPU_TO_LE32(sdp_number);
581*dea5f973SBhosale, Yogeshnull 
582*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
583*dea5f973SBhosale, Yogeshnull }
584*dea5f973SBhosale, Yogeshnull 
585*dea5f973SBhosale, Yogeshnull /**
586*dea5f973SBhosale, Yogeshnull  * ixgbe_acquire_res - acquire the ownership of a resource
587*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
588*dea5f973SBhosale, Yogeshnull  * @res: resource ID
589*dea5f973SBhosale, Yogeshnull  * @access: access type (read or write)
590*dea5f973SBhosale, Yogeshnull  * @timeout: timeout in milliseconds
591*dea5f973SBhosale, Yogeshnull  *
592*dea5f973SBhosale, Yogeshnull  * Make an attempt to acquire the ownership of a resource using
593*dea5f973SBhosale, Yogeshnull  * the ixgbe_aci_req_res to utilize ACI.
594*dea5f973SBhosale, Yogeshnull  * In case if some other driver has previously acquired the resource and
595*dea5f973SBhosale, Yogeshnull  * performed any necessary updates, the IXGBE_ERR_ACI_NO_WORK is returned,
596*dea5f973SBhosale, Yogeshnull  * and the caller does not obtain the resource and has no further work to do.
597*dea5f973SBhosale, Yogeshnull  * If needed, the function will poll until the current lock owner timeouts.
598*dea5f973SBhosale, Yogeshnull  *
599*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
600*dea5f973SBhosale, Yogeshnull  */
ixgbe_acquire_res(struct ixgbe_hw * hw,enum ixgbe_aci_res_ids res,enum ixgbe_aci_res_access_type access,u32 timeout)601*dea5f973SBhosale, Yogeshnull s32 ixgbe_acquire_res(struct ixgbe_hw *hw, enum ixgbe_aci_res_ids res,
602*dea5f973SBhosale, Yogeshnull 		      enum ixgbe_aci_res_access_type access, u32 timeout)
603*dea5f973SBhosale, Yogeshnull {
604*dea5f973SBhosale, Yogeshnull #define IXGBE_RES_POLLING_DELAY_MS	10
605*dea5f973SBhosale, Yogeshnull 	u32 delay = IXGBE_RES_POLLING_DELAY_MS;
606*dea5f973SBhosale, Yogeshnull 	u32 res_timeout = timeout;
607*dea5f973SBhosale, Yogeshnull 	u32 retry_timeout = 0;
608*dea5f973SBhosale, Yogeshnull 	s32 status;
609*dea5f973SBhosale, Yogeshnull 
610*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_req_res(hw, res, access, 0, &res_timeout);
611*dea5f973SBhosale, Yogeshnull 
612*dea5f973SBhosale, Yogeshnull 	/* A return code of IXGBE_ERR_ACI_NO_WORK means that another driver has
613*dea5f973SBhosale, Yogeshnull 	 * previously acquired the resource and performed any necessary updates;
614*dea5f973SBhosale, Yogeshnull 	 * in this case the caller does not obtain the resource and has no
615*dea5f973SBhosale, Yogeshnull 	 * further work to do.
616*dea5f973SBhosale, Yogeshnull 	 */
617*dea5f973SBhosale, Yogeshnull 	if (status == IXGBE_ERR_ACI_NO_WORK)
618*dea5f973SBhosale, Yogeshnull 		goto ixgbe_acquire_res_exit;
619*dea5f973SBhosale, Yogeshnull 
620*dea5f973SBhosale, Yogeshnull 	/* If necessary, poll until the current lock owner timeouts.
621*dea5f973SBhosale, Yogeshnull 	 * Set retry_timeout to the timeout value reported by the FW in the
622*dea5f973SBhosale, Yogeshnull 	 * response to the "Request Resource Ownership" (0x0008) Admin Command
623*dea5f973SBhosale, Yogeshnull 	 * as it indicates the maximum time the current owner of the resource
624*dea5f973SBhosale, Yogeshnull 	 * is allowed to hold it.
625*dea5f973SBhosale, Yogeshnull 	 */
626*dea5f973SBhosale, Yogeshnull 	retry_timeout = res_timeout;
627*dea5f973SBhosale, Yogeshnull 	while (status && retry_timeout && res_timeout) {
628*dea5f973SBhosale, Yogeshnull 		msec_delay(delay);
629*dea5f973SBhosale, Yogeshnull 		retry_timeout = (retry_timeout > delay) ?
630*dea5f973SBhosale, Yogeshnull 			retry_timeout - delay : 0;
631*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_req_res(hw, res, access, 0, &res_timeout);
632*dea5f973SBhosale, Yogeshnull 
633*dea5f973SBhosale, Yogeshnull 		if (status == IXGBE_ERR_ACI_NO_WORK)
634*dea5f973SBhosale, Yogeshnull 			/* lock free, but no work to do */
635*dea5f973SBhosale, Yogeshnull 			break;
636*dea5f973SBhosale, Yogeshnull 
637*dea5f973SBhosale, Yogeshnull 		if (!status)
638*dea5f973SBhosale, Yogeshnull 			/* lock acquired */
639*dea5f973SBhosale, Yogeshnull 			break;
640*dea5f973SBhosale, Yogeshnull 	}
641*dea5f973SBhosale, Yogeshnull 
642*dea5f973SBhosale, Yogeshnull ixgbe_acquire_res_exit:
643*dea5f973SBhosale, Yogeshnull 	return status;
644*dea5f973SBhosale, Yogeshnull }
645*dea5f973SBhosale, Yogeshnull 
646*dea5f973SBhosale, Yogeshnull /**
647*dea5f973SBhosale, Yogeshnull  * ixgbe_release_res - release a common resource
648*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
649*dea5f973SBhosale, Yogeshnull  * @res: resource ID
650*dea5f973SBhosale, Yogeshnull  *
651*dea5f973SBhosale, Yogeshnull  * Release a common resource using ixgbe_aci_release_res.
652*dea5f973SBhosale, Yogeshnull  */
ixgbe_release_res(struct ixgbe_hw * hw,enum ixgbe_aci_res_ids res)653*dea5f973SBhosale, Yogeshnull void ixgbe_release_res(struct ixgbe_hw *hw, enum ixgbe_aci_res_ids res)
654*dea5f973SBhosale, Yogeshnull {
655*dea5f973SBhosale, Yogeshnull 	u32 total_delay = 0;
656*dea5f973SBhosale, Yogeshnull 	s32 status;
657*dea5f973SBhosale, Yogeshnull 
658*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_release_res(hw, res, 0);
659*dea5f973SBhosale, Yogeshnull 
660*dea5f973SBhosale, Yogeshnull 	/* There are some rare cases when trying to release the resource
661*dea5f973SBhosale, Yogeshnull 	 * results in an admin command timeout, so handle them correctly.
662*dea5f973SBhosale, Yogeshnull 	 */
663*dea5f973SBhosale, Yogeshnull 	while ((status == IXGBE_ERR_ACI_TIMEOUT) &&
664*dea5f973SBhosale, Yogeshnull 	       (total_delay < IXGBE_ACI_RELEASE_RES_TIMEOUT)) {
665*dea5f973SBhosale, Yogeshnull 		msec_delay(1);
666*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_release_res(hw, res, 0);
667*dea5f973SBhosale, Yogeshnull 		total_delay++;
668*dea5f973SBhosale, Yogeshnull 	}
669*dea5f973SBhosale, Yogeshnull }
670*dea5f973SBhosale, Yogeshnull 
671*dea5f973SBhosale, Yogeshnull /**
672*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_common_caps - Parse common device/function capabilities
673*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
674*dea5f973SBhosale, Yogeshnull  * @caps: pointer to common capabilities structure
675*dea5f973SBhosale, Yogeshnull  * @elem: the capability element to parse
676*dea5f973SBhosale, Yogeshnull  * @prefix: message prefix for tracing capabilities
677*dea5f973SBhosale, Yogeshnull  *
678*dea5f973SBhosale, Yogeshnull  * Given a capability element, extract relevant details into the common
679*dea5f973SBhosale, Yogeshnull  * capability structure.
680*dea5f973SBhosale, Yogeshnull  *
681*dea5f973SBhosale, Yogeshnull  * Return: true if the capability matches one of the common capability ids,
682*dea5f973SBhosale, Yogeshnull  * false otherwise.
683*dea5f973SBhosale, Yogeshnull  */
684*dea5f973SBhosale, Yogeshnull static bool
ixgbe_parse_common_caps(struct ixgbe_hw * hw,struct ixgbe_hw_common_caps * caps,struct ixgbe_aci_cmd_list_caps_elem * elem,const char * prefix)685*dea5f973SBhosale, Yogeshnull ixgbe_parse_common_caps(struct ixgbe_hw *hw, struct ixgbe_hw_common_caps *caps,
686*dea5f973SBhosale, Yogeshnull 			struct ixgbe_aci_cmd_list_caps_elem *elem,
687*dea5f973SBhosale, Yogeshnull 			const char *prefix)
688*dea5f973SBhosale, Yogeshnull {
689*dea5f973SBhosale, Yogeshnull 	u32 logical_id = IXGBE_LE32_TO_CPU(elem->logical_id);
690*dea5f973SBhosale, Yogeshnull 	u32 phys_id = IXGBE_LE32_TO_CPU(elem->phys_id);
691*dea5f973SBhosale, Yogeshnull 	u32 number = IXGBE_LE32_TO_CPU(elem->number);
692*dea5f973SBhosale, Yogeshnull 	u16 cap = IXGBE_LE16_TO_CPU(elem->cap);
693*dea5f973SBhosale, Yogeshnull 	bool found = true;
694*dea5f973SBhosale, Yogeshnull 
695*dea5f973SBhosale, Yogeshnull 	UNREFERENCED_1PARAMETER(hw);
696*dea5f973SBhosale, Yogeshnull 
697*dea5f973SBhosale, Yogeshnull 	switch (cap) {
698*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_VALID_FUNCTIONS:
699*dea5f973SBhosale, Yogeshnull 		caps->valid_functions = number;
700*dea5f973SBhosale, Yogeshnull 		break;
701*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_SRIOV:
702*dea5f973SBhosale, Yogeshnull 		caps->sr_iov_1_1 = (number == 1);
703*dea5f973SBhosale, Yogeshnull 		break;
704*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_VMDQ:
705*dea5f973SBhosale, Yogeshnull 		caps->vmdq = (number == 1);
706*dea5f973SBhosale, Yogeshnull 		break;
707*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_DCB:
708*dea5f973SBhosale, Yogeshnull 		caps->dcb = (number == 1);
709*dea5f973SBhosale, Yogeshnull 		caps->active_tc_bitmap = logical_id;
710*dea5f973SBhosale, Yogeshnull 		caps->maxtc = phys_id;
711*dea5f973SBhosale, Yogeshnull 		break;
712*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_RSS:
713*dea5f973SBhosale, Yogeshnull 		caps->rss_table_size = number;
714*dea5f973SBhosale, Yogeshnull 		caps->rss_table_entry_width = logical_id;
715*dea5f973SBhosale, Yogeshnull 		break;
716*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_RXQS:
717*dea5f973SBhosale, Yogeshnull 		caps->num_rxq = number;
718*dea5f973SBhosale, Yogeshnull 		caps->rxq_first_id = phys_id;
719*dea5f973SBhosale, Yogeshnull 		break;
720*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_TXQS:
721*dea5f973SBhosale, Yogeshnull 		caps->num_txq = number;
722*dea5f973SBhosale, Yogeshnull 		caps->txq_first_id = phys_id;
723*dea5f973SBhosale, Yogeshnull 		break;
724*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_MSIX:
725*dea5f973SBhosale, Yogeshnull 		caps->num_msix_vectors = number;
726*dea5f973SBhosale, Yogeshnull 		caps->msix_vector_first_id = phys_id;
727*dea5f973SBhosale, Yogeshnull 		break;
728*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_NVM_VER:
729*dea5f973SBhosale, Yogeshnull 		break;
730*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_NVM_MGMT:
731*dea5f973SBhosale, Yogeshnull 		caps->sec_rev_disabled =
732*dea5f973SBhosale, Yogeshnull 			(number & IXGBE_NVM_MGMT_SEC_REV_DISABLED) ?
733*dea5f973SBhosale, Yogeshnull 			true : false;
734*dea5f973SBhosale, Yogeshnull 		caps->update_disabled =
735*dea5f973SBhosale, Yogeshnull 			(number & IXGBE_NVM_MGMT_UPDATE_DISABLED) ?
736*dea5f973SBhosale, Yogeshnull 			true : false;
737*dea5f973SBhosale, Yogeshnull 		caps->nvm_unified_update =
738*dea5f973SBhosale, Yogeshnull 			(number & IXGBE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
739*dea5f973SBhosale, Yogeshnull 			true : false;
740*dea5f973SBhosale, Yogeshnull 		caps->netlist_auth =
741*dea5f973SBhosale, Yogeshnull 			(number & IXGBE_NVM_MGMT_NETLIST_AUTH_SUPPORT) ?
742*dea5f973SBhosale, Yogeshnull 			true : false;
743*dea5f973SBhosale, Yogeshnull 		break;
744*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_MAX_MTU:
745*dea5f973SBhosale, Yogeshnull 		caps->max_mtu = number;
746*dea5f973SBhosale, Yogeshnull 		break;
747*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_PCIE_RESET_AVOIDANCE:
748*dea5f973SBhosale, Yogeshnull 		caps->pcie_reset_avoidance = (number > 0);
749*dea5f973SBhosale, Yogeshnull 		break;
750*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_POST_UPDATE_RESET_RESTRICT:
751*dea5f973SBhosale, Yogeshnull 		caps->reset_restrict_support = (number == 1);
752*dea5f973SBhosale, Yogeshnull 		break;
753*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG0:
754*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG1:
755*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG2:
756*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG3:
757*dea5f973SBhosale, Yogeshnull 	{
758*dea5f973SBhosale, Yogeshnull 		u8 index = cap - IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG0;
759*dea5f973SBhosale, Yogeshnull 
760*dea5f973SBhosale, Yogeshnull 		caps->ext_topo_dev_img_ver_high[index] = number;
761*dea5f973SBhosale, Yogeshnull 		caps->ext_topo_dev_img_ver_low[index] = logical_id;
762*dea5f973SBhosale, Yogeshnull 		caps->ext_topo_dev_img_part_num[index] =
763*dea5f973SBhosale, Yogeshnull 			(phys_id & IXGBE_EXT_TOPO_DEV_IMG_PART_NUM_M) >>
764*dea5f973SBhosale, Yogeshnull 			IXGBE_EXT_TOPO_DEV_IMG_PART_NUM_S;
765*dea5f973SBhosale, Yogeshnull 		caps->ext_topo_dev_img_load_en[index] =
766*dea5f973SBhosale, Yogeshnull 			(phys_id & IXGBE_EXT_TOPO_DEV_IMG_LOAD_EN) != 0;
767*dea5f973SBhosale, Yogeshnull 		caps->ext_topo_dev_img_prog_en[index] =
768*dea5f973SBhosale, Yogeshnull 			(phys_id & IXGBE_EXT_TOPO_DEV_IMG_PROG_EN) != 0;
769*dea5f973SBhosale, Yogeshnull 		break;
770*dea5f973SBhosale, Yogeshnull 	}
771*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_OROM_RECOVERY_UPDATE:
772*dea5f973SBhosale, Yogeshnull 		caps->orom_recovery_update = (number == 1);
773*dea5f973SBhosale, Yogeshnull 		break;
774*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACI_CAPS_NEXT_CLUSTER_ID:
775*dea5f973SBhosale, Yogeshnull 		caps->next_cluster_id_support = (number == 1);
776*dea5f973SBhosale, Yogeshnull 		DEBUGOUT2("%s: next_cluster_id_support = %d\n",
777*dea5f973SBhosale, Yogeshnull 			  prefix, caps->next_cluster_id_support);
778*dea5f973SBhosale, Yogeshnull 		break;
779*dea5f973SBhosale, Yogeshnull 	default:
780*dea5f973SBhosale, Yogeshnull 		/* Not one of the recognized common capabilities */
781*dea5f973SBhosale, Yogeshnull 		found = false;
782*dea5f973SBhosale, Yogeshnull 	}
783*dea5f973SBhosale, Yogeshnull 
784*dea5f973SBhosale, Yogeshnull 	return found;
785*dea5f973SBhosale, Yogeshnull }
786*dea5f973SBhosale, Yogeshnull 
787*dea5f973SBhosale, Yogeshnull /**
788*dea5f973SBhosale, Yogeshnull  * ixgbe_hweight8 - count set bits among the 8 lowest bits
789*dea5f973SBhosale, Yogeshnull  * @w: variable storing set bits to count
790*dea5f973SBhosale, Yogeshnull  *
791*dea5f973SBhosale, Yogeshnull  * Return: the number of set bits among the 8 lowest bits in the provided value.
792*dea5f973SBhosale, Yogeshnull  */
ixgbe_hweight8(u32 w)793*dea5f973SBhosale, Yogeshnull static u8 ixgbe_hweight8(u32 w)
794*dea5f973SBhosale, Yogeshnull {
795*dea5f973SBhosale, Yogeshnull 	u8 hweight = 0, i;
796*dea5f973SBhosale, Yogeshnull 
797*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < 8; i++)
798*dea5f973SBhosale, Yogeshnull 		if (w & (1 << i))
799*dea5f973SBhosale, Yogeshnull 			hweight++;
800*dea5f973SBhosale, Yogeshnull 
801*dea5f973SBhosale, Yogeshnull 	return hweight;
802*dea5f973SBhosale, Yogeshnull }
803*dea5f973SBhosale, Yogeshnull 
804*dea5f973SBhosale, Yogeshnull /**
805*dea5f973SBhosale, Yogeshnull  * ixgbe_hweight32 - count set bits among the 32 lowest bits
806*dea5f973SBhosale, Yogeshnull  * @w: variable storing set bits to count
807*dea5f973SBhosale, Yogeshnull  *
808*dea5f973SBhosale, Yogeshnull  * Return: the number of set bits among the 32 lowest bits in the
809*dea5f973SBhosale, Yogeshnull  * provided value.
810*dea5f973SBhosale, Yogeshnull  */
ixgbe_hweight32(u32 w)811*dea5f973SBhosale, Yogeshnull static u8 ixgbe_hweight32(u32 w)
812*dea5f973SBhosale, Yogeshnull {
813*dea5f973SBhosale, Yogeshnull 	u32 bitMask = 0x1, i;
814*dea5f973SBhosale, Yogeshnull 	u8  bitCnt = 0;
815*dea5f973SBhosale, Yogeshnull 
816*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < 32; i++)
817*dea5f973SBhosale, Yogeshnull 	{
818*dea5f973SBhosale, Yogeshnull 		if (w & bitMask)
819*dea5f973SBhosale, Yogeshnull 			bitCnt++;
820*dea5f973SBhosale, Yogeshnull 
821*dea5f973SBhosale, Yogeshnull 		bitMask = bitMask << 0x1;
822*dea5f973SBhosale, Yogeshnull 	}
823*dea5f973SBhosale, Yogeshnull 
824*dea5f973SBhosale, Yogeshnull 	return bitCnt;
825*dea5f973SBhosale, Yogeshnull }
826*dea5f973SBhosale, Yogeshnull 
827*dea5f973SBhosale, Yogeshnull /**
828*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_valid_functions_cap - Parse IXGBE_ACI_CAPS_VALID_FUNCTIONS caps
829*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
830*dea5f973SBhosale, Yogeshnull  * @dev_p: pointer to device capabilities structure
831*dea5f973SBhosale, Yogeshnull  * @cap: capability element to parse
832*dea5f973SBhosale, Yogeshnull  *
833*dea5f973SBhosale, Yogeshnull  * Parse IXGBE_ACI_CAPS_VALID_FUNCTIONS for device capabilities.
834*dea5f973SBhosale, Yogeshnull  */
835*dea5f973SBhosale, Yogeshnull static void
ixgbe_parse_valid_functions_cap(struct ixgbe_hw * hw,struct ixgbe_hw_dev_caps * dev_p,struct ixgbe_aci_cmd_list_caps_elem * cap)836*dea5f973SBhosale, Yogeshnull ixgbe_parse_valid_functions_cap(struct ixgbe_hw *hw,
837*dea5f973SBhosale, Yogeshnull 				struct ixgbe_hw_dev_caps *dev_p,
838*dea5f973SBhosale, Yogeshnull 				struct ixgbe_aci_cmd_list_caps_elem *cap)
839*dea5f973SBhosale, Yogeshnull {
840*dea5f973SBhosale, Yogeshnull 	u32 number = IXGBE_LE32_TO_CPU(cap->number);
841*dea5f973SBhosale, Yogeshnull 
842*dea5f973SBhosale, Yogeshnull 	UNREFERENCED_1PARAMETER(hw);
843*dea5f973SBhosale, Yogeshnull 
844*dea5f973SBhosale, Yogeshnull 	dev_p->num_funcs = ixgbe_hweight32(number);
845*dea5f973SBhosale, Yogeshnull }
846*dea5f973SBhosale, Yogeshnull 
847*dea5f973SBhosale, Yogeshnull /**
848*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_vf_dev_caps - Parse IXGBE_ACI_CAPS_VF device caps
849*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
850*dea5f973SBhosale, Yogeshnull  * @dev_p: pointer to device capabilities structure
851*dea5f973SBhosale, Yogeshnull  * @cap: capability element to parse
852*dea5f973SBhosale, Yogeshnull  *
853*dea5f973SBhosale, Yogeshnull  * Parse IXGBE_ACI_CAPS_VF for device capabilities.
854*dea5f973SBhosale, Yogeshnull  */
ixgbe_parse_vf_dev_caps(struct ixgbe_hw * hw,struct ixgbe_hw_dev_caps * dev_p,struct ixgbe_aci_cmd_list_caps_elem * cap)855*dea5f973SBhosale, Yogeshnull static void ixgbe_parse_vf_dev_caps(struct ixgbe_hw *hw,
856*dea5f973SBhosale, Yogeshnull 				    struct ixgbe_hw_dev_caps *dev_p,
857*dea5f973SBhosale, Yogeshnull 				    struct ixgbe_aci_cmd_list_caps_elem *cap)
858*dea5f973SBhosale, Yogeshnull {
859*dea5f973SBhosale, Yogeshnull 	u32 number = IXGBE_LE32_TO_CPU(cap->number);
860*dea5f973SBhosale, Yogeshnull 
861*dea5f973SBhosale, Yogeshnull 	UNREFERENCED_1PARAMETER(hw);
862*dea5f973SBhosale, Yogeshnull 
863*dea5f973SBhosale, Yogeshnull 	dev_p->num_vfs_exposed = number;
864*dea5f973SBhosale, Yogeshnull }
865*dea5f973SBhosale, Yogeshnull 
866*dea5f973SBhosale, Yogeshnull /**
867*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_vsi_dev_caps - Parse IXGBE_ACI_CAPS_VSI device caps
868*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
869*dea5f973SBhosale, Yogeshnull  * @dev_p: pointer to device capabilities structure
870*dea5f973SBhosale, Yogeshnull  * @cap: capability element to parse
871*dea5f973SBhosale, Yogeshnull  *
872*dea5f973SBhosale, Yogeshnull  * Parse IXGBE_ACI_CAPS_VSI for device capabilities.
873*dea5f973SBhosale, Yogeshnull  */
ixgbe_parse_vsi_dev_caps(struct ixgbe_hw * hw,struct ixgbe_hw_dev_caps * dev_p,struct ixgbe_aci_cmd_list_caps_elem * cap)874*dea5f973SBhosale, Yogeshnull static void ixgbe_parse_vsi_dev_caps(struct ixgbe_hw *hw,
875*dea5f973SBhosale, Yogeshnull 				     struct ixgbe_hw_dev_caps *dev_p,
876*dea5f973SBhosale, Yogeshnull 				     struct ixgbe_aci_cmd_list_caps_elem *cap)
877*dea5f973SBhosale, Yogeshnull {
878*dea5f973SBhosale, Yogeshnull 	u32 number = IXGBE_LE32_TO_CPU(cap->number);
879*dea5f973SBhosale, Yogeshnull 
880*dea5f973SBhosale, Yogeshnull 	UNREFERENCED_1PARAMETER(hw);
881*dea5f973SBhosale, Yogeshnull 
882*dea5f973SBhosale, Yogeshnull 	dev_p->num_vsi_allocd_to_host = number;
883*dea5f973SBhosale, Yogeshnull }
884*dea5f973SBhosale, Yogeshnull 
885*dea5f973SBhosale, Yogeshnull /**
886*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_fdir_dev_caps - Parse IXGBE_ACI_CAPS_FD device caps
887*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
888*dea5f973SBhosale, Yogeshnull  * @dev_p: pointer to device capabilities structure
889*dea5f973SBhosale, Yogeshnull  * @cap: capability element to parse
890*dea5f973SBhosale, Yogeshnull  *
891*dea5f973SBhosale, Yogeshnull  * Parse IXGBE_ACI_CAPS_FD for device capabilities.
892*dea5f973SBhosale, Yogeshnull  */
ixgbe_parse_fdir_dev_caps(struct ixgbe_hw * hw,struct ixgbe_hw_dev_caps * dev_p,struct ixgbe_aci_cmd_list_caps_elem * cap)893*dea5f973SBhosale, Yogeshnull static void ixgbe_parse_fdir_dev_caps(struct ixgbe_hw *hw,
894*dea5f973SBhosale, Yogeshnull 				      struct ixgbe_hw_dev_caps *dev_p,
895*dea5f973SBhosale, Yogeshnull 				      struct ixgbe_aci_cmd_list_caps_elem *cap)
896*dea5f973SBhosale, Yogeshnull {
897*dea5f973SBhosale, Yogeshnull 	u32 number = IXGBE_LE32_TO_CPU(cap->number);
898*dea5f973SBhosale, Yogeshnull 
899*dea5f973SBhosale, Yogeshnull 	UNREFERENCED_1PARAMETER(hw);
900*dea5f973SBhosale, Yogeshnull 
901*dea5f973SBhosale, Yogeshnull 	dev_p->num_flow_director_fltr = number;
902*dea5f973SBhosale, Yogeshnull }
903*dea5f973SBhosale, Yogeshnull 
904*dea5f973SBhosale, Yogeshnull /**
905*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_dev_caps - Parse device capabilities
906*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
907*dea5f973SBhosale, Yogeshnull  * @dev_p: pointer to device capabilities structure
908*dea5f973SBhosale, Yogeshnull  * @buf: buffer containing the device capability records
909*dea5f973SBhosale, Yogeshnull  * @cap_count: the number of capabilities
910*dea5f973SBhosale, Yogeshnull  *
911*dea5f973SBhosale, Yogeshnull  * Helper device to parse device (0x000B) capabilities list. For
912*dea5f973SBhosale, Yogeshnull  * capabilities shared between device and function, this relies on
913*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_common_caps.
914*dea5f973SBhosale, Yogeshnull  *
915*dea5f973SBhosale, Yogeshnull  * Loop through the list of provided capabilities and extract the relevant
916*dea5f973SBhosale, Yogeshnull  * data into the device capabilities structured.
917*dea5f973SBhosale, Yogeshnull  */
ixgbe_parse_dev_caps(struct ixgbe_hw * hw,struct ixgbe_hw_dev_caps * dev_p,void * buf,u32 cap_count)918*dea5f973SBhosale, Yogeshnull static void ixgbe_parse_dev_caps(struct ixgbe_hw *hw,
919*dea5f973SBhosale, Yogeshnull 				 struct ixgbe_hw_dev_caps *dev_p,
920*dea5f973SBhosale, Yogeshnull 				 void *buf, u32 cap_count)
921*dea5f973SBhosale, Yogeshnull {
922*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_list_caps_elem *cap_resp;
923*dea5f973SBhosale, Yogeshnull 	u32 i;
924*dea5f973SBhosale, Yogeshnull 
925*dea5f973SBhosale, Yogeshnull 	cap_resp = (struct ixgbe_aci_cmd_list_caps_elem *)buf;
926*dea5f973SBhosale, Yogeshnull 
927*dea5f973SBhosale, Yogeshnull 	memset(dev_p, 0, sizeof(*dev_p));
928*dea5f973SBhosale, Yogeshnull 
929*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < cap_count; i++) {
930*dea5f973SBhosale, Yogeshnull 		u16 cap = IXGBE_LE16_TO_CPU(cap_resp[i].cap);
931*dea5f973SBhosale, Yogeshnull 		bool found;
932*dea5f973SBhosale, Yogeshnull 
933*dea5f973SBhosale, Yogeshnull 		found = ixgbe_parse_common_caps(hw, &dev_p->common_cap,
934*dea5f973SBhosale, Yogeshnull 					      &cap_resp[i], "dev caps");
935*dea5f973SBhosale, Yogeshnull 
936*dea5f973SBhosale, Yogeshnull 		switch (cap) {
937*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_CAPS_VALID_FUNCTIONS:
938*dea5f973SBhosale, Yogeshnull 			ixgbe_parse_valid_functions_cap(hw, dev_p,
939*dea5f973SBhosale, Yogeshnull 							&cap_resp[i]);
940*dea5f973SBhosale, Yogeshnull 			break;
941*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_CAPS_VF:
942*dea5f973SBhosale, Yogeshnull 			ixgbe_parse_vf_dev_caps(hw, dev_p, &cap_resp[i]);
943*dea5f973SBhosale, Yogeshnull 			break;
944*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_CAPS_VSI:
945*dea5f973SBhosale, Yogeshnull 			ixgbe_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
946*dea5f973SBhosale, Yogeshnull 			break;
947*dea5f973SBhosale, Yogeshnull 		case  IXGBE_ACI_CAPS_FD:
948*dea5f973SBhosale, Yogeshnull 			ixgbe_parse_fdir_dev_caps(hw, dev_p, &cap_resp[i]);
949*dea5f973SBhosale, Yogeshnull 			break;
950*dea5f973SBhosale, Yogeshnull 		default:
951*dea5f973SBhosale, Yogeshnull 			/* Don't list common capabilities as unknown */
952*dea5f973SBhosale, Yogeshnull 			if (!found)
953*dea5f973SBhosale, Yogeshnull 				break;
954*dea5f973SBhosale, Yogeshnull 		}
955*dea5f973SBhosale, Yogeshnull 	}
956*dea5f973SBhosale, Yogeshnull 
957*dea5f973SBhosale, Yogeshnull }
958*dea5f973SBhosale, Yogeshnull 
959*dea5f973SBhosale, Yogeshnull /**
960*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_vf_func_caps - Parse IXGBE_ACI_CAPS_VF function caps
961*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
962*dea5f973SBhosale, Yogeshnull  * @func_p: pointer to function capabilities structure
963*dea5f973SBhosale, Yogeshnull  * @cap: pointer to the capability element to parse
964*dea5f973SBhosale, Yogeshnull  *
965*dea5f973SBhosale, Yogeshnull  * Extract function capabilities for IXGBE_ACI_CAPS_VF.
966*dea5f973SBhosale, Yogeshnull  */
ixgbe_parse_vf_func_caps(struct ixgbe_hw * hw,struct ixgbe_hw_func_caps * func_p,struct ixgbe_aci_cmd_list_caps_elem * cap)967*dea5f973SBhosale, Yogeshnull static void ixgbe_parse_vf_func_caps(struct ixgbe_hw *hw,
968*dea5f973SBhosale, Yogeshnull 				     struct ixgbe_hw_func_caps *func_p,
969*dea5f973SBhosale, Yogeshnull 				     struct ixgbe_aci_cmd_list_caps_elem *cap)
970*dea5f973SBhosale, Yogeshnull {
971*dea5f973SBhosale, Yogeshnull 	u32 logical_id = IXGBE_LE32_TO_CPU(cap->logical_id);
972*dea5f973SBhosale, Yogeshnull 	u32 number = IXGBE_LE32_TO_CPU(cap->number);
973*dea5f973SBhosale, Yogeshnull 
974*dea5f973SBhosale, Yogeshnull 	UNREFERENCED_1PARAMETER(hw);
975*dea5f973SBhosale, Yogeshnull 
976*dea5f973SBhosale, Yogeshnull 	func_p->num_allocd_vfs = number;
977*dea5f973SBhosale, Yogeshnull 	func_p->vf_base_id = logical_id;
978*dea5f973SBhosale, Yogeshnull }
979*dea5f973SBhosale, Yogeshnull 
980*dea5f973SBhosale, Yogeshnull /**
981*dea5f973SBhosale, Yogeshnull  * ixgbe_get_num_per_func - determine number of resources per PF
982*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
983*dea5f973SBhosale, Yogeshnull  * @max: value to be evenly split between each PF
984*dea5f973SBhosale, Yogeshnull  *
985*dea5f973SBhosale, Yogeshnull  * Determine the number of valid functions by going through the bitmap returned
986*dea5f973SBhosale, Yogeshnull  * from parsing capabilities and use this to calculate the number of resources
987*dea5f973SBhosale, Yogeshnull  * per PF based on the max value passed in.
988*dea5f973SBhosale, Yogeshnull  *
989*dea5f973SBhosale, Yogeshnull  * Return: the number of resources per PF or 0, if no PH are available.
990*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_num_per_func(struct ixgbe_hw * hw,u32 max)991*dea5f973SBhosale, Yogeshnull static u32 ixgbe_get_num_per_func(struct ixgbe_hw *hw, u32 max)
992*dea5f973SBhosale, Yogeshnull {
993*dea5f973SBhosale, Yogeshnull 	u8 funcs;
994*dea5f973SBhosale, Yogeshnull 
995*dea5f973SBhosale, Yogeshnull #define IXGBE_CAPS_VALID_FUNCS_M	0xFF
996*dea5f973SBhosale, Yogeshnull 	funcs = ixgbe_hweight8(hw->dev_caps.common_cap.valid_functions &
997*dea5f973SBhosale, Yogeshnull 			     IXGBE_CAPS_VALID_FUNCS_M);
998*dea5f973SBhosale, Yogeshnull 
999*dea5f973SBhosale, Yogeshnull 	if (!funcs)
1000*dea5f973SBhosale, Yogeshnull 		return 0;
1001*dea5f973SBhosale, Yogeshnull 
1002*dea5f973SBhosale, Yogeshnull 	return max / funcs;
1003*dea5f973SBhosale, Yogeshnull }
1004*dea5f973SBhosale, Yogeshnull 
1005*dea5f973SBhosale, Yogeshnull /**
1006*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_vsi_func_caps - Parse IXGBE_ACI_CAPS_VSI function caps
1007*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1008*dea5f973SBhosale, Yogeshnull  * @func_p: pointer to function capabilities structure
1009*dea5f973SBhosale, Yogeshnull  * @cap: pointer to the capability element to parse
1010*dea5f973SBhosale, Yogeshnull  *
1011*dea5f973SBhosale, Yogeshnull  * Extract function capabilities for IXGBE_ACI_CAPS_VSI.
1012*dea5f973SBhosale, Yogeshnull  */
ixgbe_parse_vsi_func_caps(struct ixgbe_hw * hw,struct ixgbe_hw_func_caps * func_p,struct ixgbe_aci_cmd_list_caps_elem * cap)1013*dea5f973SBhosale, Yogeshnull static void ixgbe_parse_vsi_func_caps(struct ixgbe_hw *hw,
1014*dea5f973SBhosale, Yogeshnull 				      struct ixgbe_hw_func_caps *func_p,
1015*dea5f973SBhosale, Yogeshnull 				      struct ixgbe_aci_cmd_list_caps_elem *cap)
1016*dea5f973SBhosale, Yogeshnull {
1017*dea5f973SBhosale, Yogeshnull 	func_p->guar_num_vsi = ixgbe_get_num_per_func(hw, IXGBE_MAX_VSI);
1018*dea5f973SBhosale, Yogeshnull }
1019*dea5f973SBhosale, Yogeshnull 
1020*dea5f973SBhosale, Yogeshnull /**
1021*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_func_caps - Parse function capabilities
1022*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1023*dea5f973SBhosale, Yogeshnull  * @func_p: pointer to function capabilities structure
1024*dea5f973SBhosale, Yogeshnull  * @buf: buffer containing the function capability records
1025*dea5f973SBhosale, Yogeshnull  * @cap_count: the number of capabilities
1026*dea5f973SBhosale, Yogeshnull  *
1027*dea5f973SBhosale, Yogeshnull  * Helper function to parse function (0x000A) capabilities list. For
1028*dea5f973SBhosale, Yogeshnull  * capabilities shared between device and function, this relies on
1029*dea5f973SBhosale, Yogeshnull  * ixgbe_parse_common_caps.
1030*dea5f973SBhosale, Yogeshnull  *
1031*dea5f973SBhosale, Yogeshnull  * Loop through the list of provided capabilities and extract the relevant
1032*dea5f973SBhosale, Yogeshnull  * data into the function capabilities structured.
1033*dea5f973SBhosale, Yogeshnull  */
ixgbe_parse_func_caps(struct ixgbe_hw * hw,struct ixgbe_hw_func_caps * func_p,void * buf,u32 cap_count)1034*dea5f973SBhosale, Yogeshnull static void ixgbe_parse_func_caps(struct ixgbe_hw *hw,
1035*dea5f973SBhosale, Yogeshnull 				  struct ixgbe_hw_func_caps *func_p,
1036*dea5f973SBhosale, Yogeshnull 				  void *buf, u32 cap_count)
1037*dea5f973SBhosale, Yogeshnull {
1038*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_list_caps_elem *cap_resp;
1039*dea5f973SBhosale, Yogeshnull 	u32 i;
1040*dea5f973SBhosale, Yogeshnull 
1041*dea5f973SBhosale, Yogeshnull 	cap_resp = (struct ixgbe_aci_cmd_list_caps_elem *)buf;
1042*dea5f973SBhosale, Yogeshnull 
1043*dea5f973SBhosale, Yogeshnull 	memset(func_p, 0, sizeof(*func_p));
1044*dea5f973SBhosale, Yogeshnull 
1045*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < cap_count; i++) {
1046*dea5f973SBhosale, Yogeshnull 		u16 cap = IXGBE_LE16_TO_CPU(cap_resp[i].cap);
1047*dea5f973SBhosale, Yogeshnull 		ixgbe_parse_common_caps(hw, &func_p->common_cap,
1048*dea5f973SBhosale, Yogeshnull 					&cap_resp[i], "func caps");
1049*dea5f973SBhosale, Yogeshnull 
1050*dea5f973SBhosale, Yogeshnull 		switch (cap) {
1051*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_CAPS_VF:
1052*dea5f973SBhosale, Yogeshnull 			ixgbe_parse_vf_func_caps(hw, func_p, &cap_resp[i]);
1053*dea5f973SBhosale, Yogeshnull 			break;
1054*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_CAPS_VSI:
1055*dea5f973SBhosale, Yogeshnull 			ixgbe_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
1056*dea5f973SBhosale, Yogeshnull 			break;
1057*dea5f973SBhosale, Yogeshnull 		default:
1058*dea5f973SBhosale, Yogeshnull 			/* Don't list common capabilities as unknown */
1059*dea5f973SBhosale, Yogeshnull 			break;
1060*dea5f973SBhosale, Yogeshnull 		}
1061*dea5f973SBhosale, Yogeshnull 	}
1062*dea5f973SBhosale, Yogeshnull 
1063*dea5f973SBhosale, Yogeshnull }
1064*dea5f973SBhosale, Yogeshnull 
1065*dea5f973SBhosale, Yogeshnull /**
1066*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_list_caps - query function/device capabilities
1067*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1068*dea5f973SBhosale, Yogeshnull  * @buf: a buffer to hold the capabilities
1069*dea5f973SBhosale, Yogeshnull  * @buf_size: size of the buffer
1070*dea5f973SBhosale, Yogeshnull  * @cap_count: if not NULL, set to the number of capabilities reported
1071*dea5f973SBhosale, Yogeshnull  * @opc: capabilities type to discover, device or function
1072*dea5f973SBhosale, Yogeshnull  *
1073*dea5f973SBhosale, Yogeshnull  * Get the function (0x000A) or device (0x000B) capabilities description from
1074*dea5f973SBhosale, Yogeshnull  * firmware and store it in the buffer.
1075*dea5f973SBhosale, Yogeshnull  *
1076*dea5f973SBhosale, Yogeshnull  * If the cap_count pointer is not NULL, then it is set to the number of
1077*dea5f973SBhosale, Yogeshnull  * capabilities firmware will report. Note that if the buffer size is too
1078*dea5f973SBhosale, Yogeshnull  * small, it is possible the command will return IXGBE_ERR_OUT_OF_MEM. The
1079*dea5f973SBhosale, Yogeshnull  * cap_count will still be updated in this case. It is recommended that the
1080*dea5f973SBhosale, Yogeshnull  * buffer size be set to IXGBE_ACI_MAX_BUFFER_SIZE (the largest possible
1081*dea5f973SBhosale, Yogeshnull  * buffer that firmware could return) to avoid this.
1082*dea5f973SBhosale, Yogeshnull  *
1083*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1084*dea5f973SBhosale, Yogeshnull  * Exit code of IXGBE_ERR_OUT_OF_MEM means the buffer size is too small.
1085*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_list_caps(struct ixgbe_hw * hw,void * buf,u16 buf_size,u32 * cap_count,enum ixgbe_aci_opc opc)1086*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_list_caps(struct ixgbe_hw *hw, void *buf, u16 buf_size,
1087*dea5f973SBhosale, Yogeshnull 			u32 *cap_count, enum ixgbe_aci_opc opc)
1088*dea5f973SBhosale, Yogeshnull {
1089*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_list_caps *cmd;
1090*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1091*dea5f973SBhosale, Yogeshnull 	s32 status;
1092*dea5f973SBhosale, Yogeshnull 
1093*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.get_cap;
1094*dea5f973SBhosale, Yogeshnull 
1095*dea5f973SBhosale, Yogeshnull 	if (opc != ixgbe_aci_opc_list_func_caps &&
1096*dea5f973SBhosale, Yogeshnull 	    opc != ixgbe_aci_opc_list_dev_caps)
1097*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
1098*dea5f973SBhosale, Yogeshnull 
1099*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, opc);
1100*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, buf, buf_size);
1101*dea5f973SBhosale, Yogeshnull 
1102*dea5f973SBhosale, Yogeshnull 	if (cap_count)
1103*dea5f973SBhosale, Yogeshnull 		*cap_count = IXGBE_LE32_TO_CPU(cmd->count);
1104*dea5f973SBhosale, Yogeshnull 
1105*dea5f973SBhosale, Yogeshnull 	return status;
1106*dea5f973SBhosale, Yogeshnull }
1107*dea5f973SBhosale, Yogeshnull 
1108*dea5f973SBhosale, Yogeshnull /**
1109*dea5f973SBhosale, Yogeshnull  * ixgbe_discover_dev_caps - Read and extract device capabilities
1110*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hardware structure
1111*dea5f973SBhosale, Yogeshnull  * @dev_caps: pointer to device capabilities structure
1112*dea5f973SBhosale, Yogeshnull  *
1113*dea5f973SBhosale, Yogeshnull  * Read the device capabilities and extract them into the dev_caps structure
1114*dea5f973SBhosale, Yogeshnull  * for later use.
1115*dea5f973SBhosale, Yogeshnull  *
1116*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1117*dea5f973SBhosale, Yogeshnull  */
ixgbe_discover_dev_caps(struct ixgbe_hw * hw,struct ixgbe_hw_dev_caps * dev_caps)1118*dea5f973SBhosale, Yogeshnull s32 ixgbe_discover_dev_caps(struct ixgbe_hw *hw,
1119*dea5f973SBhosale, Yogeshnull 			    struct ixgbe_hw_dev_caps *dev_caps)
1120*dea5f973SBhosale, Yogeshnull {
1121*dea5f973SBhosale, Yogeshnull 	u32 status, cap_count = 0;
1122*dea5f973SBhosale, Yogeshnull 	u8 *cbuf = NULL;
1123*dea5f973SBhosale, Yogeshnull 
1124*dea5f973SBhosale, Yogeshnull 	cbuf = (u8*)ixgbe_malloc(hw, IXGBE_ACI_MAX_BUFFER_SIZE);
1125*dea5f973SBhosale, Yogeshnull 	if (!cbuf)
1126*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_OUT_OF_MEM;
1127*dea5f973SBhosale, Yogeshnull 	/* Although the driver doesn't know the number of capabilities the
1128*dea5f973SBhosale, Yogeshnull 	 * device will return, we can simply send a 4KB buffer, the maximum
1129*dea5f973SBhosale, Yogeshnull 	 * possible size that firmware can return.
1130*dea5f973SBhosale, Yogeshnull 	 */
1131*dea5f973SBhosale, Yogeshnull 	cap_count = IXGBE_ACI_MAX_BUFFER_SIZE /
1132*dea5f973SBhosale, Yogeshnull 		    sizeof(struct ixgbe_aci_cmd_list_caps_elem);
1133*dea5f973SBhosale, Yogeshnull 
1134*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_list_caps(hw, cbuf, IXGBE_ACI_MAX_BUFFER_SIZE,
1135*dea5f973SBhosale, Yogeshnull 				     &cap_count,
1136*dea5f973SBhosale, Yogeshnull 				     ixgbe_aci_opc_list_dev_caps);
1137*dea5f973SBhosale, Yogeshnull 	if (!status)
1138*dea5f973SBhosale, Yogeshnull 		ixgbe_parse_dev_caps(hw, dev_caps, cbuf, cap_count);
1139*dea5f973SBhosale, Yogeshnull 
1140*dea5f973SBhosale, Yogeshnull 	if (cbuf)
1141*dea5f973SBhosale, Yogeshnull 		ixgbe_free(hw, cbuf);
1142*dea5f973SBhosale, Yogeshnull 
1143*dea5f973SBhosale, Yogeshnull 	return status;
1144*dea5f973SBhosale, Yogeshnull }
1145*dea5f973SBhosale, Yogeshnull 
1146*dea5f973SBhosale, Yogeshnull /**
1147*dea5f973SBhosale, Yogeshnull  * ixgbe_discover_func_caps - Read and extract function capabilities
1148*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hardware structure
1149*dea5f973SBhosale, Yogeshnull  * @func_caps: pointer to function capabilities structure
1150*dea5f973SBhosale, Yogeshnull  *
1151*dea5f973SBhosale, Yogeshnull  * Read the function capabilities and extract them into the func_caps structure
1152*dea5f973SBhosale, Yogeshnull  * for later use.
1153*dea5f973SBhosale, Yogeshnull  *
1154*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1155*dea5f973SBhosale, Yogeshnull  */
ixgbe_discover_func_caps(struct ixgbe_hw * hw,struct ixgbe_hw_func_caps * func_caps)1156*dea5f973SBhosale, Yogeshnull s32 ixgbe_discover_func_caps(struct ixgbe_hw *hw,
1157*dea5f973SBhosale, Yogeshnull 			     struct ixgbe_hw_func_caps *func_caps)
1158*dea5f973SBhosale, Yogeshnull {
1159*dea5f973SBhosale, Yogeshnull 	u32 cap_count = 0;
1160*dea5f973SBhosale, Yogeshnull 	u8 *cbuf = NULL;
1161*dea5f973SBhosale, Yogeshnull 	s32 status;
1162*dea5f973SBhosale, Yogeshnull 
1163*dea5f973SBhosale, Yogeshnull 	cbuf = (u8*)ixgbe_malloc(hw, IXGBE_ACI_MAX_BUFFER_SIZE);
1164*dea5f973SBhosale, Yogeshnull 	if(!cbuf)
1165*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_OUT_OF_MEM;
1166*dea5f973SBhosale, Yogeshnull 	/* Although the driver doesn't know the number of capabilities the
1167*dea5f973SBhosale, Yogeshnull 	 * device will return, we can simply send a 4KB buffer, the maximum
1168*dea5f973SBhosale, Yogeshnull 	 * possible size that firmware can return.
1169*dea5f973SBhosale, Yogeshnull 	 */
1170*dea5f973SBhosale, Yogeshnull 	cap_count = IXGBE_ACI_MAX_BUFFER_SIZE /
1171*dea5f973SBhosale, Yogeshnull 		    sizeof(struct ixgbe_aci_cmd_list_caps_elem);
1172*dea5f973SBhosale, Yogeshnull 
1173*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_list_caps(hw, cbuf, IXGBE_ACI_MAX_BUFFER_SIZE,
1174*dea5f973SBhosale, Yogeshnull 				     &cap_count,
1175*dea5f973SBhosale, Yogeshnull 				     ixgbe_aci_opc_list_func_caps);
1176*dea5f973SBhosale, Yogeshnull 	if (!status)
1177*dea5f973SBhosale, Yogeshnull 		ixgbe_parse_func_caps(hw, func_caps, cbuf, cap_count);
1178*dea5f973SBhosale, Yogeshnull 
1179*dea5f973SBhosale, Yogeshnull 	if (cbuf)
1180*dea5f973SBhosale, Yogeshnull 		ixgbe_free(hw, cbuf);
1181*dea5f973SBhosale, Yogeshnull 
1182*dea5f973SBhosale, Yogeshnull 	return status;
1183*dea5f973SBhosale, Yogeshnull }
1184*dea5f973SBhosale, Yogeshnull 
1185*dea5f973SBhosale, Yogeshnull /**
1186*dea5f973SBhosale, Yogeshnull  * ixgbe_get_caps - get info about the HW
1187*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hardware structure
1188*dea5f973SBhosale, Yogeshnull  *
1189*dea5f973SBhosale, Yogeshnull  * Retrieve both device and function capabilities.
1190*dea5f973SBhosale, Yogeshnull  *
1191*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1192*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_caps(struct ixgbe_hw * hw)1193*dea5f973SBhosale, Yogeshnull s32 ixgbe_get_caps(struct ixgbe_hw *hw)
1194*dea5f973SBhosale, Yogeshnull {
1195*dea5f973SBhosale, Yogeshnull 	s32 status;
1196*dea5f973SBhosale, Yogeshnull 
1197*dea5f973SBhosale, Yogeshnull 	status = ixgbe_discover_dev_caps(hw, &hw->dev_caps);
1198*dea5f973SBhosale, Yogeshnull 	if (status)
1199*dea5f973SBhosale, Yogeshnull 		return status;
1200*dea5f973SBhosale, Yogeshnull 
1201*dea5f973SBhosale, Yogeshnull 	return ixgbe_discover_func_caps(hw, &hw->func_caps);
1202*dea5f973SBhosale, Yogeshnull }
1203*dea5f973SBhosale, Yogeshnull 
1204*dea5f973SBhosale, Yogeshnull /**
1205*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_disable_rxen - disable RX
1206*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1207*dea5f973SBhosale, Yogeshnull  *
1208*dea5f973SBhosale, Yogeshnull  * Request a safe disable of Receive Enable using ACI command (0x000C).
1209*dea5f973SBhosale, Yogeshnull  *
1210*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1211*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_disable_rxen(struct ixgbe_hw * hw)1212*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_disable_rxen(struct ixgbe_hw *hw)
1213*dea5f973SBhosale, Yogeshnull {
1214*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_disable_rxen *cmd;
1215*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1216*dea5f973SBhosale, Yogeshnull 
1217*dea5f973SBhosale, Yogeshnull 	UNREFERENCED_1PARAMETER(hw);
1218*dea5f973SBhosale, Yogeshnull 
1219*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.disable_rxen;
1220*dea5f973SBhosale, Yogeshnull 
1221*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_disable_rxen);
1222*dea5f973SBhosale, Yogeshnull 
1223*dea5f973SBhosale, Yogeshnull 	cmd->lport_num = (u8)hw->bus.func;
1224*dea5f973SBhosale, Yogeshnull 
1225*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
1226*dea5f973SBhosale, Yogeshnull }
1227*dea5f973SBhosale, Yogeshnull 
1228*dea5f973SBhosale, Yogeshnull /**
1229*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_get_phy_caps - returns PHY capabilities
1230*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1231*dea5f973SBhosale, Yogeshnull  * @qual_mods: report qualified modules
1232*dea5f973SBhosale, Yogeshnull  * @report_mode: report mode capabilities
1233*dea5f973SBhosale, Yogeshnull  * @pcaps: structure for PHY capabilities to be filled
1234*dea5f973SBhosale, Yogeshnull  *
1235*dea5f973SBhosale, Yogeshnull  * Returns the various PHY capabilities supported on the Port
1236*dea5f973SBhosale, Yogeshnull  * using ACI command (0x0600).
1237*dea5f973SBhosale, Yogeshnull  *
1238*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1239*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_get_phy_caps(struct ixgbe_hw * hw,bool qual_mods,u8 report_mode,struct ixgbe_aci_cmd_get_phy_caps_data * pcaps)1240*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_get_phy_caps(struct ixgbe_hw *hw, bool qual_mods, u8 report_mode,
1241*dea5f973SBhosale, Yogeshnull 			   struct ixgbe_aci_cmd_get_phy_caps_data *pcaps)
1242*dea5f973SBhosale, Yogeshnull {
1243*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps *cmd;
1244*dea5f973SBhosale, Yogeshnull 	u16 pcaps_size = sizeof(*pcaps);
1245*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1246*dea5f973SBhosale, Yogeshnull 	s32 status;
1247*dea5f973SBhosale, Yogeshnull 
1248*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.get_phy;
1249*dea5f973SBhosale, Yogeshnull 
1250*dea5f973SBhosale, Yogeshnull 	if (!pcaps || (report_mode & ~IXGBE_ACI_REPORT_MODE_M))
1251*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
1252*dea5f973SBhosale, Yogeshnull 
1253*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_phy_caps);
1254*dea5f973SBhosale, Yogeshnull 
1255*dea5f973SBhosale, Yogeshnull 	if (qual_mods)
1256*dea5f973SBhosale, Yogeshnull 		cmd->param0 |= IXGBE_CPU_TO_LE16(IXGBE_ACI_GET_PHY_RQM);
1257*dea5f973SBhosale, Yogeshnull 
1258*dea5f973SBhosale, Yogeshnull 	cmd->param0 |= IXGBE_CPU_TO_LE16(report_mode);
1259*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, pcaps, pcaps_size);
1260*dea5f973SBhosale, Yogeshnull 
1261*dea5f973SBhosale, Yogeshnull 	if (status == IXGBE_SUCCESS &&
1262*dea5f973SBhosale, Yogeshnull 	    report_mode == IXGBE_ACI_REPORT_TOPO_CAP_MEDIA) {
1263*dea5f973SBhosale, Yogeshnull 		hw->phy.phy_type_low = IXGBE_LE64_TO_CPU(pcaps->phy_type_low);
1264*dea5f973SBhosale, Yogeshnull 		hw->phy.phy_type_high = IXGBE_LE64_TO_CPU(pcaps->phy_type_high);
1265*dea5f973SBhosale, Yogeshnull 		memcpy(hw->link.link_info.module_type, &pcaps->module_type,
1266*dea5f973SBhosale, Yogeshnull 			   sizeof(hw->link.link_info.module_type));
1267*dea5f973SBhosale, Yogeshnull 	}
1268*dea5f973SBhosale, Yogeshnull 
1269*dea5f973SBhosale, Yogeshnull 	return status;
1270*dea5f973SBhosale, Yogeshnull }
1271*dea5f973SBhosale, Yogeshnull 
1272*dea5f973SBhosale, Yogeshnull /**
1273*dea5f973SBhosale, Yogeshnull  * ixgbe_phy_caps_equals_cfg - check if capabilities match the PHY config
1274*dea5f973SBhosale, Yogeshnull  * @phy_caps: PHY capabilities
1275*dea5f973SBhosale, Yogeshnull  * @phy_cfg: PHY configuration
1276*dea5f973SBhosale, Yogeshnull  *
1277*dea5f973SBhosale, Yogeshnull  * Helper function to determine if PHY capabilities match PHY
1278*dea5f973SBhosale, Yogeshnull  * configuration
1279*dea5f973SBhosale, Yogeshnull  *
1280*dea5f973SBhosale, Yogeshnull  * Return: true if PHY capabilities match PHY configuration.
1281*dea5f973SBhosale, Yogeshnull  */
1282*dea5f973SBhosale, Yogeshnull bool
ixgbe_phy_caps_equals_cfg(struct ixgbe_aci_cmd_get_phy_caps_data * phy_caps,struct ixgbe_aci_cmd_set_phy_cfg_data * phy_cfg)1283*dea5f973SBhosale, Yogeshnull ixgbe_phy_caps_equals_cfg(struct ixgbe_aci_cmd_get_phy_caps_data *phy_caps,
1284*dea5f973SBhosale, Yogeshnull 			  struct ixgbe_aci_cmd_set_phy_cfg_data *phy_cfg)
1285*dea5f973SBhosale, Yogeshnull {
1286*dea5f973SBhosale, Yogeshnull 	u8 caps_mask, cfg_mask;
1287*dea5f973SBhosale, Yogeshnull 
1288*dea5f973SBhosale, Yogeshnull 	if (!phy_caps || !phy_cfg)
1289*dea5f973SBhosale, Yogeshnull 		return false;
1290*dea5f973SBhosale, Yogeshnull 
1291*dea5f973SBhosale, Yogeshnull 	/* These bits are not common between capabilities and configuration.
1292*dea5f973SBhosale, Yogeshnull 	 * Do not use them to determine equality.
1293*dea5f973SBhosale, Yogeshnull 	 */
1294*dea5f973SBhosale, Yogeshnull 	caps_mask = IXGBE_ACI_PHY_CAPS_MASK & ~(IXGBE_ACI_PHY_AN_MODE |
1295*dea5f973SBhosale, Yogeshnull 					      IXGBE_ACI_PHY_EN_MOD_QUAL);
1296*dea5f973SBhosale, Yogeshnull 	cfg_mask = IXGBE_ACI_PHY_ENA_VALID_MASK &
1297*dea5f973SBhosale, Yogeshnull 		   ~IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
1298*dea5f973SBhosale, Yogeshnull 
1299*dea5f973SBhosale, Yogeshnull 	if (phy_caps->phy_type_low != phy_cfg->phy_type_low ||
1300*dea5f973SBhosale, Yogeshnull 	    phy_caps->phy_type_high != phy_cfg->phy_type_high ||
1301*dea5f973SBhosale, Yogeshnull 	    ((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) ||
1302*dea5f973SBhosale, Yogeshnull 	    phy_caps->low_power_ctrl_an != phy_cfg->low_power_ctrl_an ||
1303*dea5f973SBhosale, Yogeshnull 	    phy_caps->eee_cap != phy_cfg->eee_cap ||
1304*dea5f973SBhosale, Yogeshnull 	    phy_caps->eeer_value != phy_cfg->eeer_value ||
1305*dea5f973SBhosale, Yogeshnull 	    phy_caps->link_fec_options != phy_cfg->link_fec_opt)
1306*dea5f973SBhosale, Yogeshnull 		return false;
1307*dea5f973SBhosale, Yogeshnull 
1308*dea5f973SBhosale, Yogeshnull 	return true;
1309*dea5f973SBhosale, Yogeshnull }
1310*dea5f973SBhosale, Yogeshnull 
1311*dea5f973SBhosale, Yogeshnull /**
1312*dea5f973SBhosale, Yogeshnull  * ixgbe_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
1313*dea5f973SBhosale, Yogeshnull  * @caps: PHY ability structure to copy data from
1314*dea5f973SBhosale, Yogeshnull  * @cfg: PHY configuration structure to copy data to
1315*dea5f973SBhosale, Yogeshnull  *
1316*dea5f973SBhosale, Yogeshnull  * Helper function to copy data from PHY capabilities data structure
1317*dea5f973SBhosale, Yogeshnull  * to PHY configuration data structure
1318*dea5f973SBhosale, Yogeshnull  */
ixgbe_copy_phy_caps_to_cfg(struct ixgbe_aci_cmd_get_phy_caps_data * caps,struct ixgbe_aci_cmd_set_phy_cfg_data * cfg)1319*dea5f973SBhosale, Yogeshnull void ixgbe_copy_phy_caps_to_cfg(struct ixgbe_aci_cmd_get_phy_caps_data *caps,
1320*dea5f973SBhosale, Yogeshnull 				struct ixgbe_aci_cmd_set_phy_cfg_data *cfg)
1321*dea5f973SBhosale, Yogeshnull {
1322*dea5f973SBhosale, Yogeshnull 	if (!caps || !cfg)
1323*dea5f973SBhosale, Yogeshnull 		return;
1324*dea5f973SBhosale, Yogeshnull 
1325*dea5f973SBhosale, Yogeshnull 	memset(cfg, 0, sizeof(*cfg));
1326*dea5f973SBhosale, Yogeshnull 	cfg->phy_type_low = caps->phy_type_low;
1327*dea5f973SBhosale, Yogeshnull 	cfg->phy_type_high = caps->phy_type_high;
1328*dea5f973SBhosale, Yogeshnull 	cfg->caps = caps->caps;
1329*dea5f973SBhosale, Yogeshnull 	cfg->low_power_ctrl_an = caps->low_power_ctrl_an;
1330*dea5f973SBhosale, Yogeshnull 	cfg->eee_cap = caps->eee_cap;
1331*dea5f973SBhosale, Yogeshnull 	cfg->eeer_value = caps->eeer_value;
1332*dea5f973SBhosale, Yogeshnull 	cfg->link_fec_opt = caps->link_fec_options;
1333*dea5f973SBhosale, Yogeshnull 	cfg->module_compliance_enforcement =
1334*dea5f973SBhosale, Yogeshnull 		caps->module_compliance_enforcement;
1335*dea5f973SBhosale, Yogeshnull }
1336*dea5f973SBhosale, Yogeshnull 
1337*dea5f973SBhosale, Yogeshnull /**
1338*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_set_phy_cfg - set PHY configuration
1339*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1340*dea5f973SBhosale, Yogeshnull  * @cfg: structure with PHY configuration data to be set
1341*dea5f973SBhosale, Yogeshnull  *
1342*dea5f973SBhosale, Yogeshnull  * Set the various PHY configuration parameters supported on the Port
1343*dea5f973SBhosale, Yogeshnull  * using ACI command (0x0601).
1344*dea5f973SBhosale, Yogeshnull  * One or more of the Set PHY config parameters may be ignored in an MFP
1345*dea5f973SBhosale, Yogeshnull  * mode as the PF may not have the privilege to set some of the PHY Config
1346*dea5f973SBhosale, Yogeshnull  * parameters.
1347*dea5f973SBhosale, Yogeshnull  *
1348*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1349*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_set_phy_cfg(struct ixgbe_hw * hw,struct ixgbe_aci_cmd_set_phy_cfg_data * cfg)1350*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_set_phy_cfg(struct ixgbe_hw *hw,
1351*dea5f973SBhosale, Yogeshnull 			  struct ixgbe_aci_cmd_set_phy_cfg_data *cfg)
1352*dea5f973SBhosale, Yogeshnull {
1353*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1354*dea5f973SBhosale, Yogeshnull 	s32 status;
1355*dea5f973SBhosale, Yogeshnull 
1356*dea5f973SBhosale, Yogeshnull 	if (!cfg)
1357*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
1358*dea5f973SBhosale, Yogeshnull 
1359*dea5f973SBhosale, Yogeshnull 	/* Ensure that only valid bits of cfg->caps can be turned on. */
1360*dea5f973SBhosale, Yogeshnull 	if (cfg->caps & ~IXGBE_ACI_PHY_ENA_VALID_MASK) {
1361*dea5f973SBhosale, Yogeshnull 		cfg->caps &= IXGBE_ACI_PHY_ENA_VALID_MASK;
1362*dea5f973SBhosale, Yogeshnull 	}
1363*dea5f973SBhosale, Yogeshnull 
1364*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_set_phy_cfg);
1365*dea5f973SBhosale, Yogeshnull 	desc.flags |= IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_RD);
1366*dea5f973SBhosale, Yogeshnull 
1367*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, cfg, sizeof(*cfg));
1368*dea5f973SBhosale, Yogeshnull 
1369*dea5f973SBhosale, Yogeshnull 	if (!status)
1370*dea5f973SBhosale, Yogeshnull 		hw->phy.curr_user_phy_cfg = *cfg;
1371*dea5f973SBhosale, Yogeshnull 
1372*dea5f973SBhosale, Yogeshnull 	return status;
1373*dea5f973SBhosale, Yogeshnull }
1374*dea5f973SBhosale, Yogeshnull 
1375*dea5f973SBhosale, Yogeshnull /**
1376*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_set_link_restart_an - set up link and restart AN
1377*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1378*dea5f973SBhosale, Yogeshnull  * @ena_link: if true: enable link, if false: disable link
1379*dea5f973SBhosale, Yogeshnull  *
1380*dea5f973SBhosale, Yogeshnull  * Function sets up the link and restarts the Auto-Negotiation over the link.
1381*dea5f973SBhosale, Yogeshnull  *
1382*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1383*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_set_link_restart_an(struct ixgbe_hw * hw,bool ena_link)1384*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_set_link_restart_an(struct ixgbe_hw *hw, bool ena_link)
1385*dea5f973SBhosale, Yogeshnull {
1386*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_restart_an *cmd;
1387*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1388*dea5f973SBhosale, Yogeshnull 
1389*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.restart_an;
1390*dea5f973SBhosale, Yogeshnull 
1391*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_restart_an);
1392*dea5f973SBhosale, Yogeshnull 
1393*dea5f973SBhosale, Yogeshnull 	cmd->cmd_flags = IXGBE_ACI_RESTART_AN_LINK_RESTART;
1394*dea5f973SBhosale, Yogeshnull 	if (ena_link)
1395*dea5f973SBhosale, Yogeshnull 		cmd->cmd_flags |= IXGBE_ACI_RESTART_AN_LINK_ENABLE;
1396*dea5f973SBhosale, Yogeshnull 	else
1397*dea5f973SBhosale, Yogeshnull 		cmd->cmd_flags &= ~IXGBE_ACI_RESTART_AN_LINK_ENABLE;
1398*dea5f973SBhosale, Yogeshnull 
1399*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
1400*dea5f973SBhosale, Yogeshnull }
1401*dea5f973SBhosale, Yogeshnull 
1402*dea5f973SBhosale, Yogeshnull /**
1403*dea5f973SBhosale, Yogeshnull  * ixgbe_is_media_cage_present - check if media cage is present
1404*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1405*dea5f973SBhosale, Yogeshnull  *
1406*dea5f973SBhosale, Yogeshnull  * Identify presence of media cage using the ACI command (0x06E0).
1407*dea5f973SBhosale, Yogeshnull  *
1408*dea5f973SBhosale, Yogeshnull  * Return: true if media cage is present, else false. If no cage, then
1409*dea5f973SBhosale, Yogeshnull  * media type is backplane or BASE-T.
1410*dea5f973SBhosale, Yogeshnull  */
ixgbe_is_media_cage_present(struct ixgbe_hw * hw)1411*dea5f973SBhosale, Yogeshnull static bool ixgbe_is_media_cage_present(struct ixgbe_hw *hw)
1412*dea5f973SBhosale, Yogeshnull {
1413*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_link_topo *cmd;
1414*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1415*dea5f973SBhosale, Yogeshnull 
1416*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.get_link_topo;
1417*dea5f973SBhosale, Yogeshnull 
1418*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_link_topo);
1419*dea5f973SBhosale, Yogeshnull 
1420*dea5f973SBhosale, Yogeshnull 	cmd->addr.topo_params.node_type_ctx =
1421*dea5f973SBhosale, Yogeshnull 		(IXGBE_ACI_LINK_TOPO_NODE_CTX_PORT <<
1422*dea5f973SBhosale, Yogeshnull 		 IXGBE_ACI_LINK_TOPO_NODE_CTX_S);
1423*dea5f973SBhosale, Yogeshnull 
1424*dea5f973SBhosale, Yogeshnull 	/* set node type */
1425*dea5f973SBhosale, Yogeshnull 	cmd->addr.topo_params.node_type_ctx |=
1426*dea5f973SBhosale, Yogeshnull 		(IXGBE_ACI_LINK_TOPO_NODE_TYPE_M &
1427*dea5f973SBhosale, Yogeshnull 		 IXGBE_ACI_LINK_TOPO_NODE_TYPE_CAGE);
1428*dea5f973SBhosale, Yogeshnull 
1429*dea5f973SBhosale, Yogeshnull 	/* Node type cage can be used to determine if cage is present. If AQC
1430*dea5f973SBhosale, Yogeshnull 	 * returns error (ENOENT), then no cage present. If no cage present then
1431*dea5f973SBhosale, Yogeshnull 	 * connection type is backplane or BASE-T.
1432*dea5f973SBhosale, Yogeshnull 	 */
1433*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_get_netlist_node(hw, cmd, NULL, NULL);
1434*dea5f973SBhosale, Yogeshnull }
1435*dea5f973SBhosale, Yogeshnull 
1436*dea5f973SBhosale, Yogeshnull /**
1437*dea5f973SBhosale, Yogeshnull  * ixgbe_get_media_type_from_phy_type - Gets media type based on phy type
1438*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1439*dea5f973SBhosale, Yogeshnull  *
1440*dea5f973SBhosale, Yogeshnull  * Try to identify the media type based on the phy type.
1441*dea5f973SBhosale, Yogeshnull  * If more than one media type, the ixgbe_media_type_unknown is returned.
1442*dea5f973SBhosale, Yogeshnull  * First, phy_type_low is checked, then phy_type_high.
1443*dea5f973SBhosale, Yogeshnull  * If none are identified, the ixgbe_media_type_unknown is returned
1444*dea5f973SBhosale, Yogeshnull  *
1445*dea5f973SBhosale, Yogeshnull  * Return: type of a media based on phy type in form of enum.
1446*dea5f973SBhosale, Yogeshnull  */
1447*dea5f973SBhosale, Yogeshnull static enum ixgbe_media_type
ixgbe_get_media_type_from_phy_type(struct ixgbe_hw * hw)1448*dea5f973SBhosale, Yogeshnull ixgbe_get_media_type_from_phy_type(struct ixgbe_hw *hw)
1449*dea5f973SBhosale, Yogeshnull {
1450*dea5f973SBhosale, Yogeshnull 	struct ixgbe_link_status *hw_link_info;
1451*dea5f973SBhosale, Yogeshnull 
1452*dea5f973SBhosale, Yogeshnull 	if (!hw)
1453*dea5f973SBhosale, Yogeshnull 		return ixgbe_media_type_unknown;
1454*dea5f973SBhosale, Yogeshnull 
1455*dea5f973SBhosale, Yogeshnull 	hw_link_info = &hw->link.link_info;
1456*dea5f973SBhosale, Yogeshnull 	if (hw_link_info->phy_type_low && hw_link_info->phy_type_high)
1457*dea5f973SBhosale, Yogeshnull 		/* If more than one media type is selected, report unknown */
1458*dea5f973SBhosale, Yogeshnull 		return ixgbe_media_type_unknown;
1459*dea5f973SBhosale, Yogeshnull 
1460*dea5f973SBhosale, Yogeshnull 	if (hw_link_info->phy_type_low) {
1461*dea5f973SBhosale, Yogeshnull 		/* 1G SGMII is a special case where some DA cable PHYs
1462*dea5f973SBhosale, Yogeshnull 		 * may show this as an option when it really shouldn't
1463*dea5f973SBhosale, Yogeshnull 		 * be since SGMII is meant to be between a MAC and a PHY
1464*dea5f973SBhosale, Yogeshnull 		 * in a backplane. Try to detect this case and handle it
1465*dea5f973SBhosale, Yogeshnull 		 */
1466*dea5f973SBhosale, Yogeshnull 		if (hw_link_info->phy_type_low == IXGBE_PHY_TYPE_LOW_1G_SGMII &&
1467*dea5f973SBhosale, Yogeshnull 		    (hw_link_info->module_type[IXGBE_ACI_MOD_TYPE_IDENT] ==
1468*dea5f973SBhosale, Yogeshnull 		    IXGBE_ACI_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE ||
1469*dea5f973SBhosale, Yogeshnull 		    hw_link_info->module_type[IXGBE_ACI_MOD_TYPE_IDENT] ==
1470*dea5f973SBhosale, Yogeshnull 		    IXGBE_ACI_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE))
1471*dea5f973SBhosale, Yogeshnull 			return ixgbe_media_type_da;
1472*dea5f973SBhosale, Yogeshnull 
1473*dea5f973SBhosale, Yogeshnull 		switch (hw_link_info->phy_type_low) {
1474*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_1000BASE_SX:
1475*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_1000BASE_LX:
1476*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_10GBASE_SR:
1477*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_10GBASE_LR:
1478*dea5f973SBhosale, Yogeshnull 			return ixgbe_media_type_fiber;
1479*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
1480*dea5f973SBhosale, Yogeshnull 			return ixgbe_media_type_fiber;
1481*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_100BASE_TX:
1482*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_1000BASE_T:
1483*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_2500BASE_T:
1484*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_5GBASE_T:
1485*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_10GBASE_T:
1486*dea5f973SBhosale, Yogeshnull 			return ixgbe_media_type_copper;
1487*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_10G_SFI_DA:
1488*dea5f973SBhosale, Yogeshnull 			return ixgbe_media_type_da;
1489*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_1000BASE_KX:
1490*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_2500BASE_KX:
1491*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_2500BASE_X:
1492*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_5GBASE_KR:
1493*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_10GBASE_KR_CR1:
1494*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_LOW_10G_SFI_C2C:
1495*dea5f973SBhosale, Yogeshnull 			return ixgbe_media_type_backplane;
1496*dea5f973SBhosale, Yogeshnull 		}
1497*dea5f973SBhosale, Yogeshnull 	} else {
1498*dea5f973SBhosale, Yogeshnull 		switch (hw_link_info->phy_type_high) {
1499*dea5f973SBhosale, Yogeshnull 		case IXGBE_PHY_TYPE_HIGH_10BASE_T:
1500*dea5f973SBhosale, Yogeshnull 			return ixgbe_media_type_copper;
1501*dea5f973SBhosale, Yogeshnull 		}
1502*dea5f973SBhosale, Yogeshnull 	}
1503*dea5f973SBhosale, Yogeshnull 	return ixgbe_media_type_unknown;
1504*dea5f973SBhosale, Yogeshnull }
1505*dea5f973SBhosale, Yogeshnull 
1506*dea5f973SBhosale, Yogeshnull /**
1507*dea5f973SBhosale, Yogeshnull  * ixgbe_update_link_info - update status of the HW network link
1508*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1509*dea5f973SBhosale, Yogeshnull  *
1510*dea5f973SBhosale, Yogeshnull  * Update the status of the HW network link.
1511*dea5f973SBhosale, Yogeshnull  *
1512*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1513*dea5f973SBhosale, Yogeshnull  */
ixgbe_update_link_info(struct ixgbe_hw * hw)1514*dea5f973SBhosale, Yogeshnull s32 ixgbe_update_link_info(struct ixgbe_hw *hw)
1515*dea5f973SBhosale, Yogeshnull {
1516*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data *pcaps;
1517*dea5f973SBhosale, Yogeshnull 	struct ixgbe_link_status *li;
1518*dea5f973SBhosale, Yogeshnull 	s32 status;
1519*dea5f973SBhosale, Yogeshnull 
1520*dea5f973SBhosale, Yogeshnull 	if (!hw)
1521*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
1522*dea5f973SBhosale, Yogeshnull 
1523*dea5f973SBhosale, Yogeshnull 	li = &hw->link.link_info;
1524*dea5f973SBhosale, Yogeshnull 
1525*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_get_link_info(hw, true, NULL);
1526*dea5f973SBhosale, Yogeshnull 	if (status)
1527*dea5f973SBhosale, Yogeshnull 		return status;
1528*dea5f973SBhosale, Yogeshnull 
1529*dea5f973SBhosale, Yogeshnull 	if (li->link_info & IXGBE_ACI_MEDIA_AVAILABLE) {
1530*dea5f973SBhosale, Yogeshnull 		pcaps = (struct ixgbe_aci_cmd_get_phy_caps_data *)
1531*dea5f973SBhosale, Yogeshnull 			ixgbe_malloc(hw, sizeof(*pcaps));
1532*dea5f973SBhosale, Yogeshnull 		if (!pcaps)
1533*dea5f973SBhosale, Yogeshnull 			return IXGBE_ERR_OUT_OF_MEM;
1534*dea5f973SBhosale, Yogeshnull 
1535*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_get_phy_caps(hw, false,
1536*dea5f973SBhosale, Yogeshnull 						IXGBE_ACI_REPORT_TOPO_CAP_MEDIA,
1537*dea5f973SBhosale, Yogeshnull 						pcaps);
1538*dea5f973SBhosale, Yogeshnull 
1539*dea5f973SBhosale, Yogeshnull 		if (status == IXGBE_SUCCESS)
1540*dea5f973SBhosale, Yogeshnull 			memcpy(li->module_type, &pcaps->module_type,
1541*dea5f973SBhosale, Yogeshnull 			       sizeof(li->module_type));
1542*dea5f973SBhosale, Yogeshnull 
1543*dea5f973SBhosale, Yogeshnull 		ixgbe_free(hw, pcaps);
1544*dea5f973SBhosale, Yogeshnull 	}
1545*dea5f973SBhosale, Yogeshnull 
1546*dea5f973SBhosale, Yogeshnull 	return status;
1547*dea5f973SBhosale, Yogeshnull }
1548*dea5f973SBhosale, Yogeshnull 
1549*dea5f973SBhosale, Yogeshnull /**
1550*dea5f973SBhosale, Yogeshnull  * ixgbe_get_link_status - get status of the HW network link
1551*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1552*dea5f973SBhosale, Yogeshnull  * @link_up: pointer to bool (true/false = linkup/linkdown)
1553*dea5f973SBhosale, Yogeshnull  *
1554*dea5f973SBhosale, Yogeshnull  * Variable link_up is true if link is up, false if link is down.
1555*dea5f973SBhosale, Yogeshnull  * The variable link_up is invalid if status is non zero. As a
1556*dea5f973SBhosale, Yogeshnull  * result of this call, link status reporting becomes enabled
1557*dea5f973SBhosale, Yogeshnull  *
1558*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1559*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_link_status(struct ixgbe_hw * hw,bool * link_up)1560*dea5f973SBhosale, Yogeshnull s32 ixgbe_get_link_status(struct ixgbe_hw *hw, bool *link_up)
1561*dea5f973SBhosale, Yogeshnull {
1562*dea5f973SBhosale, Yogeshnull 	s32 status = IXGBE_SUCCESS;
1563*dea5f973SBhosale, Yogeshnull 
1564*dea5f973SBhosale, Yogeshnull 	if (!hw || !link_up)
1565*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
1566*dea5f973SBhosale, Yogeshnull 
1567*dea5f973SBhosale, Yogeshnull 	if (hw->link.get_link_info) {
1568*dea5f973SBhosale, Yogeshnull 		status = ixgbe_update_link_info(hw);
1569*dea5f973SBhosale, Yogeshnull 		if (status) {
1570*dea5f973SBhosale, Yogeshnull 			return status;
1571*dea5f973SBhosale, Yogeshnull 		}
1572*dea5f973SBhosale, Yogeshnull 	}
1573*dea5f973SBhosale, Yogeshnull 
1574*dea5f973SBhosale, Yogeshnull 	*link_up = hw->link.link_info.link_info & IXGBE_ACI_LINK_UP;
1575*dea5f973SBhosale, Yogeshnull 
1576*dea5f973SBhosale, Yogeshnull 	return status;
1577*dea5f973SBhosale, Yogeshnull }
1578*dea5f973SBhosale, Yogeshnull 
1579*dea5f973SBhosale, Yogeshnull /**
1580*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_get_link_info - get the link status
1581*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1582*dea5f973SBhosale, Yogeshnull  * @ena_lse: enable/disable LinkStatusEvent reporting
1583*dea5f973SBhosale, Yogeshnull  * @link: pointer to link status structure - optional
1584*dea5f973SBhosale, Yogeshnull  *
1585*dea5f973SBhosale, Yogeshnull  * Get the current Link Status using ACI command (0x607).
1586*dea5f973SBhosale, Yogeshnull  * The current link can be optionally provided to update
1587*dea5f973SBhosale, Yogeshnull  * the status.
1588*dea5f973SBhosale, Yogeshnull  *
1589*dea5f973SBhosale, Yogeshnull  * Return: the link status of the adapter.
1590*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_get_link_info(struct ixgbe_hw * hw,bool ena_lse,struct ixgbe_link_status * link)1591*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_get_link_info(struct ixgbe_hw *hw, bool ena_lse,
1592*dea5f973SBhosale, Yogeshnull 			    struct ixgbe_link_status *link)
1593*dea5f973SBhosale, Yogeshnull {
1594*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_link_status_data link_data = { 0 };
1595*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_link_status *resp;
1596*dea5f973SBhosale, Yogeshnull 	struct ixgbe_link_status *li_old, *li;
1597*dea5f973SBhosale, Yogeshnull 	struct ixgbe_fc_info *hw_fc_info;
1598*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1599*dea5f973SBhosale, Yogeshnull 	bool tx_pause, rx_pause;
1600*dea5f973SBhosale, Yogeshnull 	u8 cmd_flags;
1601*dea5f973SBhosale, Yogeshnull 	s32 status;
1602*dea5f973SBhosale, Yogeshnull 
1603*dea5f973SBhosale, Yogeshnull 	if (!hw)
1604*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
1605*dea5f973SBhosale, Yogeshnull 
1606*dea5f973SBhosale, Yogeshnull 	li_old = &hw->link.link_info_old;
1607*dea5f973SBhosale, Yogeshnull 	li = &hw->link.link_info;
1608*dea5f973SBhosale, Yogeshnull 	hw_fc_info = &hw->fc;
1609*dea5f973SBhosale, Yogeshnull 
1610*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_link_status);
1611*dea5f973SBhosale, Yogeshnull 	cmd_flags = (ena_lse) ? IXGBE_ACI_LSE_ENA : IXGBE_ACI_LSE_DIS;
1612*dea5f973SBhosale, Yogeshnull 	resp = &desc.params.get_link_status;
1613*dea5f973SBhosale, Yogeshnull 	resp->cmd_flags = cmd_flags;
1614*dea5f973SBhosale, Yogeshnull 
1615*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, &link_data, sizeof(link_data));
1616*dea5f973SBhosale, Yogeshnull 
1617*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS)
1618*dea5f973SBhosale, Yogeshnull 		return status;
1619*dea5f973SBhosale, Yogeshnull 
1620*dea5f973SBhosale, Yogeshnull 	/* save off old link status information */
1621*dea5f973SBhosale, Yogeshnull 	*li_old = *li;
1622*dea5f973SBhosale, Yogeshnull 
1623*dea5f973SBhosale, Yogeshnull 	/* update current link status information */
1624*dea5f973SBhosale, Yogeshnull 	li->link_speed = IXGBE_LE16_TO_CPU(link_data.link_speed);
1625*dea5f973SBhosale, Yogeshnull 	li->phy_type_low = IXGBE_LE64_TO_CPU(link_data.phy_type_low);
1626*dea5f973SBhosale, Yogeshnull 	li->phy_type_high = IXGBE_LE64_TO_CPU(link_data.phy_type_high);
1627*dea5f973SBhosale, Yogeshnull 	li->link_info = link_data.link_info;
1628*dea5f973SBhosale, Yogeshnull 	li->link_cfg_err = link_data.link_cfg_err;
1629*dea5f973SBhosale, Yogeshnull 	li->an_info = link_data.an_info;
1630*dea5f973SBhosale, Yogeshnull 	li->ext_info = link_data.ext_info;
1631*dea5f973SBhosale, Yogeshnull 	li->max_frame_size = IXGBE_LE16_TO_CPU(link_data.max_frame_size);
1632*dea5f973SBhosale, Yogeshnull 	li->fec_info = link_data.cfg & IXGBE_ACI_FEC_MASK;
1633*dea5f973SBhosale, Yogeshnull 	li->topo_media_conflict = link_data.topo_media_conflict;
1634*dea5f973SBhosale, Yogeshnull 	li->pacing = link_data.cfg & (IXGBE_ACI_CFG_PACING_M |
1635*dea5f973SBhosale, Yogeshnull 				      IXGBE_ACI_CFG_PACING_TYPE_M);
1636*dea5f973SBhosale, Yogeshnull 
1637*dea5f973SBhosale, Yogeshnull 	/* update fc info */
1638*dea5f973SBhosale, Yogeshnull 	tx_pause = !!(link_data.an_info & IXGBE_ACI_LINK_PAUSE_TX);
1639*dea5f973SBhosale, Yogeshnull 	rx_pause = !!(link_data.an_info & IXGBE_ACI_LINK_PAUSE_RX);
1640*dea5f973SBhosale, Yogeshnull 	if (tx_pause && rx_pause)
1641*dea5f973SBhosale, Yogeshnull 		hw_fc_info->current_mode = ixgbe_fc_full;
1642*dea5f973SBhosale, Yogeshnull 	else if (tx_pause)
1643*dea5f973SBhosale, Yogeshnull 		hw_fc_info->current_mode = ixgbe_fc_tx_pause;
1644*dea5f973SBhosale, Yogeshnull 	else if (rx_pause)
1645*dea5f973SBhosale, Yogeshnull 		hw_fc_info->current_mode = ixgbe_fc_rx_pause;
1646*dea5f973SBhosale, Yogeshnull 	else
1647*dea5f973SBhosale, Yogeshnull 		hw_fc_info->current_mode = ixgbe_fc_none;
1648*dea5f973SBhosale, Yogeshnull 
1649*dea5f973SBhosale, Yogeshnull 	li->lse_ena = !!(resp->cmd_flags & IXGBE_ACI_LSE_IS_ENABLED);
1650*dea5f973SBhosale, Yogeshnull 
1651*dea5f973SBhosale, Yogeshnull 	/* save link status information */
1652*dea5f973SBhosale, Yogeshnull 	if (link)
1653*dea5f973SBhosale, Yogeshnull 		*link = *li;
1654*dea5f973SBhosale, Yogeshnull 
1655*dea5f973SBhosale, Yogeshnull 	/* flag cleared so calling functions don't call AQ again */
1656*dea5f973SBhosale, Yogeshnull 	hw->link.get_link_info = false;
1657*dea5f973SBhosale, Yogeshnull 
1658*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
1659*dea5f973SBhosale, Yogeshnull }
1660*dea5f973SBhosale, Yogeshnull 
1661*dea5f973SBhosale, Yogeshnull /**
1662*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_set_event_mask - set event mask
1663*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1664*dea5f973SBhosale, Yogeshnull  * @port_num: port number of the physical function
1665*dea5f973SBhosale, Yogeshnull  * @mask: event mask to be set
1666*dea5f973SBhosale, Yogeshnull  *
1667*dea5f973SBhosale, Yogeshnull  * Set the event mask using ACI command (0x0613).
1668*dea5f973SBhosale, Yogeshnull  *
1669*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1670*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_set_event_mask(struct ixgbe_hw * hw,u8 port_num,u16 mask)1671*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_set_event_mask(struct ixgbe_hw *hw, u8 port_num, u16 mask)
1672*dea5f973SBhosale, Yogeshnull {
1673*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_set_event_mask *cmd;
1674*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1675*dea5f973SBhosale, Yogeshnull 
1676*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.set_event_mask;
1677*dea5f973SBhosale, Yogeshnull 
1678*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_set_event_mask);
1679*dea5f973SBhosale, Yogeshnull 
1680*dea5f973SBhosale, Yogeshnull 	cmd->event_mask = IXGBE_CPU_TO_LE16(mask);
1681*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
1682*dea5f973SBhosale, Yogeshnull }
1683*dea5f973SBhosale, Yogeshnull 
1684*dea5f973SBhosale, Yogeshnull /**
1685*dea5f973SBhosale, Yogeshnull  * ixgbe_configure_lse - enable/disable link status events
1686*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1687*dea5f973SBhosale, Yogeshnull  * @activate: bool value deciding if lse should be enabled nor disabled
1688*dea5f973SBhosale, Yogeshnull  * @mask: event mask to be set; a set bit means deactivation of the
1689*dea5f973SBhosale, Yogeshnull  * corresponding event
1690*dea5f973SBhosale, Yogeshnull  *
1691*dea5f973SBhosale, Yogeshnull  * Set the event mask and then enable or disable link status events
1692*dea5f973SBhosale, Yogeshnull  *
1693*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1694*dea5f973SBhosale, Yogeshnull  */
ixgbe_configure_lse(struct ixgbe_hw * hw,bool activate,u16 mask)1695*dea5f973SBhosale, Yogeshnull s32 ixgbe_configure_lse(struct ixgbe_hw *hw, bool activate, u16 mask)
1696*dea5f973SBhosale, Yogeshnull {
1697*dea5f973SBhosale, Yogeshnull 	s32 rc;
1698*dea5f973SBhosale, Yogeshnull 
1699*dea5f973SBhosale, Yogeshnull 	rc = ixgbe_aci_set_event_mask(hw, (u8)hw->bus.func, mask);
1700*dea5f973SBhosale, Yogeshnull 	if (rc) {
1701*dea5f973SBhosale, Yogeshnull 		return rc;
1702*dea5f973SBhosale, Yogeshnull 	}
1703*dea5f973SBhosale, Yogeshnull 
1704*dea5f973SBhosale, Yogeshnull 	/* Enabling link status events generation by fw */
1705*dea5f973SBhosale, Yogeshnull 	rc = ixgbe_aci_get_link_info(hw, activate, NULL);
1706*dea5f973SBhosale, Yogeshnull 	if (rc) {
1707*dea5f973SBhosale, Yogeshnull 		return rc;
1708*dea5f973SBhosale, Yogeshnull 	}
1709*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
1710*dea5f973SBhosale, Yogeshnull }
1711*dea5f973SBhosale, Yogeshnull 
1712*dea5f973SBhosale, Yogeshnull /**
1713*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_get_netlist_node - get a node handle
1714*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hw struct
1715*dea5f973SBhosale, Yogeshnull  * @cmd: get_link_topo AQ structure
1716*dea5f973SBhosale, Yogeshnull  * @node_part_number: output node part number if node found
1717*dea5f973SBhosale, Yogeshnull  * @node_handle: output node handle parameter if node found
1718*dea5f973SBhosale, Yogeshnull  *
1719*dea5f973SBhosale, Yogeshnull  * Get the netlist node and assigns it to
1720*dea5f973SBhosale, Yogeshnull  * the provided handle using ACI command (0x06E0).
1721*dea5f973SBhosale, Yogeshnull  *
1722*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1723*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_get_netlist_node(struct ixgbe_hw * hw,struct ixgbe_aci_cmd_get_link_topo * cmd,u8 * node_part_number,u16 * node_handle)1724*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_get_netlist_node(struct ixgbe_hw *hw,
1725*dea5f973SBhosale, Yogeshnull 			       struct ixgbe_aci_cmd_get_link_topo *cmd,
1726*dea5f973SBhosale, Yogeshnull 			       u8 *node_part_number, u16 *node_handle)
1727*dea5f973SBhosale, Yogeshnull {
1728*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1729*dea5f973SBhosale, Yogeshnull 
1730*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_link_topo);
1731*dea5f973SBhosale, Yogeshnull 	desc.params.get_link_topo = *cmd;
1732*dea5f973SBhosale, Yogeshnull 
1733*dea5f973SBhosale, Yogeshnull 	if (ixgbe_aci_send_cmd(hw, &desc, NULL, 0))
1734*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_NOT_SUPPORTED;
1735*dea5f973SBhosale, Yogeshnull 
1736*dea5f973SBhosale, Yogeshnull 	if (node_handle)
1737*dea5f973SBhosale, Yogeshnull 		*node_handle =
1738*dea5f973SBhosale, Yogeshnull 			IXGBE_LE16_TO_CPU(desc.params.get_link_topo.addr.handle);
1739*dea5f973SBhosale, Yogeshnull 	if (node_part_number)
1740*dea5f973SBhosale, Yogeshnull 		*node_part_number = desc.params.get_link_topo.node_part_num;
1741*dea5f973SBhosale, Yogeshnull 
1742*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
1743*dea5f973SBhosale, Yogeshnull }
1744*dea5f973SBhosale, Yogeshnull 
1745*dea5f973SBhosale, Yogeshnull /**
1746*dea5f973SBhosale, Yogeshnull  * ixgbe_find_netlist_node - find a node handle
1747*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hw struct
1748*dea5f973SBhosale, Yogeshnull  * @node_type_ctx: type of netlist node to look for
1749*dea5f973SBhosale, Yogeshnull  * @node_part_number: node part number to look for
1750*dea5f973SBhosale, Yogeshnull  * @node_handle: output parameter if node found - optional
1751*dea5f973SBhosale, Yogeshnull  *
1752*dea5f973SBhosale, Yogeshnull  * Find and return the node handle for a given node type and part number in the
1753*dea5f973SBhosale, Yogeshnull  * netlist. When found IXGBE_SUCCESS is returned, IXGBE_ERR_NOT_SUPPORTED
1754*dea5f973SBhosale, Yogeshnull  * otherwise. If @node_handle provided, it would be set to found node handle.
1755*dea5f973SBhosale, Yogeshnull  *
1756*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1757*dea5f973SBhosale, Yogeshnull  */
ixgbe_find_netlist_node(struct ixgbe_hw * hw,u8 node_type_ctx,u8 node_part_number,u16 * node_handle)1758*dea5f973SBhosale, Yogeshnull s32 ixgbe_find_netlist_node(struct ixgbe_hw *hw, u8 node_type_ctx,
1759*dea5f973SBhosale, Yogeshnull 			    u8 node_part_number, u16 *node_handle)
1760*dea5f973SBhosale, Yogeshnull {
1761*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_link_topo cmd;
1762*dea5f973SBhosale, Yogeshnull 	u8 rec_node_part_number;
1763*dea5f973SBhosale, Yogeshnull 	u16 rec_node_handle;
1764*dea5f973SBhosale, Yogeshnull 	s32 status;
1765*dea5f973SBhosale, Yogeshnull 	u8 idx;
1766*dea5f973SBhosale, Yogeshnull 
1767*dea5f973SBhosale, Yogeshnull 	for (idx = 0; idx < IXGBE_MAX_NETLIST_SIZE; idx++) {
1768*dea5f973SBhosale, Yogeshnull 		memset(&cmd, 0, sizeof(cmd));
1769*dea5f973SBhosale, Yogeshnull 
1770*dea5f973SBhosale, Yogeshnull 		cmd.addr.topo_params.node_type_ctx =
1771*dea5f973SBhosale, Yogeshnull 			(node_type_ctx << IXGBE_ACI_LINK_TOPO_NODE_TYPE_S);
1772*dea5f973SBhosale, Yogeshnull 		cmd.addr.topo_params.index = idx;
1773*dea5f973SBhosale, Yogeshnull 
1774*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_get_netlist_node(hw, &cmd,
1775*dea5f973SBhosale, Yogeshnull 						    &rec_node_part_number,
1776*dea5f973SBhosale, Yogeshnull 						    &rec_node_handle);
1777*dea5f973SBhosale, Yogeshnull 		if (status)
1778*dea5f973SBhosale, Yogeshnull 			return status;
1779*dea5f973SBhosale, Yogeshnull 
1780*dea5f973SBhosale, Yogeshnull 		if (rec_node_part_number == node_part_number) {
1781*dea5f973SBhosale, Yogeshnull 			if (node_handle)
1782*dea5f973SBhosale, Yogeshnull 				*node_handle = rec_node_handle;
1783*dea5f973SBhosale, Yogeshnull 			return IXGBE_SUCCESS;
1784*dea5f973SBhosale, Yogeshnull 		}
1785*dea5f973SBhosale, Yogeshnull 	}
1786*dea5f973SBhosale, Yogeshnull 
1787*dea5f973SBhosale, Yogeshnull 	return IXGBE_ERR_NOT_SUPPORTED;
1788*dea5f973SBhosale, Yogeshnull }
1789*dea5f973SBhosale, Yogeshnull 
1790*dea5f973SBhosale, Yogeshnull /**
1791*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_read_i2c - read I2C register value
1792*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hw struct
1793*dea5f973SBhosale, Yogeshnull  * @topo_addr: topology address for a device to communicate with
1794*dea5f973SBhosale, Yogeshnull  * @bus_addr: 7-bit I2C bus address
1795*dea5f973SBhosale, Yogeshnull  * @addr: I2C memory address (I2C offset) with up to 16 bits
1796*dea5f973SBhosale, Yogeshnull  * @params: I2C parameters: bit [7] - Repeated start,
1797*dea5f973SBhosale, Yogeshnull  *				      bits [6:5] data offset size,
1798*dea5f973SBhosale, Yogeshnull  *			    bit [4] - I2C address type, bits [3:0] - data size
1799*dea5f973SBhosale, Yogeshnull  *				      to read (0-16 bytes)
1800*dea5f973SBhosale, Yogeshnull  * @data: pointer to data (0 to 16 bytes) to be read from the I2C device
1801*dea5f973SBhosale, Yogeshnull  *
1802*dea5f973SBhosale, Yogeshnull  * Read the value of the I2C pin register using ACI command (0x06E2).
1803*dea5f973SBhosale, Yogeshnull  *
1804*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1805*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_read_i2c(struct ixgbe_hw * hw,struct ixgbe_aci_cmd_link_topo_addr topo_addr,u16 bus_addr,__le16 addr,u8 params,u8 * data)1806*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_read_i2c(struct ixgbe_hw *hw,
1807*dea5f973SBhosale, Yogeshnull 		       struct ixgbe_aci_cmd_link_topo_addr topo_addr,
1808*dea5f973SBhosale, Yogeshnull 		       u16 bus_addr, __le16 addr, u8 params, u8 *data)
1809*dea5f973SBhosale, Yogeshnull {
1810*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc = { 0 };
1811*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_i2c *cmd;
1812*dea5f973SBhosale, Yogeshnull 	u8 data_size;
1813*dea5f973SBhosale, Yogeshnull 	s32 status;
1814*dea5f973SBhosale, Yogeshnull 
1815*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_read_i2c);
1816*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.read_write_i2c;
1817*dea5f973SBhosale, Yogeshnull 
1818*dea5f973SBhosale, Yogeshnull 	if (!data)
1819*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
1820*dea5f973SBhosale, Yogeshnull 
1821*dea5f973SBhosale, Yogeshnull 	data_size = (params & IXGBE_ACI_I2C_DATA_SIZE_M) >>
1822*dea5f973SBhosale, Yogeshnull 		    IXGBE_ACI_I2C_DATA_SIZE_S;
1823*dea5f973SBhosale, Yogeshnull 
1824*dea5f973SBhosale, Yogeshnull 	cmd->i2c_bus_addr = IXGBE_CPU_TO_LE16(bus_addr);
1825*dea5f973SBhosale, Yogeshnull 	cmd->topo_addr = topo_addr;
1826*dea5f973SBhosale, Yogeshnull 	cmd->i2c_params = params;
1827*dea5f973SBhosale, Yogeshnull 	cmd->i2c_addr = addr;
1828*dea5f973SBhosale, Yogeshnull 
1829*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
1830*dea5f973SBhosale, Yogeshnull 	if (!status) {
1831*dea5f973SBhosale, Yogeshnull 		struct ixgbe_aci_cmd_read_i2c_resp *resp;
1832*dea5f973SBhosale, Yogeshnull 		u8 i;
1833*dea5f973SBhosale, Yogeshnull 
1834*dea5f973SBhosale, Yogeshnull 		resp = &desc.params.read_i2c_resp;
1835*dea5f973SBhosale, Yogeshnull 		for (i = 0; i < data_size; i++) {
1836*dea5f973SBhosale, Yogeshnull 			*data = resp->i2c_data[i];
1837*dea5f973SBhosale, Yogeshnull 			data++;
1838*dea5f973SBhosale, Yogeshnull 		}
1839*dea5f973SBhosale, Yogeshnull 	}
1840*dea5f973SBhosale, Yogeshnull 
1841*dea5f973SBhosale, Yogeshnull 	return status;
1842*dea5f973SBhosale, Yogeshnull }
1843*dea5f973SBhosale, Yogeshnull 
1844*dea5f973SBhosale, Yogeshnull /**
1845*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_write_i2c - write a value to I2C register
1846*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hw struct
1847*dea5f973SBhosale, Yogeshnull  * @topo_addr: topology address for a device to communicate with
1848*dea5f973SBhosale, Yogeshnull  * @bus_addr: 7-bit I2C bus address
1849*dea5f973SBhosale, Yogeshnull  * @addr: I2C memory address (I2C offset) with up to 16 bits
1850*dea5f973SBhosale, Yogeshnull  * @params: I2C parameters: bit [4] - I2C address type, bits [3:0] - data size
1851*dea5f973SBhosale, Yogeshnull  *				      to write (0-7 bytes)
1852*dea5f973SBhosale, Yogeshnull  * @data: pointer to data (0 to 4 bytes) to be written to the I2C device
1853*dea5f973SBhosale, Yogeshnull  *
1854*dea5f973SBhosale, Yogeshnull  * Write a value to the I2C pin register using ACI command (0x06E3).
1855*dea5f973SBhosale, Yogeshnull  *
1856*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1857*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_write_i2c(struct ixgbe_hw * hw,struct ixgbe_aci_cmd_link_topo_addr topo_addr,u16 bus_addr,__le16 addr,u8 params,u8 * data)1858*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_write_i2c(struct ixgbe_hw *hw,
1859*dea5f973SBhosale, Yogeshnull 			struct ixgbe_aci_cmd_link_topo_addr topo_addr,
1860*dea5f973SBhosale, Yogeshnull 			u16 bus_addr, __le16 addr, u8 params, u8 *data)
1861*dea5f973SBhosale, Yogeshnull {
1862*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc = { 0 };
1863*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_i2c *cmd;
1864*dea5f973SBhosale, Yogeshnull 	u8 i, data_size;
1865*dea5f973SBhosale, Yogeshnull 
1866*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_write_i2c);
1867*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.read_write_i2c;
1868*dea5f973SBhosale, Yogeshnull 
1869*dea5f973SBhosale, Yogeshnull 	data_size = (params & IXGBE_ACI_I2C_DATA_SIZE_M) >>
1870*dea5f973SBhosale, Yogeshnull 		    IXGBE_ACI_I2C_DATA_SIZE_S;
1871*dea5f973SBhosale, Yogeshnull 
1872*dea5f973SBhosale, Yogeshnull 	/* data_size limited to 4 */
1873*dea5f973SBhosale, Yogeshnull 	if (data_size > 4)
1874*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
1875*dea5f973SBhosale, Yogeshnull 
1876*dea5f973SBhosale, Yogeshnull 	cmd->i2c_bus_addr = IXGBE_CPU_TO_LE16(bus_addr);
1877*dea5f973SBhosale, Yogeshnull 	cmd->topo_addr = topo_addr;
1878*dea5f973SBhosale, Yogeshnull 	cmd->i2c_params = params;
1879*dea5f973SBhosale, Yogeshnull 	cmd->i2c_addr = addr;
1880*dea5f973SBhosale, Yogeshnull 
1881*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < data_size; i++) {
1882*dea5f973SBhosale, Yogeshnull 		cmd->i2c_data[i] = *data;
1883*dea5f973SBhosale, Yogeshnull 		data++;
1884*dea5f973SBhosale, Yogeshnull 	}
1885*dea5f973SBhosale, Yogeshnull 
1886*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
1887*dea5f973SBhosale, Yogeshnull }
1888*dea5f973SBhosale, Yogeshnull 
1889*dea5f973SBhosale, Yogeshnull /**
1890*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_set_port_id_led - set LED value for the given port
1891*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1892*dea5f973SBhosale, Yogeshnull  * @orig_mode: set LED original mode
1893*dea5f973SBhosale, Yogeshnull  *
1894*dea5f973SBhosale, Yogeshnull  * Set LED value for the given port (0x06E9)
1895*dea5f973SBhosale, Yogeshnull  *
1896*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1897*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_set_port_id_led(struct ixgbe_hw * hw,bool orig_mode)1898*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_set_port_id_led(struct ixgbe_hw *hw, bool orig_mode)
1899*dea5f973SBhosale, Yogeshnull {
1900*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_set_port_id_led *cmd;
1901*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1902*dea5f973SBhosale, Yogeshnull 
1903*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.set_port_id_led;
1904*dea5f973SBhosale, Yogeshnull 
1905*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_set_port_id_led);
1906*dea5f973SBhosale, Yogeshnull 
1907*dea5f973SBhosale, Yogeshnull 	cmd->lport_num = (u8)hw->bus.func;
1908*dea5f973SBhosale, Yogeshnull 	cmd->lport_num_valid = IXGBE_ACI_PORT_ID_PORT_NUM_VALID;
1909*dea5f973SBhosale, Yogeshnull 
1910*dea5f973SBhosale, Yogeshnull 	if (orig_mode)
1911*dea5f973SBhosale, Yogeshnull 		cmd->ident_mode = IXGBE_ACI_PORT_IDENT_LED_ORIG;
1912*dea5f973SBhosale, Yogeshnull 	else
1913*dea5f973SBhosale, Yogeshnull 		cmd->ident_mode = IXGBE_ACI_PORT_IDENT_LED_BLINK;
1914*dea5f973SBhosale, Yogeshnull 
1915*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
1916*dea5f973SBhosale, Yogeshnull }
1917*dea5f973SBhosale, Yogeshnull 
1918*dea5f973SBhosale, Yogeshnull /**
1919*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_set_gpio - set GPIO pin state
1920*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hw struct
1921*dea5f973SBhosale, Yogeshnull  * @gpio_ctrl_handle: GPIO controller node handle
1922*dea5f973SBhosale, Yogeshnull  * @pin_idx: IO Number of the GPIO that needs to be set
1923*dea5f973SBhosale, Yogeshnull  * @value: SW provide IO value to set in the LSB
1924*dea5f973SBhosale, Yogeshnull  *
1925*dea5f973SBhosale, Yogeshnull  * Set the GPIO pin state that is a part of the topology
1926*dea5f973SBhosale, Yogeshnull  * using ACI command (0x06EC).
1927*dea5f973SBhosale, Yogeshnull  *
1928*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1929*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_set_gpio(struct ixgbe_hw * hw,u16 gpio_ctrl_handle,u8 pin_idx,bool value)1930*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_set_gpio(struct ixgbe_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
1931*dea5f973SBhosale, Yogeshnull 		       bool value)
1932*dea5f973SBhosale, Yogeshnull {
1933*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_gpio *cmd;
1934*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1935*dea5f973SBhosale, Yogeshnull 
1936*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_set_gpio);
1937*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.read_write_gpio;
1938*dea5f973SBhosale, Yogeshnull 	cmd->gpio_ctrl_handle = IXGBE_CPU_TO_LE16(gpio_ctrl_handle);
1939*dea5f973SBhosale, Yogeshnull 	cmd->gpio_num = pin_idx;
1940*dea5f973SBhosale, Yogeshnull 	cmd->gpio_val = value ? 1 : 0;
1941*dea5f973SBhosale, Yogeshnull 
1942*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
1943*dea5f973SBhosale, Yogeshnull }
1944*dea5f973SBhosale, Yogeshnull 
1945*dea5f973SBhosale, Yogeshnull /**
1946*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_get_gpio - get GPIO pin state
1947*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hw struct
1948*dea5f973SBhosale, Yogeshnull  * @gpio_ctrl_handle: GPIO controller node handle
1949*dea5f973SBhosale, Yogeshnull  * @pin_idx: IO Number of the GPIO that needs to be set
1950*dea5f973SBhosale, Yogeshnull  * @value: IO value read
1951*dea5f973SBhosale, Yogeshnull  *
1952*dea5f973SBhosale, Yogeshnull  * Get the value of a GPIO signal which is part of the topology
1953*dea5f973SBhosale, Yogeshnull  * using ACI command (0x06ED).
1954*dea5f973SBhosale, Yogeshnull  *
1955*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1956*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_get_gpio(struct ixgbe_hw * hw,u16 gpio_ctrl_handle,u8 pin_idx,bool * value)1957*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_get_gpio(struct ixgbe_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
1958*dea5f973SBhosale, Yogeshnull 		       bool *value)
1959*dea5f973SBhosale, Yogeshnull {
1960*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_gpio *cmd;
1961*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1962*dea5f973SBhosale, Yogeshnull 	s32 status;
1963*dea5f973SBhosale, Yogeshnull 
1964*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_gpio);
1965*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.read_write_gpio;
1966*dea5f973SBhosale, Yogeshnull 	cmd->gpio_ctrl_handle = IXGBE_CPU_TO_LE16(gpio_ctrl_handle);
1967*dea5f973SBhosale, Yogeshnull 	cmd->gpio_num = pin_idx;
1968*dea5f973SBhosale, Yogeshnull 
1969*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
1970*dea5f973SBhosale, Yogeshnull 	if (status)
1971*dea5f973SBhosale, Yogeshnull 		return status;
1972*dea5f973SBhosale, Yogeshnull 
1973*dea5f973SBhosale, Yogeshnull 	*value = !!cmd->gpio_val;
1974*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
1975*dea5f973SBhosale, Yogeshnull }
1976*dea5f973SBhosale, Yogeshnull 
1977*dea5f973SBhosale, Yogeshnull /**
1978*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_sff_eeprom - read/write SFF EEPROM
1979*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
1980*dea5f973SBhosale, Yogeshnull  * @lport: bits [7:0] = logical port, bit [8] = logical port valid
1981*dea5f973SBhosale, Yogeshnull  * @bus_addr: I2C bus address of the eeprom (typically 0xA0, 0=topo default)
1982*dea5f973SBhosale, Yogeshnull  * @mem_addr: I2C offset. lower 8 bits for address, 8 upper bits zero padding.
1983*dea5f973SBhosale, Yogeshnull  * @page: QSFP page
1984*dea5f973SBhosale, Yogeshnull  * @page_bank_ctrl: configuration of SFF/CMIS paging and banking control
1985*dea5f973SBhosale, Yogeshnull  * @data: pointer to data buffer to be read/written to the I2C device.
1986*dea5f973SBhosale, Yogeshnull  * @length: 1-16 for read, 1 for write.
1987*dea5f973SBhosale, Yogeshnull  * @write: 0 read, 1 for write.
1988*dea5f973SBhosale, Yogeshnull  *
1989*dea5f973SBhosale, Yogeshnull  * Read/write SFF EEPROM using ACI command (0x06EE).
1990*dea5f973SBhosale, Yogeshnull  *
1991*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
1992*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_sff_eeprom(struct ixgbe_hw * hw,u16 lport,u8 bus_addr,u16 mem_addr,u8 page,u8 page_bank_ctrl,u8 * data,u8 length,bool write)1993*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_sff_eeprom(struct ixgbe_hw *hw, u16 lport, u8 bus_addr,
1994*dea5f973SBhosale, Yogeshnull 			 u16 mem_addr, u8 page, u8 page_bank_ctrl, u8 *data,
1995*dea5f973SBhosale, Yogeshnull 			 u8 length, bool write)
1996*dea5f973SBhosale, Yogeshnull {
1997*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_sff_eeprom *cmd;
1998*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
1999*dea5f973SBhosale, Yogeshnull 	s32 status;
2000*dea5f973SBhosale, Yogeshnull 
2001*dea5f973SBhosale, Yogeshnull 	if (!data || (mem_addr & 0xff00))
2002*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
2003*dea5f973SBhosale, Yogeshnull 
2004*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_sff_eeprom);
2005*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.read_write_sff_param;
2006*dea5f973SBhosale, Yogeshnull 	desc.flags = IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_RD);
2007*dea5f973SBhosale, Yogeshnull 	cmd->lport_num = (u8)(lport & 0xff);
2008*dea5f973SBhosale, Yogeshnull 	cmd->lport_num_valid = (u8)((lport >> 8) & 0x01);
2009*dea5f973SBhosale, Yogeshnull 	cmd->i2c_bus_addr = IXGBE_CPU_TO_LE16(((bus_addr >> 1) &
2010*dea5f973SBhosale, Yogeshnull 					 IXGBE_ACI_SFF_I2CBUS_7BIT_M) |
2011*dea5f973SBhosale, Yogeshnull 					((page_bank_ctrl <<
2012*dea5f973SBhosale, Yogeshnull 					  IXGBE_ACI_SFF_PAGE_BANK_CTRL_S) &
2013*dea5f973SBhosale, Yogeshnull 					 IXGBE_ACI_SFF_PAGE_BANK_CTRL_M));
2014*dea5f973SBhosale, Yogeshnull 	cmd->i2c_offset = IXGBE_CPU_TO_LE16(mem_addr & 0xff);
2015*dea5f973SBhosale, Yogeshnull 	cmd->module_page = page;
2016*dea5f973SBhosale, Yogeshnull 	if (write)
2017*dea5f973SBhosale, Yogeshnull 		cmd->i2c_bus_addr |= IXGBE_CPU_TO_LE16(IXGBE_ACI_SFF_IS_WRITE);
2018*dea5f973SBhosale, Yogeshnull 
2019*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, data, length);
2020*dea5f973SBhosale, Yogeshnull 	return status;
2021*dea5f973SBhosale, Yogeshnull }
2022*dea5f973SBhosale, Yogeshnull 
2023*dea5f973SBhosale, Yogeshnull /**
2024*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_prog_topo_dev_nvm - program Topology Device NVM
2025*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hardware structure
2026*dea5f973SBhosale, Yogeshnull  * @topo_params: pointer to structure storing topology parameters for a device
2027*dea5f973SBhosale, Yogeshnull  *
2028*dea5f973SBhosale, Yogeshnull  * Program Topology Device NVM using ACI command (0x06F2).
2029*dea5f973SBhosale, Yogeshnull  *
2030*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2031*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_prog_topo_dev_nvm(struct ixgbe_hw * hw,struct ixgbe_aci_cmd_link_topo_params * topo_params)2032*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_prog_topo_dev_nvm(struct ixgbe_hw *hw,
2033*dea5f973SBhosale, Yogeshnull 			struct ixgbe_aci_cmd_link_topo_params *topo_params)
2034*dea5f973SBhosale, Yogeshnull {
2035*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_prog_topo_dev_nvm *cmd;
2036*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
2037*dea5f973SBhosale, Yogeshnull 
2038*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.prog_topo_dev_nvm;
2039*dea5f973SBhosale, Yogeshnull 
2040*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_prog_topo_dev_nvm);
2041*dea5f973SBhosale, Yogeshnull 
2042*dea5f973SBhosale, Yogeshnull 	memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params));
2043*dea5f973SBhosale, Yogeshnull 
2044*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
2045*dea5f973SBhosale, Yogeshnull }
2046*dea5f973SBhosale, Yogeshnull 
2047*dea5f973SBhosale, Yogeshnull /**
2048*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_read_topo_dev_nvm - read Topology Device NVM
2049*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hardware structure
2050*dea5f973SBhosale, Yogeshnull  * @topo_params: pointer to structure storing topology parameters for a device
2051*dea5f973SBhosale, Yogeshnull  * @start_address: byte offset in the topology device NVM
2052*dea5f973SBhosale, Yogeshnull  * @data: pointer to data buffer
2053*dea5f973SBhosale, Yogeshnull  * @data_size: number of bytes to be read from the topology device NVM
2054*dea5f973SBhosale, Yogeshnull  * Read Topology Device NVM (0x06F3)
2055*dea5f973SBhosale, Yogeshnull  *
2056*dea5f973SBhosale, Yogeshnull  * Read Topology of Device NVM using ACI command (0x06F3).
2057*dea5f973SBhosale, Yogeshnull  *
2058*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2059*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_read_topo_dev_nvm(struct ixgbe_hw * hw,struct ixgbe_aci_cmd_link_topo_params * topo_params,u32 start_address,u8 * data,u8 data_size)2060*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_read_topo_dev_nvm(struct ixgbe_hw *hw,
2061*dea5f973SBhosale, Yogeshnull 			struct ixgbe_aci_cmd_link_topo_params *topo_params,
2062*dea5f973SBhosale, Yogeshnull 			u32 start_address, u8 *data, u8 data_size)
2063*dea5f973SBhosale, Yogeshnull {
2064*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_read_topo_dev_nvm *cmd;
2065*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
2066*dea5f973SBhosale, Yogeshnull 	s32 status;
2067*dea5f973SBhosale, Yogeshnull 
2068*dea5f973SBhosale, Yogeshnull 	if (!data || data_size == 0 ||
2069*dea5f973SBhosale, Yogeshnull 	    data_size > IXGBE_ACI_READ_TOPO_DEV_NVM_DATA_READ_SIZE)
2070*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
2071*dea5f973SBhosale, Yogeshnull 
2072*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.read_topo_dev_nvm;
2073*dea5f973SBhosale, Yogeshnull 
2074*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_read_topo_dev_nvm);
2075*dea5f973SBhosale, Yogeshnull 
2076*dea5f973SBhosale, Yogeshnull 	desc.datalen = IXGBE_CPU_TO_LE16(data_size);
2077*dea5f973SBhosale, Yogeshnull 	memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params));
2078*dea5f973SBhosale, Yogeshnull 	cmd->start_address = IXGBE_CPU_TO_LE32(start_address);
2079*dea5f973SBhosale, Yogeshnull 
2080*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
2081*dea5f973SBhosale, Yogeshnull 	if (status)
2082*dea5f973SBhosale, Yogeshnull 		return status;
2083*dea5f973SBhosale, Yogeshnull 
2084*dea5f973SBhosale, Yogeshnull 	memcpy(data, cmd->data_read, data_size);
2085*dea5f973SBhosale, Yogeshnull 
2086*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
2087*dea5f973SBhosale, Yogeshnull }
2088*dea5f973SBhosale, Yogeshnull 
2089*dea5f973SBhosale, Yogeshnull /**
2090*dea5f973SBhosale, Yogeshnull  * ixgbe_acquire_nvm - Generic request for acquiring the NVM ownership
2091*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
2092*dea5f973SBhosale, Yogeshnull  * @access: NVM access type (read or write)
2093*dea5f973SBhosale, Yogeshnull  *
2094*dea5f973SBhosale, Yogeshnull  * Request NVM ownership.
2095*dea5f973SBhosale, Yogeshnull  *
2096*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2097*dea5f973SBhosale, Yogeshnull  */
ixgbe_acquire_nvm(struct ixgbe_hw * hw,enum ixgbe_aci_res_access_type access)2098*dea5f973SBhosale, Yogeshnull s32 ixgbe_acquire_nvm(struct ixgbe_hw *hw,
2099*dea5f973SBhosale, Yogeshnull 		      enum ixgbe_aci_res_access_type access)
2100*dea5f973SBhosale, Yogeshnull {
2101*dea5f973SBhosale, Yogeshnull 	u32 fla;
2102*dea5f973SBhosale, Yogeshnull 
2103*dea5f973SBhosale, Yogeshnull 	/* Skip if we are in blank NVM programming mode */
2104*dea5f973SBhosale, Yogeshnull 	fla = IXGBE_READ_REG(hw, GLNVM_FLA);
2105*dea5f973SBhosale, Yogeshnull 	if ((fla & GLNVM_FLA_LOCKED_M) == 0)
2106*dea5f973SBhosale, Yogeshnull 		return IXGBE_SUCCESS;
2107*dea5f973SBhosale, Yogeshnull 
2108*dea5f973SBhosale, Yogeshnull 	return ixgbe_acquire_res(hw, IXGBE_NVM_RES_ID, access,
2109*dea5f973SBhosale, Yogeshnull 				 IXGBE_NVM_TIMEOUT);
2110*dea5f973SBhosale, Yogeshnull }
2111*dea5f973SBhosale, Yogeshnull 
2112*dea5f973SBhosale, Yogeshnull /**
2113*dea5f973SBhosale, Yogeshnull  * ixgbe_release_nvm - Generic request for releasing the NVM ownership
2114*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
2115*dea5f973SBhosale, Yogeshnull  *
2116*dea5f973SBhosale, Yogeshnull  * Release NVM ownership.
2117*dea5f973SBhosale, Yogeshnull  */
ixgbe_release_nvm(struct ixgbe_hw * hw)2118*dea5f973SBhosale, Yogeshnull void ixgbe_release_nvm(struct ixgbe_hw *hw)
2119*dea5f973SBhosale, Yogeshnull {
2120*dea5f973SBhosale, Yogeshnull 	u32 fla;
2121*dea5f973SBhosale, Yogeshnull 
2122*dea5f973SBhosale, Yogeshnull 	/* Skip if we are in blank NVM programming mode */
2123*dea5f973SBhosale, Yogeshnull 	fla = IXGBE_READ_REG(hw, GLNVM_FLA);
2124*dea5f973SBhosale, Yogeshnull 	if ((fla & GLNVM_FLA_LOCKED_M) == 0)
2125*dea5f973SBhosale, Yogeshnull 		return;
2126*dea5f973SBhosale, Yogeshnull 
2127*dea5f973SBhosale, Yogeshnull 	ixgbe_release_res(hw, IXGBE_NVM_RES_ID);
2128*dea5f973SBhosale, Yogeshnull }
2129*dea5f973SBhosale, Yogeshnull 
2130*dea5f973SBhosale, Yogeshnull 
2131*dea5f973SBhosale, Yogeshnull /**
2132*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_read_nvm - read NVM
2133*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2134*dea5f973SBhosale, Yogeshnull  * @module_typeid: module pointer location in words from the NVM beginning
2135*dea5f973SBhosale, Yogeshnull  * @offset: byte offset from the module beginning
2136*dea5f973SBhosale, Yogeshnull  * @length: length of the section to be read (in bytes from the offset)
2137*dea5f973SBhosale, Yogeshnull  * @data: command buffer (size [bytes] = length)
2138*dea5f973SBhosale, Yogeshnull  * @last_command: tells if this is the last command in a series
2139*dea5f973SBhosale, Yogeshnull  * @read_shadow_ram: tell if this is a shadow RAM read
2140*dea5f973SBhosale, Yogeshnull  *
2141*dea5f973SBhosale, Yogeshnull  * Read the NVM using ACI command (0x0701).
2142*dea5f973SBhosale, Yogeshnull  *
2143*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2144*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_read_nvm(struct ixgbe_hw * hw,u16 module_typeid,u32 offset,u16 length,void * data,bool last_command,bool read_shadow_ram)2145*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_read_nvm(struct ixgbe_hw *hw, u16 module_typeid, u32 offset,
2146*dea5f973SBhosale, Yogeshnull 		       u16 length, void *data, bool last_command,
2147*dea5f973SBhosale, Yogeshnull 		       bool read_shadow_ram)
2148*dea5f973SBhosale, Yogeshnull {
2149*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
2150*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm *cmd;
2151*dea5f973SBhosale, Yogeshnull 
2152*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.nvm;
2153*dea5f973SBhosale, Yogeshnull 
2154*dea5f973SBhosale, Yogeshnull 	if (offset > IXGBE_ACI_NVM_MAX_OFFSET)
2155*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
2156*dea5f973SBhosale, Yogeshnull 
2157*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_read);
2158*dea5f973SBhosale, Yogeshnull 
2159*dea5f973SBhosale, Yogeshnull 	if (!read_shadow_ram && module_typeid == IXGBE_ACI_NVM_START_POINT)
2160*dea5f973SBhosale, Yogeshnull 		cmd->cmd_flags |= IXGBE_ACI_NVM_FLASH_ONLY;
2161*dea5f973SBhosale, Yogeshnull 
2162*dea5f973SBhosale, Yogeshnull 	/* If this is the last command in a series, set the proper flag. */
2163*dea5f973SBhosale, Yogeshnull 	if (last_command)
2164*dea5f973SBhosale, Yogeshnull 		cmd->cmd_flags |= IXGBE_ACI_NVM_LAST_CMD;
2165*dea5f973SBhosale, Yogeshnull 	cmd->module_typeid = IXGBE_CPU_TO_LE16(module_typeid);
2166*dea5f973SBhosale, Yogeshnull 	cmd->offset_low = IXGBE_CPU_TO_LE16(offset & 0xFFFF);
2167*dea5f973SBhosale, Yogeshnull 	cmd->offset_high = (offset >> 16) & 0xFF;
2168*dea5f973SBhosale, Yogeshnull 	cmd->length = IXGBE_CPU_TO_LE16(length);
2169*dea5f973SBhosale, Yogeshnull 
2170*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, data, length);
2171*dea5f973SBhosale, Yogeshnull }
2172*dea5f973SBhosale, Yogeshnull 
2173*dea5f973SBhosale, Yogeshnull /**
2174*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_erase_nvm - erase NVM sector
2175*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2176*dea5f973SBhosale, Yogeshnull  * @module_typeid: module pointer location in words from the NVM beginning
2177*dea5f973SBhosale, Yogeshnull  *
2178*dea5f973SBhosale, Yogeshnull  * Erase the NVM sector using the ACI command (0x0702).
2179*dea5f973SBhosale, Yogeshnull  *
2180*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2181*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_erase_nvm(struct ixgbe_hw * hw,u16 module_typeid)2182*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_erase_nvm(struct ixgbe_hw *hw, u16 module_typeid)
2183*dea5f973SBhosale, Yogeshnull {
2184*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
2185*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm *cmd;
2186*dea5f973SBhosale, Yogeshnull 	s32 status;
2187*dea5f973SBhosale, Yogeshnull 	__le16 len;
2188*dea5f973SBhosale, Yogeshnull 
2189*dea5f973SBhosale, Yogeshnull 	/* read a length value from SR, so module_typeid is equal to 0 */
2190*dea5f973SBhosale, Yogeshnull 	/* calculate offset where module size is placed from bytes to words */
2191*dea5f973SBhosale, Yogeshnull 	/* set last command and read from SR values to true */
2192*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_read_nvm(hw, 0, 2 * module_typeid + 2, 2, &len, true,
2193*dea5f973SBhosale, Yogeshnull 				 true);
2194*dea5f973SBhosale, Yogeshnull 	if (status)
2195*dea5f973SBhosale, Yogeshnull 		return status;
2196*dea5f973SBhosale, Yogeshnull 
2197*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.nvm;
2198*dea5f973SBhosale, Yogeshnull 
2199*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_erase);
2200*dea5f973SBhosale, Yogeshnull 
2201*dea5f973SBhosale, Yogeshnull 	cmd->module_typeid = IXGBE_CPU_TO_LE16(module_typeid);
2202*dea5f973SBhosale, Yogeshnull 	cmd->length = len;
2203*dea5f973SBhosale, Yogeshnull 	cmd->offset_low = 0;
2204*dea5f973SBhosale, Yogeshnull 	cmd->offset_high = 0;
2205*dea5f973SBhosale, Yogeshnull 
2206*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
2207*dea5f973SBhosale, Yogeshnull }
2208*dea5f973SBhosale, Yogeshnull 
2209*dea5f973SBhosale, Yogeshnull /**
2210*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_update_nvm - update NVM
2211*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2212*dea5f973SBhosale, Yogeshnull  * @module_typeid: module pointer location in words from the NVM beginning
2213*dea5f973SBhosale, Yogeshnull  * @offset: byte offset from the module beginning
2214*dea5f973SBhosale, Yogeshnull  * @length: length of the section to be written (in bytes from the offset)
2215*dea5f973SBhosale, Yogeshnull  * @data: command buffer (size [bytes] = length)
2216*dea5f973SBhosale, Yogeshnull  * @last_command: tells if this is the last command in a series
2217*dea5f973SBhosale, Yogeshnull  * @command_flags: command parameters
2218*dea5f973SBhosale, Yogeshnull  *
2219*dea5f973SBhosale, Yogeshnull  * Update the NVM using the ACI command (0x0703).
2220*dea5f973SBhosale, Yogeshnull  *
2221*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2222*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_update_nvm(struct ixgbe_hw * hw,u16 module_typeid,u32 offset,u16 length,void * data,bool last_command,u8 command_flags)2223*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_update_nvm(struct ixgbe_hw *hw, u16 module_typeid,
2224*dea5f973SBhosale, Yogeshnull 			 u32 offset, u16 length, void *data,
2225*dea5f973SBhosale, Yogeshnull 			 bool last_command, u8 command_flags)
2226*dea5f973SBhosale, Yogeshnull {
2227*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
2228*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm *cmd;
2229*dea5f973SBhosale, Yogeshnull 
2230*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.nvm;
2231*dea5f973SBhosale, Yogeshnull 
2232*dea5f973SBhosale, Yogeshnull 	/* In offset the highest byte must be zeroed. */
2233*dea5f973SBhosale, Yogeshnull 	if (offset & 0xFF000000)
2234*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
2235*dea5f973SBhosale, Yogeshnull 
2236*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_write);
2237*dea5f973SBhosale, Yogeshnull 
2238*dea5f973SBhosale, Yogeshnull 	cmd->cmd_flags |= command_flags;
2239*dea5f973SBhosale, Yogeshnull 
2240*dea5f973SBhosale, Yogeshnull 	/* If this is the last command in a series, set the proper flag. */
2241*dea5f973SBhosale, Yogeshnull 	if (last_command)
2242*dea5f973SBhosale, Yogeshnull 		cmd->cmd_flags |= IXGBE_ACI_NVM_LAST_CMD;
2243*dea5f973SBhosale, Yogeshnull 	cmd->module_typeid = IXGBE_CPU_TO_LE16(module_typeid);
2244*dea5f973SBhosale, Yogeshnull 	cmd->offset_low = IXGBE_CPU_TO_LE16(offset & 0xFFFF);
2245*dea5f973SBhosale, Yogeshnull 	cmd->offset_high = (offset >> 16) & 0xFF;
2246*dea5f973SBhosale, Yogeshnull 	cmd->length = IXGBE_CPU_TO_LE16(length);
2247*dea5f973SBhosale, Yogeshnull 
2248*dea5f973SBhosale, Yogeshnull 	desc.flags |= IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_RD);
2249*dea5f973SBhosale, Yogeshnull 
2250*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, data, length);
2251*dea5f973SBhosale, Yogeshnull }
2252*dea5f973SBhosale, Yogeshnull 
2253*dea5f973SBhosale, Yogeshnull /**
2254*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_read_nvm_cfg - read an NVM config block
2255*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2256*dea5f973SBhosale, Yogeshnull  * @cmd_flags: NVM access admin command bits
2257*dea5f973SBhosale, Yogeshnull  * @field_id: field or feature ID
2258*dea5f973SBhosale, Yogeshnull  * @data: buffer for result
2259*dea5f973SBhosale, Yogeshnull  * @buf_size: buffer size
2260*dea5f973SBhosale, Yogeshnull  * @elem_count: pointer to count of elements read by FW
2261*dea5f973SBhosale, Yogeshnull  *
2262*dea5f973SBhosale, Yogeshnull  * Reads a single or multiple feature/field ID and data using ACI command
2263*dea5f973SBhosale, Yogeshnull  * (0x0704).
2264*dea5f973SBhosale, Yogeshnull  *
2265*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2266*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_read_nvm_cfg(struct ixgbe_hw * hw,u8 cmd_flags,u16 field_id,void * data,u16 buf_size,u16 * elem_count)2267*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_read_nvm_cfg(struct ixgbe_hw *hw, u8 cmd_flags,
2268*dea5f973SBhosale, Yogeshnull 			   u16 field_id, void *data, u16 buf_size,
2269*dea5f973SBhosale, Yogeshnull 			   u16 *elem_count)
2270*dea5f973SBhosale, Yogeshnull {
2271*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm_cfg *cmd;
2272*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
2273*dea5f973SBhosale, Yogeshnull 	s32 status;
2274*dea5f973SBhosale, Yogeshnull 
2275*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.nvm_cfg;
2276*dea5f973SBhosale, Yogeshnull 
2277*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_cfg_read);
2278*dea5f973SBhosale, Yogeshnull 
2279*dea5f973SBhosale, Yogeshnull 	cmd->cmd_flags = cmd_flags;
2280*dea5f973SBhosale, Yogeshnull 	cmd->id = IXGBE_CPU_TO_LE16(field_id);
2281*dea5f973SBhosale, Yogeshnull 
2282*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, data, buf_size);
2283*dea5f973SBhosale, Yogeshnull 	if (!status && elem_count)
2284*dea5f973SBhosale, Yogeshnull 		*elem_count = IXGBE_LE16_TO_CPU(cmd->count);
2285*dea5f973SBhosale, Yogeshnull 
2286*dea5f973SBhosale, Yogeshnull 	return status;
2287*dea5f973SBhosale, Yogeshnull }
2288*dea5f973SBhosale, Yogeshnull 
2289*dea5f973SBhosale, Yogeshnull /**
2290*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_write_nvm_cfg - write an NVM config block
2291*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2292*dea5f973SBhosale, Yogeshnull  * @cmd_flags: NVM access admin command bits
2293*dea5f973SBhosale, Yogeshnull  * @data: buffer for result
2294*dea5f973SBhosale, Yogeshnull  * @buf_size: buffer size
2295*dea5f973SBhosale, Yogeshnull  * @elem_count: count of elements to be written
2296*dea5f973SBhosale, Yogeshnull  *
2297*dea5f973SBhosale, Yogeshnull  * Writes a single or multiple feature/field ID and data using ACI command
2298*dea5f973SBhosale, Yogeshnull  * (0x0705).
2299*dea5f973SBhosale, Yogeshnull  *
2300*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2301*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_write_nvm_cfg(struct ixgbe_hw * hw,u8 cmd_flags,void * data,u16 buf_size,u16 elem_count)2302*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_write_nvm_cfg(struct ixgbe_hw *hw, u8 cmd_flags,
2303*dea5f973SBhosale, Yogeshnull 			    void *data, u16 buf_size, u16 elem_count)
2304*dea5f973SBhosale, Yogeshnull {
2305*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm_cfg *cmd;
2306*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
2307*dea5f973SBhosale, Yogeshnull 
2308*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.nvm_cfg;
2309*dea5f973SBhosale, Yogeshnull 
2310*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_cfg_write);
2311*dea5f973SBhosale, Yogeshnull 	desc.flags |= IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_RD);
2312*dea5f973SBhosale, Yogeshnull 
2313*dea5f973SBhosale, Yogeshnull 	cmd->count = IXGBE_CPU_TO_LE16(elem_count);
2314*dea5f973SBhosale, Yogeshnull 	cmd->cmd_flags = cmd_flags;
2315*dea5f973SBhosale, Yogeshnull 
2316*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, data, buf_size);
2317*dea5f973SBhosale, Yogeshnull }
2318*dea5f973SBhosale, Yogeshnull 
2319*dea5f973SBhosale, Yogeshnull /**
2320*dea5f973SBhosale, Yogeshnull  * ixgbe_nvm_validate_checksum - validate checksum
2321*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2322*dea5f973SBhosale, Yogeshnull  *
2323*dea5f973SBhosale, Yogeshnull  * Verify NVM PFA checksum validity using ACI command (0x0706).
2324*dea5f973SBhosale, Yogeshnull  * If the checksum verification failed, IXGBE_ERR_NVM_CHECKSUM is returned.
2325*dea5f973SBhosale, Yogeshnull  * The function acquires and then releases the NVM ownership.
2326*dea5f973SBhosale, Yogeshnull  *
2327*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2328*dea5f973SBhosale, Yogeshnull  */
ixgbe_nvm_validate_checksum(struct ixgbe_hw * hw)2329*dea5f973SBhosale, Yogeshnull s32 ixgbe_nvm_validate_checksum(struct ixgbe_hw *hw)
2330*dea5f973SBhosale, Yogeshnull {
2331*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm_checksum *cmd;
2332*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
2333*dea5f973SBhosale, Yogeshnull 	s32 status;
2334*dea5f973SBhosale, Yogeshnull 
2335*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
2336*dea5f973SBhosale, Yogeshnull 	if (status)
2337*dea5f973SBhosale, Yogeshnull 		return status;
2338*dea5f973SBhosale, Yogeshnull 
2339*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.nvm_checksum;
2340*dea5f973SBhosale, Yogeshnull 
2341*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_checksum);
2342*dea5f973SBhosale, Yogeshnull 	cmd->flags = IXGBE_ACI_NVM_CHECKSUM_VERIFY;
2343*dea5f973SBhosale, Yogeshnull 
2344*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
2345*dea5f973SBhosale, Yogeshnull 
2346*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
2347*dea5f973SBhosale, Yogeshnull 
2348*dea5f973SBhosale, Yogeshnull 	if (!status)
2349*dea5f973SBhosale, Yogeshnull 		if (IXGBE_LE16_TO_CPU(cmd->checksum) !=
2350*dea5f973SBhosale, Yogeshnull 		    IXGBE_ACI_NVM_CHECKSUM_CORRECT) {
2351*dea5f973SBhosale, Yogeshnull 			ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
2352*dea5f973SBhosale, Yogeshnull 				      "Invalid Shadow Ram checksum");
2353*dea5f973SBhosale, Yogeshnull 			status = IXGBE_ERR_NVM_CHECKSUM;
2354*dea5f973SBhosale, Yogeshnull 		}
2355*dea5f973SBhosale, Yogeshnull 
2356*dea5f973SBhosale, Yogeshnull 	return status;
2357*dea5f973SBhosale, Yogeshnull }
2358*dea5f973SBhosale, Yogeshnull 
2359*dea5f973SBhosale, Yogeshnull /**
2360*dea5f973SBhosale, Yogeshnull  * ixgbe_nvm_recalculate_checksum - recalculate checksum
2361*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2362*dea5f973SBhosale, Yogeshnull  *
2363*dea5f973SBhosale, Yogeshnull  * Recalculate NVM PFA checksum using ACI command (0x0706).
2364*dea5f973SBhosale, Yogeshnull  * The function acquires and then releases the NVM ownership.
2365*dea5f973SBhosale, Yogeshnull  *
2366*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2367*dea5f973SBhosale, Yogeshnull  */
ixgbe_nvm_recalculate_checksum(struct ixgbe_hw * hw)2368*dea5f973SBhosale, Yogeshnull s32 ixgbe_nvm_recalculate_checksum(struct ixgbe_hw *hw)
2369*dea5f973SBhosale, Yogeshnull {
2370*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm_checksum *cmd;
2371*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
2372*dea5f973SBhosale, Yogeshnull 	s32 status;
2373*dea5f973SBhosale, Yogeshnull 
2374*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_WRITE);
2375*dea5f973SBhosale, Yogeshnull 	if (status)
2376*dea5f973SBhosale, Yogeshnull 		return status;
2377*dea5f973SBhosale, Yogeshnull 
2378*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.nvm_checksum;
2379*dea5f973SBhosale, Yogeshnull 
2380*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_checksum);
2381*dea5f973SBhosale, Yogeshnull 	cmd->flags = IXGBE_ACI_NVM_CHECKSUM_RECALC;
2382*dea5f973SBhosale, Yogeshnull 
2383*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
2384*dea5f973SBhosale, Yogeshnull 
2385*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
2386*dea5f973SBhosale, Yogeshnull 
2387*dea5f973SBhosale, Yogeshnull 	return status;
2388*dea5f973SBhosale, Yogeshnull }
2389*dea5f973SBhosale, Yogeshnull 
2390*dea5f973SBhosale, Yogeshnull /**
2391*dea5f973SBhosale, Yogeshnull  * ixgbe_nvm_write_activate - NVM activate write
2392*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2393*dea5f973SBhosale, Yogeshnull  * @cmd_flags: flags for write activate command
2394*dea5f973SBhosale, Yogeshnull  * @response_flags: response indicators from firmware
2395*dea5f973SBhosale, Yogeshnull  *
2396*dea5f973SBhosale, Yogeshnull  * Update the control word with the required banks' validity bits
2397*dea5f973SBhosale, Yogeshnull  * and dumps the Shadow RAM to flash using ACI command (0x0707).
2398*dea5f973SBhosale, Yogeshnull  *
2399*dea5f973SBhosale, Yogeshnull  * cmd_flags controls which banks to activate, the preservation level to use
2400*dea5f973SBhosale, Yogeshnull  * when activating the NVM bank, and whether an EMP reset is required for
2401*dea5f973SBhosale, Yogeshnull  * activation.
2402*dea5f973SBhosale, Yogeshnull  *
2403*dea5f973SBhosale, Yogeshnull  * Note that the 16bit cmd_flags value is split between two separate 1 byte
2404*dea5f973SBhosale, Yogeshnull  * flag values in the descriptor.
2405*dea5f973SBhosale, Yogeshnull  *
2406*dea5f973SBhosale, Yogeshnull  * On successful return of the firmware command, the response_flags variable
2407*dea5f973SBhosale, Yogeshnull  * is updated with the flags reported by firmware indicating certain status,
2408*dea5f973SBhosale, Yogeshnull  * such as whether EMP reset is enabled.
2409*dea5f973SBhosale, Yogeshnull  *
2410*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2411*dea5f973SBhosale, Yogeshnull  */
ixgbe_nvm_write_activate(struct ixgbe_hw * hw,u16 cmd_flags,u8 * response_flags)2412*dea5f973SBhosale, Yogeshnull s32 ixgbe_nvm_write_activate(struct ixgbe_hw *hw, u16 cmd_flags,
2413*dea5f973SBhosale, Yogeshnull 			     u8 *response_flags)
2414*dea5f973SBhosale, Yogeshnull {
2415*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
2416*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm *cmd;
2417*dea5f973SBhosale, Yogeshnull 	s32 status;
2418*dea5f973SBhosale, Yogeshnull 
2419*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.nvm;
2420*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc,
2421*dea5f973SBhosale, Yogeshnull 					ixgbe_aci_opc_nvm_write_activate);
2422*dea5f973SBhosale, Yogeshnull 
2423*dea5f973SBhosale, Yogeshnull 	cmd->cmd_flags = LO_BYTE(cmd_flags);
2424*dea5f973SBhosale, Yogeshnull 	cmd->offset_high = HI_BYTE(cmd_flags);
2425*dea5f973SBhosale, Yogeshnull 
2426*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
2427*dea5f973SBhosale, Yogeshnull 	if (!status && response_flags)
2428*dea5f973SBhosale, Yogeshnull 		*response_flags = cmd->cmd_flags;
2429*dea5f973SBhosale, Yogeshnull 
2430*dea5f973SBhosale, Yogeshnull 	return status;
2431*dea5f973SBhosale, Yogeshnull }
2432*dea5f973SBhosale, Yogeshnull 
2433*dea5f973SBhosale, Yogeshnull /**
2434*dea5f973SBhosale, Yogeshnull  * ixgbe_get_flash_bank_offset - Get offset into requested flash bank
2435*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
2436*dea5f973SBhosale, Yogeshnull  * @bank: whether to read from the active or inactive flash bank
2437*dea5f973SBhosale, Yogeshnull  * @module: the module to read from
2438*dea5f973SBhosale, Yogeshnull  *
2439*dea5f973SBhosale, Yogeshnull  * Based on the module, lookup the module offset from the beginning of the
2440*dea5f973SBhosale, Yogeshnull  * flash.
2441*dea5f973SBhosale, Yogeshnull  *
2442*dea5f973SBhosale, Yogeshnull  * Return: the flash offset. Note that a value of zero is invalid and must be
2443*dea5f973SBhosale, Yogeshnull  * treated as an error.
2444*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_flash_bank_offset(struct ixgbe_hw * hw,enum ixgbe_bank_select bank,u16 module)2445*dea5f973SBhosale, Yogeshnull static u32 ixgbe_get_flash_bank_offset(struct ixgbe_hw *hw,
2446*dea5f973SBhosale, Yogeshnull 				       enum ixgbe_bank_select bank,
2447*dea5f973SBhosale, Yogeshnull 				       u16 module)
2448*dea5f973SBhosale, Yogeshnull {
2449*dea5f973SBhosale, Yogeshnull 	struct ixgbe_bank_info *banks = &hw->flash.banks;
2450*dea5f973SBhosale, Yogeshnull 	enum ixgbe_flash_bank active_bank;
2451*dea5f973SBhosale, Yogeshnull 	bool second_bank_active;
2452*dea5f973SBhosale, Yogeshnull 	u32 offset, size;
2453*dea5f973SBhosale, Yogeshnull 
2454*dea5f973SBhosale, Yogeshnull 	switch (module) {
2455*dea5f973SBhosale, Yogeshnull 	case E610_SR_1ST_NVM_BANK_PTR:
2456*dea5f973SBhosale, Yogeshnull 		offset = banks->nvm_ptr;
2457*dea5f973SBhosale, Yogeshnull 		size = banks->nvm_size;
2458*dea5f973SBhosale, Yogeshnull 		active_bank = banks->nvm_bank;
2459*dea5f973SBhosale, Yogeshnull 		break;
2460*dea5f973SBhosale, Yogeshnull 	case E610_SR_1ST_OROM_BANK_PTR:
2461*dea5f973SBhosale, Yogeshnull 		offset = banks->orom_ptr;
2462*dea5f973SBhosale, Yogeshnull 		size = banks->orom_size;
2463*dea5f973SBhosale, Yogeshnull 		active_bank = banks->orom_bank;
2464*dea5f973SBhosale, Yogeshnull 		break;
2465*dea5f973SBhosale, Yogeshnull 	case E610_SR_NETLIST_BANK_PTR:
2466*dea5f973SBhosale, Yogeshnull 		offset = banks->netlist_ptr;
2467*dea5f973SBhosale, Yogeshnull 		size = banks->netlist_size;
2468*dea5f973SBhosale, Yogeshnull 		active_bank = banks->netlist_bank;
2469*dea5f973SBhosale, Yogeshnull 		break;
2470*dea5f973SBhosale, Yogeshnull 	default:
2471*dea5f973SBhosale, Yogeshnull 		return 0;
2472*dea5f973SBhosale, Yogeshnull 	}
2473*dea5f973SBhosale, Yogeshnull 
2474*dea5f973SBhosale, Yogeshnull 	switch (active_bank) {
2475*dea5f973SBhosale, Yogeshnull 	case IXGBE_1ST_FLASH_BANK:
2476*dea5f973SBhosale, Yogeshnull 		second_bank_active = false;
2477*dea5f973SBhosale, Yogeshnull 		break;
2478*dea5f973SBhosale, Yogeshnull 	case IXGBE_2ND_FLASH_BANK:
2479*dea5f973SBhosale, Yogeshnull 		second_bank_active = true;
2480*dea5f973SBhosale, Yogeshnull 		break;
2481*dea5f973SBhosale, Yogeshnull 	default:
2482*dea5f973SBhosale, Yogeshnull 		return 0;
2483*dea5f973SBhosale, Yogeshnull     }
2484*dea5f973SBhosale, Yogeshnull 
2485*dea5f973SBhosale, Yogeshnull 	/* The second flash bank is stored immediately following the first
2486*dea5f973SBhosale, Yogeshnull 	 * bank. Based on whether the 1st or 2nd bank is active, and whether
2487*dea5f973SBhosale, Yogeshnull 	 * we want the active or inactive bank, calculate the desired offset.
2488*dea5f973SBhosale, Yogeshnull 	 */
2489*dea5f973SBhosale, Yogeshnull 	switch (bank) {
2490*dea5f973SBhosale, Yogeshnull 	case IXGBE_ACTIVE_FLASH_BANK:
2491*dea5f973SBhosale, Yogeshnull 		return offset + (second_bank_active ? size : 0);
2492*dea5f973SBhosale, Yogeshnull 	case IXGBE_INACTIVE_FLASH_BANK:
2493*dea5f973SBhosale, Yogeshnull 		return offset + (second_bank_active ? 0 : size);
2494*dea5f973SBhosale, Yogeshnull 	}
2495*dea5f973SBhosale, Yogeshnull 
2496*dea5f973SBhosale, Yogeshnull 	return 0;
2497*dea5f973SBhosale, Yogeshnull }
2498*dea5f973SBhosale, Yogeshnull 
2499*dea5f973SBhosale, Yogeshnull /**
2500*dea5f973SBhosale, Yogeshnull  * ixgbe_read_flash_module - Read a word from one of the main NVM modules
2501*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
2502*dea5f973SBhosale, Yogeshnull  * @bank: which bank of the module to read
2503*dea5f973SBhosale, Yogeshnull  * @module: the module to read
2504*dea5f973SBhosale, Yogeshnull  * @offset: the offset into the module in bytes
2505*dea5f973SBhosale, Yogeshnull  * @data: storage for the word read from the flash
2506*dea5f973SBhosale, Yogeshnull  * @length: bytes of data to read
2507*dea5f973SBhosale, Yogeshnull  *
2508*dea5f973SBhosale, Yogeshnull  * Read data from the specified flash module. The bank parameter indicates
2509*dea5f973SBhosale, Yogeshnull  * whether or not to read from the active bank or the inactive bank of that
2510*dea5f973SBhosale, Yogeshnull  * module.
2511*dea5f973SBhosale, Yogeshnull  *
2512*dea5f973SBhosale, Yogeshnull  * The word will be read using flat NVM access, and relies on the
2513*dea5f973SBhosale, Yogeshnull  * hw->flash.banks data being setup by ixgbe_determine_active_flash_banks()
2514*dea5f973SBhosale, Yogeshnull  * during initialization.
2515*dea5f973SBhosale, Yogeshnull  *
2516*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2517*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_flash_module(struct ixgbe_hw * hw,enum ixgbe_bank_select bank,u16 module,u32 offset,u8 * data,u32 length)2518*dea5f973SBhosale, Yogeshnull static s32 ixgbe_read_flash_module(struct ixgbe_hw *hw,
2519*dea5f973SBhosale, Yogeshnull 				   enum ixgbe_bank_select bank,
2520*dea5f973SBhosale, Yogeshnull 				   u16 module, u32 offset, u8 *data, u32 length)
2521*dea5f973SBhosale, Yogeshnull {
2522*dea5f973SBhosale, Yogeshnull 	s32 status;
2523*dea5f973SBhosale, Yogeshnull 	u32 start;
2524*dea5f973SBhosale, Yogeshnull 
2525*dea5f973SBhosale, Yogeshnull 	start = ixgbe_get_flash_bank_offset(hw, bank, module);
2526*dea5f973SBhosale, Yogeshnull 	if (!start) {
2527*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
2528*dea5f973SBhosale, Yogeshnull 	}
2529*dea5f973SBhosale, Yogeshnull 
2530*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
2531*dea5f973SBhosale, Yogeshnull 	if (status)
2532*dea5f973SBhosale, Yogeshnull 		return status;
2533*dea5f973SBhosale, Yogeshnull 
2534*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_flat_nvm(hw, start + offset, &length, data, false);
2535*dea5f973SBhosale, Yogeshnull 
2536*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
2537*dea5f973SBhosale, Yogeshnull 
2538*dea5f973SBhosale, Yogeshnull 	return status;
2539*dea5f973SBhosale, Yogeshnull }
2540*dea5f973SBhosale, Yogeshnull 
2541*dea5f973SBhosale, Yogeshnull /**
2542*dea5f973SBhosale, Yogeshnull  * ixgbe_read_netlist_module - Read data from the netlist module area
2543*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
2544*dea5f973SBhosale, Yogeshnull  * @bank: whether to read from the active or inactive module
2545*dea5f973SBhosale, Yogeshnull  * @offset: offset into the netlist to read from
2546*dea5f973SBhosale, Yogeshnull  * @data: storage for returned word value
2547*dea5f973SBhosale, Yogeshnull  *
2548*dea5f973SBhosale, Yogeshnull  * Read a word from the specified netlist bank.
2549*dea5f973SBhosale, Yogeshnull  *
2550*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2551*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_netlist_module(struct ixgbe_hw * hw,enum ixgbe_bank_select bank,u32 offset,u16 * data)2552*dea5f973SBhosale, Yogeshnull static s32 ixgbe_read_netlist_module(struct ixgbe_hw *hw,
2553*dea5f973SBhosale, Yogeshnull 				     enum ixgbe_bank_select bank,
2554*dea5f973SBhosale, Yogeshnull 				     u32 offset, u16 *data)
2555*dea5f973SBhosale, Yogeshnull {
2556*dea5f973SBhosale, Yogeshnull 	__le16 data_local;
2557*dea5f973SBhosale, Yogeshnull 	s32 status;
2558*dea5f973SBhosale, Yogeshnull 
2559*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_flash_module(hw, bank, E610_SR_NETLIST_BANK_PTR,
2560*dea5f973SBhosale, Yogeshnull 					 offset * sizeof(u16),
2561*dea5f973SBhosale, Yogeshnull 					 (u8 *)&data_local,
2562*dea5f973SBhosale, Yogeshnull 					 sizeof(u16));
2563*dea5f973SBhosale, Yogeshnull 	if (!status)
2564*dea5f973SBhosale, Yogeshnull 		*data = IXGBE_LE16_TO_CPU(data_local);
2565*dea5f973SBhosale, Yogeshnull 
2566*dea5f973SBhosale, Yogeshnull 	return status;
2567*dea5f973SBhosale, Yogeshnull }
2568*dea5f973SBhosale, Yogeshnull 
2569*dea5f973SBhosale, Yogeshnull /**
2570*dea5f973SBhosale, Yogeshnull  * ixgbe_read_nvm_module - Read from the active main NVM module
2571*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
2572*dea5f973SBhosale, Yogeshnull  * @bank: whether to read from active or inactive NVM module
2573*dea5f973SBhosale, Yogeshnull  * @offset: offset into the NVM module to read, in words
2574*dea5f973SBhosale, Yogeshnull  * @data: storage for returned word value
2575*dea5f973SBhosale, Yogeshnull  *
2576*dea5f973SBhosale, Yogeshnull  * Read the specified word from the active NVM module. This includes the CSS
2577*dea5f973SBhosale, Yogeshnull  * header at the start of the NVM module.
2578*dea5f973SBhosale, Yogeshnull  *
2579*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2580*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_nvm_module(struct ixgbe_hw * hw,enum ixgbe_bank_select bank,u32 offset,u16 * data)2581*dea5f973SBhosale, Yogeshnull static s32 ixgbe_read_nvm_module(struct ixgbe_hw *hw,
2582*dea5f973SBhosale, Yogeshnull 				 enum ixgbe_bank_select bank,
2583*dea5f973SBhosale, Yogeshnull 				  u32 offset, u16 *data)
2584*dea5f973SBhosale, Yogeshnull {
2585*dea5f973SBhosale, Yogeshnull 	__le16 data_local;
2586*dea5f973SBhosale, Yogeshnull 	s32 status;
2587*dea5f973SBhosale, Yogeshnull 
2588*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_flash_module(hw, bank, E610_SR_1ST_NVM_BANK_PTR,
2589*dea5f973SBhosale, Yogeshnull 					 offset * sizeof(u16),
2590*dea5f973SBhosale, Yogeshnull 					 (u8 *)&data_local,
2591*dea5f973SBhosale, Yogeshnull 					 sizeof(u16));
2592*dea5f973SBhosale, Yogeshnull 	if (!status)
2593*dea5f973SBhosale, Yogeshnull 		*data = IXGBE_LE16_TO_CPU(data_local);
2594*dea5f973SBhosale, Yogeshnull 
2595*dea5f973SBhosale, Yogeshnull 	return status;
2596*dea5f973SBhosale, Yogeshnull }
2597*dea5f973SBhosale, Yogeshnull 
2598*dea5f973SBhosale, Yogeshnull /**
2599*dea5f973SBhosale, Yogeshnull  * ixgbe_get_nvm_css_hdr_len - Read the CSS header length from the
2600*dea5f973SBhosale, Yogeshnull  * NVM CSS header
2601*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2602*dea5f973SBhosale, Yogeshnull  * @bank: whether to read from the active or inactive flash bank
2603*dea5f973SBhosale, Yogeshnull  * @hdr_len: storage for header length in words
2604*dea5f973SBhosale, Yogeshnull  *
2605*dea5f973SBhosale, Yogeshnull  * Read the CSS header length from the NVM CSS header and add the
2606*dea5f973SBhosale, Yogeshnull  * Authentication header size, and then convert to words.
2607*dea5f973SBhosale, Yogeshnull  *
2608*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2609*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_nvm_css_hdr_len(struct ixgbe_hw * hw,enum ixgbe_bank_select bank,u32 * hdr_len)2610*dea5f973SBhosale, Yogeshnull static s32 ixgbe_get_nvm_css_hdr_len(struct ixgbe_hw *hw,
2611*dea5f973SBhosale, Yogeshnull 				     enum ixgbe_bank_select bank,
2612*dea5f973SBhosale, Yogeshnull 				     u32 *hdr_len)
2613*dea5f973SBhosale, Yogeshnull {
2614*dea5f973SBhosale, Yogeshnull 	u16 hdr_len_l, hdr_len_h;
2615*dea5f973SBhosale, Yogeshnull 	u32 hdr_len_dword;
2616*dea5f973SBhosale, Yogeshnull 	s32 status;
2617*dea5f973SBhosale, Yogeshnull 
2618*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_nvm_module(hw, bank, IXGBE_NVM_CSS_HDR_LEN_L,
2619*dea5f973SBhosale, Yogeshnull 				       &hdr_len_l);
2620*dea5f973SBhosale, Yogeshnull 	if (status)
2621*dea5f973SBhosale, Yogeshnull 		return status;
2622*dea5f973SBhosale, Yogeshnull 
2623*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_nvm_module(hw, bank, IXGBE_NVM_CSS_HDR_LEN_H,
2624*dea5f973SBhosale, Yogeshnull 				       &hdr_len_h);
2625*dea5f973SBhosale, Yogeshnull 	if (status)
2626*dea5f973SBhosale, Yogeshnull 		return status;
2627*dea5f973SBhosale, Yogeshnull 
2628*dea5f973SBhosale, Yogeshnull 	/* CSS header length is in DWORD, so convert to words and add
2629*dea5f973SBhosale, Yogeshnull 	 * authentication header size
2630*dea5f973SBhosale, Yogeshnull 	 */
2631*dea5f973SBhosale, Yogeshnull 	hdr_len_dword = hdr_len_h << 16 | hdr_len_l;
2632*dea5f973SBhosale, Yogeshnull 	*hdr_len = (hdr_len_dword * 2) + IXGBE_NVM_AUTH_HEADER_LEN;
2633*dea5f973SBhosale, Yogeshnull 
2634*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
2635*dea5f973SBhosale, Yogeshnull }
2636*dea5f973SBhosale, Yogeshnull 
2637*dea5f973SBhosale, Yogeshnull /**
2638*dea5f973SBhosale, Yogeshnull  * ixgbe_read_nvm_sr_copy - Read a word from the Shadow RAM copy in the NVM bank
2639*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
2640*dea5f973SBhosale, Yogeshnull  * @bank: whether to read from the active or inactive NVM module
2641*dea5f973SBhosale, Yogeshnull  * @offset: offset into the Shadow RAM copy to read, in words
2642*dea5f973SBhosale, Yogeshnull  * @data: storage for returned word value
2643*dea5f973SBhosale, Yogeshnull  *
2644*dea5f973SBhosale, Yogeshnull  * Read the specified word from the copy of the Shadow RAM found in the
2645*dea5f973SBhosale, Yogeshnull  * specified NVM module.
2646*dea5f973SBhosale, Yogeshnull  *
2647*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2648*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_nvm_sr_copy(struct ixgbe_hw * hw,enum ixgbe_bank_select bank,u32 offset,u16 * data)2649*dea5f973SBhosale, Yogeshnull static s32 ixgbe_read_nvm_sr_copy(struct ixgbe_hw *hw,
2650*dea5f973SBhosale, Yogeshnull 				  enum ixgbe_bank_select bank,
2651*dea5f973SBhosale, Yogeshnull 				  u32 offset, u16 *data)
2652*dea5f973SBhosale, Yogeshnull {
2653*dea5f973SBhosale, Yogeshnull 	u32 hdr_len;
2654*dea5f973SBhosale, Yogeshnull 	s32 status;
2655*dea5f973SBhosale, Yogeshnull 
2656*dea5f973SBhosale, Yogeshnull 	status = ixgbe_get_nvm_css_hdr_len(hw, bank, &hdr_len);
2657*dea5f973SBhosale, Yogeshnull 	if (status)
2658*dea5f973SBhosale, Yogeshnull 		return status;
2659*dea5f973SBhosale, Yogeshnull 
2660*dea5f973SBhosale, Yogeshnull 	hdr_len = ROUND_UP(hdr_len, 32);
2661*dea5f973SBhosale, Yogeshnull 
2662*dea5f973SBhosale, Yogeshnull 	return ixgbe_read_nvm_module(hw, bank, hdr_len + offset, data);
2663*dea5f973SBhosale, Yogeshnull }
2664*dea5f973SBhosale, Yogeshnull 
2665*dea5f973SBhosale, Yogeshnull /**
2666*dea5f973SBhosale, Yogeshnull  * ixgbe_get_nvm_minsrevs - Get the minsrevs values from flash
2667*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2668*dea5f973SBhosale, Yogeshnull  * @minsrevs: structure to store NVM and OROM minsrev values
2669*dea5f973SBhosale, Yogeshnull  *
2670*dea5f973SBhosale, Yogeshnull  * Read the Minimum Security Revision TLV and extract
2671*dea5f973SBhosale, Yogeshnull  * the revision values from the flash image
2672*dea5f973SBhosale, Yogeshnull  * into a readable structure for processing.
2673*dea5f973SBhosale, Yogeshnull  *
2674*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2675*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_nvm_minsrevs(struct ixgbe_hw * hw,struct ixgbe_minsrev_info * minsrevs)2676*dea5f973SBhosale, Yogeshnull s32 ixgbe_get_nvm_minsrevs(struct ixgbe_hw *hw,
2677*dea5f973SBhosale, Yogeshnull 			   struct ixgbe_minsrev_info *minsrevs)
2678*dea5f973SBhosale, Yogeshnull {
2679*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm_minsrev data;
2680*dea5f973SBhosale, Yogeshnull 	s32 status;
2681*dea5f973SBhosale, Yogeshnull 	u16 valid;
2682*dea5f973SBhosale, Yogeshnull 
2683*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
2684*dea5f973SBhosale, Yogeshnull 	if (status)
2685*dea5f973SBhosale, Yogeshnull 		return status;
2686*dea5f973SBhosale, Yogeshnull 
2687*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_read_nvm(hw, IXGBE_ACI_NVM_MINSREV_MOD_ID,
2688*dea5f973SBhosale, Yogeshnull 				    0, sizeof(data), &data,
2689*dea5f973SBhosale, Yogeshnull 				    true, false);
2690*dea5f973SBhosale, Yogeshnull 
2691*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
2692*dea5f973SBhosale, Yogeshnull 
2693*dea5f973SBhosale, Yogeshnull 	if (status)
2694*dea5f973SBhosale, Yogeshnull 		return status;
2695*dea5f973SBhosale, Yogeshnull 
2696*dea5f973SBhosale, Yogeshnull 	valid = IXGBE_LE16_TO_CPU(data.validity);
2697*dea5f973SBhosale, Yogeshnull 
2698*dea5f973SBhosale, Yogeshnull 	/* Extract NVM minimum security revision */
2699*dea5f973SBhosale, Yogeshnull 	if (valid & IXGBE_ACI_NVM_MINSREV_NVM_VALID) {
2700*dea5f973SBhosale, Yogeshnull 		u16 minsrev_l = IXGBE_LE16_TO_CPU(data.nvm_minsrev_l);
2701*dea5f973SBhosale, Yogeshnull 		u16 minsrev_h = IXGBE_LE16_TO_CPU(data.nvm_minsrev_h);
2702*dea5f973SBhosale, Yogeshnull 
2703*dea5f973SBhosale, Yogeshnull 		minsrevs->nvm = minsrev_h << 16 | minsrev_l;
2704*dea5f973SBhosale, Yogeshnull 		minsrevs->nvm_valid = true;
2705*dea5f973SBhosale, Yogeshnull 	}
2706*dea5f973SBhosale, Yogeshnull 
2707*dea5f973SBhosale, Yogeshnull 	/* Extract the OROM minimum security revision */
2708*dea5f973SBhosale, Yogeshnull 	if (valid & IXGBE_ACI_NVM_MINSREV_OROM_VALID) {
2709*dea5f973SBhosale, Yogeshnull 		u16 minsrev_l = IXGBE_LE16_TO_CPU(data.orom_minsrev_l);
2710*dea5f973SBhosale, Yogeshnull 		u16 minsrev_h = IXGBE_LE16_TO_CPU(data.orom_minsrev_h);
2711*dea5f973SBhosale, Yogeshnull 
2712*dea5f973SBhosale, Yogeshnull 		minsrevs->orom = minsrev_h << 16 | minsrev_l;
2713*dea5f973SBhosale, Yogeshnull 		minsrevs->orom_valid = true;
2714*dea5f973SBhosale, Yogeshnull 	}
2715*dea5f973SBhosale, Yogeshnull 
2716*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
2717*dea5f973SBhosale, Yogeshnull }
2718*dea5f973SBhosale, Yogeshnull 
2719*dea5f973SBhosale, Yogeshnull /**
2720*dea5f973SBhosale, Yogeshnull  * ixgbe_update_nvm_minsrevs - Update minsrevs TLV data in flash
2721*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2722*dea5f973SBhosale, Yogeshnull  * @minsrevs: minimum security revision information
2723*dea5f973SBhosale, Yogeshnull  *
2724*dea5f973SBhosale, Yogeshnull  * Update the NVM or Option ROM minimum security revision fields in the PFA
2725*dea5f973SBhosale, Yogeshnull  * area of the flash. Reads the minsrevs->nvm_valid and minsrevs->orom_valid
2726*dea5f973SBhosale, Yogeshnull  * fields to determine what update is being requested. If the valid bit is not
2727*dea5f973SBhosale, Yogeshnull  * set for that module, then the associated minsrev will be left as is.
2728*dea5f973SBhosale, Yogeshnull  *
2729*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2730*dea5f973SBhosale, Yogeshnull  */
ixgbe_update_nvm_minsrevs(struct ixgbe_hw * hw,struct ixgbe_minsrev_info * minsrevs)2731*dea5f973SBhosale, Yogeshnull s32 ixgbe_update_nvm_minsrevs(struct ixgbe_hw *hw,
2732*dea5f973SBhosale, Yogeshnull 			      struct ixgbe_minsrev_info *minsrevs)
2733*dea5f973SBhosale, Yogeshnull {
2734*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm_minsrev data;
2735*dea5f973SBhosale, Yogeshnull 	s32 status;
2736*dea5f973SBhosale, Yogeshnull 
2737*dea5f973SBhosale, Yogeshnull 	if (!minsrevs->nvm_valid && !minsrevs->orom_valid) {
2738*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
2739*dea5f973SBhosale, Yogeshnull 	}
2740*dea5f973SBhosale, Yogeshnull 
2741*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_WRITE);
2742*dea5f973SBhosale, Yogeshnull 	if (status)
2743*dea5f973SBhosale, Yogeshnull 		return status;
2744*dea5f973SBhosale, Yogeshnull 
2745*dea5f973SBhosale, Yogeshnull 	/* Get current data */
2746*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_read_nvm(hw, IXGBE_ACI_NVM_MINSREV_MOD_ID, 0,
2747*dea5f973SBhosale, Yogeshnull 				    sizeof(data), &data, true, false);
2748*dea5f973SBhosale, Yogeshnull 	if (status)
2749*dea5f973SBhosale, Yogeshnull 		goto exit_release_res;
2750*dea5f973SBhosale, Yogeshnull 
2751*dea5f973SBhosale, Yogeshnull 	if (minsrevs->nvm_valid) {
2752*dea5f973SBhosale, Yogeshnull 		data.nvm_minsrev_l = IXGBE_CPU_TO_LE16(minsrevs->nvm & 0xFFFF);
2753*dea5f973SBhosale, Yogeshnull 		data.nvm_minsrev_h = IXGBE_CPU_TO_LE16(minsrevs->nvm >> 16);
2754*dea5f973SBhosale, Yogeshnull 		data.validity |=
2755*dea5f973SBhosale, Yogeshnull 			IXGBE_CPU_TO_LE16(IXGBE_ACI_NVM_MINSREV_NVM_VALID);
2756*dea5f973SBhosale, Yogeshnull 	}
2757*dea5f973SBhosale, Yogeshnull 
2758*dea5f973SBhosale, Yogeshnull 	if (minsrevs->orom_valid) {
2759*dea5f973SBhosale, Yogeshnull 		data.orom_minsrev_l = IXGBE_CPU_TO_LE16(minsrevs->orom & 0xFFFF);
2760*dea5f973SBhosale, Yogeshnull 		data.orom_minsrev_h = IXGBE_CPU_TO_LE16(minsrevs->orom >> 16);
2761*dea5f973SBhosale, Yogeshnull 		data.validity |=
2762*dea5f973SBhosale, Yogeshnull 			IXGBE_CPU_TO_LE16(IXGBE_ACI_NVM_MINSREV_OROM_VALID);
2763*dea5f973SBhosale, Yogeshnull 	}
2764*dea5f973SBhosale, Yogeshnull 
2765*dea5f973SBhosale, Yogeshnull 	/* Update flash data */
2766*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_update_nvm(hw, IXGBE_ACI_NVM_MINSREV_MOD_ID, 0,
2767*dea5f973SBhosale, Yogeshnull 				      sizeof(data), &data, false,
2768*dea5f973SBhosale, Yogeshnull 				      IXGBE_ACI_NVM_SPECIAL_UPDATE);
2769*dea5f973SBhosale, Yogeshnull 	if (status)
2770*dea5f973SBhosale, Yogeshnull 		goto exit_release_res;
2771*dea5f973SBhosale, Yogeshnull 
2772*dea5f973SBhosale, Yogeshnull 	/* Dump the Shadow RAM to the flash */
2773*dea5f973SBhosale, Yogeshnull 	status = ixgbe_nvm_write_activate(hw, 0, NULL);
2774*dea5f973SBhosale, Yogeshnull 
2775*dea5f973SBhosale, Yogeshnull exit_release_res:
2776*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
2777*dea5f973SBhosale, Yogeshnull 
2778*dea5f973SBhosale, Yogeshnull 	return status;
2779*dea5f973SBhosale, Yogeshnull }
2780*dea5f973SBhosale, Yogeshnull 
2781*dea5f973SBhosale, Yogeshnull /**
2782*dea5f973SBhosale, Yogeshnull  * ixgbe_get_nvm_srev - Read the security revision from the NVM CSS header
2783*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2784*dea5f973SBhosale, Yogeshnull  * @bank: whether to read from the active or inactive flash bank
2785*dea5f973SBhosale, Yogeshnull  * @srev: storage for security revision
2786*dea5f973SBhosale, Yogeshnull  *
2787*dea5f973SBhosale, Yogeshnull  * Read the security revision out of the CSS header of the active NVM module
2788*dea5f973SBhosale, Yogeshnull  * bank.
2789*dea5f973SBhosale, Yogeshnull  *
2790*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2791*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_nvm_srev(struct ixgbe_hw * hw,enum ixgbe_bank_select bank,u32 * srev)2792*dea5f973SBhosale, Yogeshnull static s32 ixgbe_get_nvm_srev(struct ixgbe_hw *hw,
2793*dea5f973SBhosale, Yogeshnull 			      enum ixgbe_bank_select bank, u32 *srev)
2794*dea5f973SBhosale, Yogeshnull {
2795*dea5f973SBhosale, Yogeshnull 	u16 srev_l, srev_h;
2796*dea5f973SBhosale, Yogeshnull 	s32 status;
2797*dea5f973SBhosale, Yogeshnull 
2798*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_nvm_module(hw, bank, IXGBE_NVM_CSS_SREV_L, &srev_l);
2799*dea5f973SBhosale, Yogeshnull 	if (status)
2800*dea5f973SBhosale, Yogeshnull 		return status;
2801*dea5f973SBhosale, Yogeshnull 
2802*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_nvm_module(hw, bank, IXGBE_NVM_CSS_SREV_H, &srev_h);
2803*dea5f973SBhosale, Yogeshnull 	if (status)
2804*dea5f973SBhosale, Yogeshnull 		return status;
2805*dea5f973SBhosale, Yogeshnull 
2806*dea5f973SBhosale, Yogeshnull 	*srev = srev_h << 16 | srev_l;
2807*dea5f973SBhosale, Yogeshnull 
2808*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
2809*dea5f973SBhosale, Yogeshnull }
2810*dea5f973SBhosale, Yogeshnull 
2811*dea5f973SBhosale, Yogeshnull /**
2812*dea5f973SBhosale, Yogeshnull  * ixgbe_get_nvm_ver_info - Read NVM version information
2813*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2814*dea5f973SBhosale, Yogeshnull  * @bank: whether to read from the active or inactive flash bank
2815*dea5f973SBhosale, Yogeshnull  * @nvm: pointer to NVM info structure
2816*dea5f973SBhosale, Yogeshnull  *
2817*dea5f973SBhosale, Yogeshnull  * Read the NVM EETRACK ID and map version of the main NVM image bank, filling
2818*dea5f973SBhosale, Yogeshnull  * in the nvm info structure.
2819*dea5f973SBhosale, Yogeshnull  *
2820*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2821*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_nvm_ver_info(struct ixgbe_hw * hw,enum ixgbe_bank_select bank,struct ixgbe_nvm_info * nvm)2822*dea5f973SBhosale, Yogeshnull static s32 ixgbe_get_nvm_ver_info(struct ixgbe_hw *hw,
2823*dea5f973SBhosale, Yogeshnull 				  enum ixgbe_bank_select bank,
2824*dea5f973SBhosale, Yogeshnull 				  struct ixgbe_nvm_info *nvm)
2825*dea5f973SBhosale, Yogeshnull {
2826*dea5f973SBhosale, Yogeshnull 	u16 eetrack_lo, eetrack_hi, ver;
2827*dea5f973SBhosale, Yogeshnull 	s32 status;
2828*dea5f973SBhosale, Yogeshnull 
2829*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_nvm_sr_copy(hw, bank,
2830*dea5f973SBhosale, Yogeshnull 					E610_SR_NVM_DEV_STARTER_VER, &ver);
2831*dea5f973SBhosale, Yogeshnull 	if (status) {
2832*dea5f973SBhosale, Yogeshnull 		return status;
2833*dea5f973SBhosale, Yogeshnull 	}
2834*dea5f973SBhosale, Yogeshnull 
2835*dea5f973SBhosale, Yogeshnull 	nvm->major = (ver & E610_NVM_VER_HI_MASK) >> E610_NVM_VER_HI_SHIFT;
2836*dea5f973SBhosale, Yogeshnull 	nvm->minor = (ver & E610_NVM_VER_LO_MASK) >> E610_NVM_VER_LO_SHIFT;
2837*dea5f973SBhosale, Yogeshnull 
2838*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_nvm_sr_copy(hw, bank, E610_SR_NVM_EETRACK_LO,
2839*dea5f973SBhosale, Yogeshnull 					&eetrack_lo);
2840*dea5f973SBhosale, Yogeshnull 	if (status) {
2841*dea5f973SBhosale, Yogeshnull 		return status;
2842*dea5f973SBhosale, Yogeshnull 	}
2843*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_nvm_sr_copy(hw, bank, E610_SR_NVM_EETRACK_HI,
2844*dea5f973SBhosale, Yogeshnull 					&eetrack_hi);
2845*dea5f973SBhosale, Yogeshnull 	if (status) {
2846*dea5f973SBhosale, Yogeshnull 		return status;
2847*dea5f973SBhosale, Yogeshnull 	}
2848*dea5f973SBhosale, Yogeshnull 
2849*dea5f973SBhosale, Yogeshnull 	nvm->eetrack = (eetrack_hi << 16) | eetrack_lo;
2850*dea5f973SBhosale, Yogeshnull 
2851*dea5f973SBhosale, Yogeshnull 	status = ixgbe_get_nvm_srev(hw, bank, &nvm->srev);
2852*dea5f973SBhosale, Yogeshnull 
2853*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
2854*dea5f973SBhosale, Yogeshnull }
2855*dea5f973SBhosale, Yogeshnull 
2856*dea5f973SBhosale, Yogeshnull /**
2857*dea5f973SBhosale, Yogeshnull  * ixgbe_get_inactive_nvm_ver - Read Option ROM version from the inactive bank
2858*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
2859*dea5f973SBhosale, Yogeshnull  * @nvm: storage for Option ROM version information
2860*dea5f973SBhosale, Yogeshnull  *
2861*dea5f973SBhosale, Yogeshnull  * Reads the NVM EETRACK ID, Map version, and security revision of the
2862*dea5f973SBhosale, Yogeshnull  * inactive NVM bank. Used to access version data for a pending update that
2863*dea5f973SBhosale, Yogeshnull  * has not yet been activated.
2864*dea5f973SBhosale, Yogeshnull  *
2865*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2866*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_inactive_nvm_ver(struct ixgbe_hw * hw,struct ixgbe_nvm_info * nvm)2867*dea5f973SBhosale, Yogeshnull s32 ixgbe_get_inactive_nvm_ver(struct ixgbe_hw *hw, struct ixgbe_nvm_info *nvm)
2868*dea5f973SBhosale, Yogeshnull {
2869*dea5f973SBhosale, Yogeshnull 	return ixgbe_get_nvm_ver_info(hw, IXGBE_INACTIVE_FLASH_BANK, nvm);
2870*dea5f973SBhosale, Yogeshnull }
2871*dea5f973SBhosale, Yogeshnull 
2872*dea5f973SBhosale, Yogeshnull /**
2873*dea5f973SBhosale, Yogeshnull  * ixgbe_get_active_nvm_ver - Read Option ROM version from the active bank
2874*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
2875*dea5f973SBhosale, Yogeshnull  * @nvm: storage for Option ROM version information
2876*dea5f973SBhosale, Yogeshnull  *
2877*dea5f973SBhosale, Yogeshnull  * Reads the NVM EETRACK ID, Map version, and security revision of the
2878*dea5f973SBhosale, Yogeshnull  * active NVM bank.
2879*dea5f973SBhosale, Yogeshnull  *
2880*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2881*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_active_nvm_ver(struct ixgbe_hw * hw,struct ixgbe_nvm_info * nvm)2882*dea5f973SBhosale, Yogeshnull s32 ixgbe_get_active_nvm_ver(struct ixgbe_hw *hw, struct ixgbe_nvm_info *nvm)
2883*dea5f973SBhosale, Yogeshnull {
2884*dea5f973SBhosale, Yogeshnull 	return ixgbe_get_nvm_ver_info(hw, IXGBE_ACTIVE_FLASH_BANK, nvm);
2885*dea5f973SBhosale, Yogeshnull }
2886*dea5f973SBhosale, Yogeshnull 
2887*dea5f973SBhosale, Yogeshnull /**
2888*dea5f973SBhosale, Yogeshnull  * ixgbe_get_netlist_info
2889*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2890*dea5f973SBhosale, Yogeshnull  * @bank: whether to read from the active or inactive flash bank
2891*dea5f973SBhosale, Yogeshnull  * @netlist: pointer to netlist version info structure
2892*dea5f973SBhosale, Yogeshnull  *
2893*dea5f973SBhosale, Yogeshnull  * Get the netlist version information from the requested bank. Reads the Link
2894*dea5f973SBhosale, Yogeshnull  * Topology section to find the Netlist ID block and extract the relevant
2895*dea5f973SBhosale, Yogeshnull  * information into the netlist version structure.
2896*dea5f973SBhosale, Yogeshnull  *
2897*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2898*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_netlist_info(struct ixgbe_hw * hw,enum ixgbe_bank_select bank,struct ixgbe_netlist_info * netlist)2899*dea5f973SBhosale, Yogeshnull static s32 ixgbe_get_netlist_info(struct ixgbe_hw *hw,
2900*dea5f973SBhosale, Yogeshnull 				  enum ixgbe_bank_select bank,
2901*dea5f973SBhosale, Yogeshnull 				  struct ixgbe_netlist_info *netlist)
2902*dea5f973SBhosale, Yogeshnull {
2903*dea5f973SBhosale, Yogeshnull 	u16 module_id, length, node_count, i;
2904*dea5f973SBhosale, Yogeshnull 	u16 *id_blk;
2905*dea5f973SBhosale, Yogeshnull 	s32 status;
2906*dea5f973SBhosale, Yogeshnull 
2907*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_netlist_module(hw, bank, IXGBE_NETLIST_TYPE_OFFSET,
2908*dea5f973SBhosale, Yogeshnull 					   &module_id);
2909*dea5f973SBhosale, Yogeshnull 	if (status)
2910*dea5f973SBhosale, Yogeshnull 		return status;
2911*dea5f973SBhosale, Yogeshnull 
2912*dea5f973SBhosale, Yogeshnull 	if (module_id != IXGBE_NETLIST_LINK_TOPO_MOD_ID) {
2913*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_NVM;
2914*dea5f973SBhosale, Yogeshnull 	}
2915*dea5f973SBhosale, Yogeshnull 
2916*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_netlist_module(hw, bank, IXGBE_LINK_TOPO_MODULE_LEN,
2917*dea5f973SBhosale, Yogeshnull 					   &length);
2918*dea5f973SBhosale, Yogeshnull 	if (status)
2919*dea5f973SBhosale, Yogeshnull 		return status;
2920*dea5f973SBhosale, Yogeshnull 
2921*dea5f973SBhosale, Yogeshnull 	/* sanity check that we have at least enough words to store the
2922*dea5f973SBhosale, Yogeshnull 	 * netlist ID block
2923*dea5f973SBhosale, Yogeshnull 	 */
2924*dea5f973SBhosale, Yogeshnull 	if (length < IXGBE_NETLIST_ID_BLK_SIZE) {
2925*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_NVM;
2926*dea5f973SBhosale, Yogeshnull 	}
2927*dea5f973SBhosale, Yogeshnull 
2928*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_netlist_module(hw, bank, IXGBE_LINK_TOPO_NODE_COUNT,
2929*dea5f973SBhosale, Yogeshnull 					   &node_count);
2930*dea5f973SBhosale, Yogeshnull 	if (status)
2931*dea5f973SBhosale, Yogeshnull 		return status;
2932*dea5f973SBhosale, Yogeshnull 	node_count &= IXGBE_LINK_TOPO_NODE_COUNT_M;
2933*dea5f973SBhosale, Yogeshnull 
2934*dea5f973SBhosale, Yogeshnull 	id_blk = (u16 *)ixgbe_calloc(hw, IXGBE_NETLIST_ID_BLK_SIZE,
2935*dea5f973SBhosale, Yogeshnull 		     sizeof(*id_blk));
2936*dea5f973SBhosale, Yogeshnull 	if (!id_blk)
2937*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_NO_SPACE;
2938*dea5f973SBhosale, Yogeshnull 
2939*dea5f973SBhosale, Yogeshnull 	/* Read out the entire Netlist ID Block at once. */
2940*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_flash_module(hw, bank, E610_SR_NETLIST_BANK_PTR,
2941*dea5f973SBhosale, Yogeshnull 				         IXGBE_NETLIST_ID_BLK_OFFSET(node_count) * sizeof(u16),
2942*dea5f973SBhosale, Yogeshnull 				         (u8 *)id_blk,
2943*dea5f973SBhosale, Yogeshnull 					 IXGBE_NETLIST_ID_BLK_SIZE * sizeof(u16));
2944*dea5f973SBhosale, Yogeshnull 	if (status)
2945*dea5f973SBhosale, Yogeshnull 		goto exit_error;
2946*dea5f973SBhosale, Yogeshnull 
2947*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < IXGBE_NETLIST_ID_BLK_SIZE; i++)
2948*dea5f973SBhosale, Yogeshnull 		id_blk[i] = IXGBE_LE16_TO_CPU(((__le16 *)id_blk)[i]);
2949*dea5f973SBhosale, Yogeshnull 
2950*dea5f973SBhosale, Yogeshnull 	netlist->major = id_blk[IXGBE_NETLIST_ID_BLK_MAJOR_VER_HIGH] << 16 |
2951*dea5f973SBhosale, Yogeshnull 			 id_blk[IXGBE_NETLIST_ID_BLK_MAJOR_VER_LOW];
2952*dea5f973SBhosale, Yogeshnull 	netlist->minor = id_blk[IXGBE_NETLIST_ID_BLK_MINOR_VER_HIGH] << 16 |
2953*dea5f973SBhosale, Yogeshnull 			 id_blk[IXGBE_NETLIST_ID_BLK_MINOR_VER_LOW];
2954*dea5f973SBhosale, Yogeshnull 	netlist->type = id_blk[IXGBE_NETLIST_ID_BLK_TYPE_HIGH] << 16 |
2955*dea5f973SBhosale, Yogeshnull 			id_blk[IXGBE_NETLIST_ID_BLK_TYPE_LOW];
2956*dea5f973SBhosale, Yogeshnull 	netlist->rev = id_blk[IXGBE_NETLIST_ID_BLK_REV_HIGH] << 16 |
2957*dea5f973SBhosale, Yogeshnull 		       id_blk[IXGBE_NETLIST_ID_BLK_REV_LOW];
2958*dea5f973SBhosale, Yogeshnull 	netlist->cust_ver = id_blk[IXGBE_NETLIST_ID_BLK_CUST_VER];
2959*dea5f973SBhosale, Yogeshnull 	/* Read the left most 4 bytes of SHA */
2960*dea5f973SBhosale, Yogeshnull 	netlist->hash = id_blk[IXGBE_NETLIST_ID_BLK_SHA_HASH_WORD(15)] << 16 |
2961*dea5f973SBhosale, Yogeshnull 			id_blk[IXGBE_NETLIST_ID_BLK_SHA_HASH_WORD(14)];
2962*dea5f973SBhosale, Yogeshnull 
2963*dea5f973SBhosale, Yogeshnull exit_error:
2964*dea5f973SBhosale, Yogeshnull 	ixgbe_free(hw, id_blk);
2965*dea5f973SBhosale, Yogeshnull 
2966*dea5f973SBhosale, Yogeshnull 	return status;
2967*dea5f973SBhosale, Yogeshnull }
2968*dea5f973SBhosale, Yogeshnull 
2969*dea5f973SBhosale, Yogeshnull /**
2970*dea5f973SBhosale, Yogeshnull  * ixgbe_get_inactive_netlist_ver
2971*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
2972*dea5f973SBhosale, Yogeshnull  * @netlist: pointer to netlist version info structure
2973*dea5f973SBhosale, Yogeshnull  *
2974*dea5f973SBhosale, Yogeshnull  * Read the netlist version data from the inactive netlist bank. Used to
2975*dea5f973SBhosale, Yogeshnull  * extract version data of a pending flash update in order to display the
2976*dea5f973SBhosale, Yogeshnull  * version data.
2977*dea5f973SBhosale, Yogeshnull  *
2978*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
2979*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_inactive_netlist_ver(struct ixgbe_hw * hw,struct ixgbe_netlist_info * netlist)2980*dea5f973SBhosale, Yogeshnull s32 ixgbe_get_inactive_netlist_ver(struct ixgbe_hw *hw,
2981*dea5f973SBhosale, Yogeshnull 				   struct ixgbe_netlist_info *netlist)
2982*dea5f973SBhosale, Yogeshnull {
2983*dea5f973SBhosale, Yogeshnull 	return ixgbe_get_netlist_info(hw, IXGBE_INACTIVE_FLASH_BANK, netlist);
2984*dea5f973SBhosale, Yogeshnull }
2985*dea5f973SBhosale, Yogeshnull 
2986*dea5f973SBhosale, Yogeshnull /**
2987*dea5f973SBhosale, Yogeshnull  * ixgbe_read_sr_pointer - Read the value of a Shadow RAM pointer word
2988*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
2989*dea5f973SBhosale, Yogeshnull  * @offset: the word offset of the Shadow RAM word to read
2990*dea5f973SBhosale, Yogeshnull  * @pointer: pointer value read from Shadow RAM
2991*dea5f973SBhosale, Yogeshnull  *
2992*dea5f973SBhosale, Yogeshnull  * Read the given Shadow RAM word, and convert it to a pointer value specified
2993*dea5f973SBhosale, Yogeshnull  * in bytes. This function assumes the specified offset is a valid pointer
2994*dea5f973SBhosale, Yogeshnull  * word.
2995*dea5f973SBhosale, Yogeshnull  *
2996*dea5f973SBhosale, Yogeshnull  * Each pointer word specifies whether it is stored in word size or 4KB
2997*dea5f973SBhosale, Yogeshnull  * sector size by using the highest bit. The reported pointer value will be in
2998*dea5f973SBhosale, Yogeshnull  * bytes, intended for flat NVM reads.
2999*dea5f973SBhosale, Yogeshnull  *
3000*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3001*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_sr_pointer(struct ixgbe_hw * hw,u16 offset,u32 * pointer)3002*dea5f973SBhosale, Yogeshnull static s32 ixgbe_read_sr_pointer(struct ixgbe_hw *hw, u16 offset, u32 *pointer)
3003*dea5f973SBhosale, Yogeshnull {
3004*dea5f973SBhosale, Yogeshnull 	s32 status;
3005*dea5f973SBhosale, Yogeshnull 	u16 value;
3006*dea5f973SBhosale, Yogeshnull 
3007*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_ee_aci_E610(hw, offset, &value);
3008*dea5f973SBhosale, Yogeshnull 	if (status)
3009*dea5f973SBhosale, Yogeshnull 		return status;
3010*dea5f973SBhosale, Yogeshnull 
3011*dea5f973SBhosale, Yogeshnull 	/* Determine if the pointer is in 4KB or word units */
3012*dea5f973SBhosale, Yogeshnull 	if (value & IXGBE_SR_NVM_PTR_4KB_UNITS)
3013*dea5f973SBhosale, Yogeshnull 		*pointer = (value & ~IXGBE_SR_NVM_PTR_4KB_UNITS) * 4 * 1024;
3014*dea5f973SBhosale, Yogeshnull 	else
3015*dea5f973SBhosale, Yogeshnull 		*pointer = value * 2;
3016*dea5f973SBhosale, Yogeshnull 
3017*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
3018*dea5f973SBhosale, Yogeshnull }
3019*dea5f973SBhosale, Yogeshnull 
3020*dea5f973SBhosale, Yogeshnull /**
3021*dea5f973SBhosale, Yogeshnull  * ixgbe_read_sr_area_size - Read an area size from a Shadow RAM word
3022*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
3023*dea5f973SBhosale, Yogeshnull  * @offset: the word offset of the Shadow RAM to read
3024*dea5f973SBhosale, Yogeshnull  * @size: size value read from the Shadow RAM
3025*dea5f973SBhosale, Yogeshnull  *
3026*dea5f973SBhosale, Yogeshnull  * Read the given Shadow RAM word, and convert it to an area size value
3027*dea5f973SBhosale, Yogeshnull  * specified in bytes. This function assumes the specified offset is a valid
3028*dea5f973SBhosale, Yogeshnull  * area size word.
3029*dea5f973SBhosale, Yogeshnull  *
3030*dea5f973SBhosale, Yogeshnull  * Each area size word is specified in 4KB sector units. This function reports
3031*dea5f973SBhosale, Yogeshnull  * the size in bytes, intended for flat NVM reads.
3032*dea5f973SBhosale, Yogeshnull  *
3033*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3034*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_sr_area_size(struct ixgbe_hw * hw,u16 offset,u32 * size)3035*dea5f973SBhosale, Yogeshnull static s32 ixgbe_read_sr_area_size(struct ixgbe_hw *hw, u16 offset, u32 *size)
3036*dea5f973SBhosale, Yogeshnull {
3037*dea5f973SBhosale, Yogeshnull 	s32 status;
3038*dea5f973SBhosale, Yogeshnull 	u16 value;
3039*dea5f973SBhosale, Yogeshnull 
3040*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_ee_aci_E610(hw, offset, &value);
3041*dea5f973SBhosale, Yogeshnull 	if (status)
3042*dea5f973SBhosale, Yogeshnull 		return status;
3043*dea5f973SBhosale, Yogeshnull 
3044*dea5f973SBhosale, Yogeshnull 	/* Area sizes are always specified in 4KB units */
3045*dea5f973SBhosale, Yogeshnull 	*size = value * 4 * 1024;
3046*dea5f973SBhosale, Yogeshnull 
3047*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
3048*dea5f973SBhosale, Yogeshnull }
3049*dea5f973SBhosale, Yogeshnull 
3050*dea5f973SBhosale, Yogeshnull /**
3051*dea5f973SBhosale, Yogeshnull  * ixgbe_discover_flash_size - Discover the available flash size.
3052*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
3053*dea5f973SBhosale, Yogeshnull  *
3054*dea5f973SBhosale, Yogeshnull  * The device flash could be up to 16MB in size. However, it is possible that
3055*dea5f973SBhosale, Yogeshnull  * the actual size is smaller. Use bisection to determine the accessible size
3056*dea5f973SBhosale, Yogeshnull  * of flash memory.
3057*dea5f973SBhosale, Yogeshnull  *
3058*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3059*dea5f973SBhosale, Yogeshnull  */
ixgbe_discover_flash_size(struct ixgbe_hw * hw)3060*dea5f973SBhosale, Yogeshnull static s32 ixgbe_discover_flash_size(struct ixgbe_hw *hw)
3061*dea5f973SBhosale, Yogeshnull {
3062*dea5f973SBhosale, Yogeshnull 	u32 min_size = 0, max_size = IXGBE_ACI_NVM_MAX_OFFSET + 1;
3063*dea5f973SBhosale, Yogeshnull 	s32 status;
3064*dea5f973SBhosale, Yogeshnull 
3065*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
3066*dea5f973SBhosale, Yogeshnull 	if (status)
3067*dea5f973SBhosale, Yogeshnull 		return status;
3068*dea5f973SBhosale, Yogeshnull 
3069*dea5f973SBhosale, Yogeshnull 	while ((max_size - min_size) > 1) {
3070*dea5f973SBhosale, Yogeshnull 		u32 offset = (max_size + min_size) / 2;
3071*dea5f973SBhosale, Yogeshnull 		u32 len = 1;
3072*dea5f973SBhosale, Yogeshnull 		u8 data;
3073*dea5f973SBhosale, Yogeshnull 
3074*dea5f973SBhosale, Yogeshnull 		status = ixgbe_read_flat_nvm(hw, offset, &len, &data, false);
3075*dea5f973SBhosale, Yogeshnull 		if (status == IXGBE_ERR_ACI_ERROR &&
3076*dea5f973SBhosale, Yogeshnull 		    hw->aci.last_status == IXGBE_ACI_RC_EINVAL) {
3077*dea5f973SBhosale, Yogeshnull 			status = IXGBE_SUCCESS;
3078*dea5f973SBhosale, Yogeshnull 			max_size = offset;
3079*dea5f973SBhosale, Yogeshnull 		} else if (!status) {
3080*dea5f973SBhosale, Yogeshnull 			min_size = offset;
3081*dea5f973SBhosale, Yogeshnull 		} else {
3082*dea5f973SBhosale, Yogeshnull 			/* an unexpected error occurred */
3083*dea5f973SBhosale, Yogeshnull 			goto err_read_flat_nvm;
3084*dea5f973SBhosale, Yogeshnull 		}
3085*dea5f973SBhosale, Yogeshnull 	}
3086*dea5f973SBhosale, Yogeshnull 
3087*dea5f973SBhosale, Yogeshnull 	hw->flash.flash_size = max_size;
3088*dea5f973SBhosale, Yogeshnull 
3089*dea5f973SBhosale, Yogeshnull err_read_flat_nvm:
3090*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
3091*dea5f973SBhosale, Yogeshnull 
3092*dea5f973SBhosale, Yogeshnull 	return status;
3093*dea5f973SBhosale, Yogeshnull }
3094*dea5f973SBhosale, Yogeshnull 
3095*dea5f973SBhosale, Yogeshnull /**
3096*dea5f973SBhosale, Yogeshnull  * ixgbe_determine_active_flash_banks - Discover active bank for each module
3097*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
3098*dea5f973SBhosale, Yogeshnull  *
3099*dea5f973SBhosale, Yogeshnull  * Read the Shadow RAM control word and determine which banks are active for
3100*dea5f973SBhosale, Yogeshnull  * the NVM, OROM, and Netlist modules. Also read and calculate the associated
3101*dea5f973SBhosale, Yogeshnull  * pointer and size. These values are then cached into the ixgbe_flash_info
3102*dea5f973SBhosale, Yogeshnull  * structure for later use in order to calculate the correct offset to read
3103*dea5f973SBhosale, Yogeshnull  * from the active module.
3104*dea5f973SBhosale, Yogeshnull  *
3105*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3106*dea5f973SBhosale, Yogeshnull  */
ixgbe_determine_active_flash_banks(struct ixgbe_hw * hw)3107*dea5f973SBhosale, Yogeshnull static s32 ixgbe_determine_active_flash_banks(struct ixgbe_hw *hw)
3108*dea5f973SBhosale, Yogeshnull {
3109*dea5f973SBhosale, Yogeshnull 	struct ixgbe_bank_info *banks = &hw->flash.banks;
3110*dea5f973SBhosale, Yogeshnull 	u16 ctrl_word;
3111*dea5f973SBhosale, Yogeshnull 	s32 status;
3112*dea5f973SBhosale, Yogeshnull 
3113*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_ee_aci_E610(hw, E610_SR_NVM_CTRL_WORD, &ctrl_word);
3114*dea5f973SBhosale, Yogeshnull 	if (status) {
3115*dea5f973SBhosale, Yogeshnull 		return status;
3116*dea5f973SBhosale, Yogeshnull 	}
3117*dea5f973SBhosale, Yogeshnull 
3118*dea5f973SBhosale, Yogeshnull 	/* Check that the control word indicates validity */
3119*dea5f973SBhosale, Yogeshnull 	if ((ctrl_word & IXGBE_SR_CTRL_WORD_1_M) >> IXGBE_SR_CTRL_WORD_1_S !=
3120*dea5f973SBhosale, Yogeshnull 	    IXGBE_SR_CTRL_WORD_VALID) {
3121*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_CONFIG;
3122*dea5f973SBhosale, Yogeshnull 	}
3123*dea5f973SBhosale, Yogeshnull 
3124*dea5f973SBhosale, Yogeshnull 	if (!(ctrl_word & IXGBE_SR_CTRL_WORD_NVM_BANK))
3125*dea5f973SBhosale, Yogeshnull 		banks->nvm_bank = IXGBE_1ST_FLASH_BANK;
3126*dea5f973SBhosale, Yogeshnull 	else
3127*dea5f973SBhosale, Yogeshnull 		banks->nvm_bank = IXGBE_2ND_FLASH_BANK;
3128*dea5f973SBhosale, Yogeshnull 
3129*dea5f973SBhosale, Yogeshnull 	if (!(ctrl_word & IXGBE_SR_CTRL_WORD_OROM_BANK))
3130*dea5f973SBhosale, Yogeshnull 		banks->orom_bank = IXGBE_1ST_FLASH_BANK;
3131*dea5f973SBhosale, Yogeshnull 	else
3132*dea5f973SBhosale, Yogeshnull 		banks->orom_bank = IXGBE_2ND_FLASH_BANK;
3133*dea5f973SBhosale, Yogeshnull 
3134*dea5f973SBhosale, Yogeshnull 	if (!(ctrl_word & IXGBE_SR_CTRL_WORD_NETLIST_BANK))
3135*dea5f973SBhosale, Yogeshnull 		banks->netlist_bank = IXGBE_1ST_FLASH_BANK;
3136*dea5f973SBhosale, Yogeshnull 	else
3137*dea5f973SBhosale, Yogeshnull 		banks->netlist_bank = IXGBE_2ND_FLASH_BANK;
3138*dea5f973SBhosale, Yogeshnull 
3139*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_sr_pointer(hw, E610_SR_1ST_NVM_BANK_PTR,
3140*dea5f973SBhosale, Yogeshnull 				       &banks->nvm_ptr);
3141*dea5f973SBhosale, Yogeshnull 	if (status) {
3142*dea5f973SBhosale, Yogeshnull 		return status;
3143*dea5f973SBhosale, Yogeshnull 	}
3144*dea5f973SBhosale, Yogeshnull 
3145*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_sr_area_size(hw, E610_SR_NVM_BANK_SIZE,
3146*dea5f973SBhosale, Yogeshnull 					 &banks->nvm_size);
3147*dea5f973SBhosale, Yogeshnull 	if (status) {
3148*dea5f973SBhosale, Yogeshnull 		return status;
3149*dea5f973SBhosale, Yogeshnull 	}
3150*dea5f973SBhosale, Yogeshnull 
3151*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_sr_pointer(hw, E610_SR_1ST_OROM_BANK_PTR,
3152*dea5f973SBhosale, Yogeshnull 				       &banks->orom_ptr);
3153*dea5f973SBhosale, Yogeshnull 	if (status) {
3154*dea5f973SBhosale, Yogeshnull 		return status;
3155*dea5f973SBhosale, Yogeshnull 	}
3156*dea5f973SBhosale, Yogeshnull 
3157*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_sr_area_size(hw, E610_SR_OROM_BANK_SIZE,
3158*dea5f973SBhosale, Yogeshnull 					 &banks->orom_size);
3159*dea5f973SBhosale, Yogeshnull 	if (status) {
3160*dea5f973SBhosale, Yogeshnull 		return status;
3161*dea5f973SBhosale, Yogeshnull 	}
3162*dea5f973SBhosale, Yogeshnull 
3163*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_sr_pointer(hw, E610_SR_NETLIST_BANK_PTR,
3164*dea5f973SBhosale, Yogeshnull 				       &banks->netlist_ptr);
3165*dea5f973SBhosale, Yogeshnull 	if (status) {
3166*dea5f973SBhosale, Yogeshnull 		return status;
3167*dea5f973SBhosale, Yogeshnull 	}
3168*dea5f973SBhosale, Yogeshnull 
3169*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_sr_area_size(hw, E610_SR_NETLIST_BANK_SIZE,
3170*dea5f973SBhosale, Yogeshnull 					 &banks->netlist_size);
3171*dea5f973SBhosale, Yogeshnull 	if (status) {
3172*dea5f973SBhosale, Yogeshnull 		return status;
3173*dea5f973SBhosale, Yogeshnull 	}
3174*dea5f973SBhosale, Yogeshnull 
3175*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
3176*dea5f973SBhosale, Yogeshnull }
3177*dea5f973SBhosale, Yogeshnull 
3178*dea5f973SBhosale, Yogeshnull /**
3179*dea5f973SBhosale, Yogeshnull  * ixgbe_init_nvm - initializes NVM setting
3180*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
3181*dea5f973SBhosale, Yogeshnull  *
3182*dea5f973SBhosale, Yogeshnull  * Read and populate NVM settings such as Shadow RAM size,
3183*dea5f973SBhosale, Yogeshnull  * max_timeout, and blank_nvm_mode
3184*dea5f973SBhosale, Yogeshnull  *
3185*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3186*dea5f973SBhosale, Yogeshnull  */
ixgbe_init_nvm(struct ixgbe_hw * hw)3187*dea5f973SBhosale, Yogeshnull s32 ixgbe_init_nvm(struct ixgbe_hw *hw)
3188*dea5f973SBhosale, Yogeshnull {
3189*dea5f973SBhosale, Yogeshnull 	struct ixgbe_flash_info *flash = &hw->flash;
3190*dea5f973SBhosale, Yogeshnull 	u32 fla, gens_stat, status;
3191*dea5f973SBhosale, Yogeshnull 	u8 sr_size;
3192*dea5f973SBhosale, Yogeshnull 
3193*dea5f973SBhosale, Yogeshnull 	/* The SR size is stored regardless of the NVM programming mode
3194*dea5f973SBhosale, Yogeshnull 	 * as the blank mode may be used in the factory line.
3195*dea5f973SBhosale, Yogeshnull 	 */
3196*dea5f973SBhosale, Yogeshnull 	gens_stat = IXGBE_READ_REG(hw, GLNVM_GENS);
3197*dea5f973SBhosale, Yogeshnull 	sr_size = (gens_stat & GLNVM_GENS_SR_SIZE_M) >> GLNVM_GENS_SR_SIZE_S;
3198*dea5f973SBhosale, Yogeshnull 
3199*dea5f973SBhosale, Yogeshnull 	/* Switching to words (sr_size contains power of 2) */
3200*dea5f973SBhosale, Yogeshnull 	flash->sr_words = BIT(sr_size) * IXGBE_SR_WORDS_IN_1KB;
3201*dea5f973SBhosale, Yogeshnull 
3202*dea5f973SBhosale, Yogeshnull 	/* Check if we are in the normal or blank NVM programming mode */
3203*dea5f973SBhosale, Yogeshnull 	fla = IXGBE_READ_REG(hw, GLNVM_FLA);
3204*dea5f973SBhosale, Yogeshnull 	if (fla & GLNVM_FLA_LOCKED_M) { /* Normal programming mode */
3205*dea5f973SBhosale, Yogeshnull 		flash->blank_nvm_mode = false;
3206*dea5f973SBhosale, Yogeshnull 	} else {
3207*dea5f973SBhosale, Yogeshnull 		/* Blank programming mode */
3208*dea5f973SBhosale, Yogeshnull 		flash->blank_nvm_mode = true;
3209*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_NVM_BLANK_MODE;
3210*dea5f973SBhosale, Yogeshnull 	}
3211*dea5f973SBhosale, Yogeshnull 
3212*dea5f973SBhosale, Yogeshnull 	status = ixgbe_discover_flash_size(hw);
3213*dea5f973SBhosale, Yogeshnull 	if (status) {
3214*dea5f973SBhosale, Yogeshnull 		return status;
3215*dea5f973SBhosale, Yogeshnull 	}
3216*dea5f973SBhosale, Yogeshnull 
3217*dea5f973SBhosale, Yogeshnull 	status = ixgbe_determine_active_flash_banks(hw);
3218*dea5f973SBhosale, Yogeshnull 	if (status) {
3219*dea5f973SBhosale, Yogeshnull 		return status;
3220*dea5f973SBhosale, Yogeshnull 	}
3221*dea5f973SBhosale, Yogeshnull 
3222*dea5f973SBhosale, Yogeshnull 	status = ixgbe_get_nvm_ver_info(hw, IXGBE_ACTIVE_FLASH_BANK,
3223*dea5f973SBhosale, Yogeshnull 					&flash->nvm);
3224*dea5f973SBhosale, Yogeshnull 	if (status) {
3225*dea5f973SBhosale, Yogeshnull 		return status;
3226*dea5f973SBhosale, Yogeshnull 	}
3227*dea5f973SBhosale, Yogeshnull 
3228*dea5f973SBhosale, Yogeshnull 	/* read the netlist version information */
3229*dea5f973SBhosale, Yogeshnull 	status = ixgbe_get_netlist_info(hw, IXGBE_ACTIVE_FLASH_BANK,
3230*dea5f973SBhosale, Yogeshnull 					&flash->netlist);
3231*dea5f973SBhosale, Yogeshnull 
3232*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
3233*dea5f973SBhosale, Yogeshnull }
3234*dea5f973SBhosale, Yogeshnull 
3235*dea5f973SBhosale, Yogeshnull /**
3236*dea5f973SBhosale, Yogeshnull  * ixgbe_sanitize_operate - Clear the user data
3237*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
3238*dea5f973SBhosale, Yogeshnull  *
3239*dea5f973SBhosale, Yogeshnull  * Clear user data from NVM using ACI command (0x070C).
3240*dea5f973SBhosale, Yogeshnull  *
3241*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3242*dea5f973SBhosale, Yogeshnull  */
ixgbe_sanitize_operate(struct ixgbe_hw * hw)3243*dea5f973SBhosale, Yogeshnull s32 ixgbe_sanitize_operate(struct ixgbe_hw *hw)
3244*dea5f973SBhosale, Yogeshnull {
3245*dea5f973SBhosale, Yogeshnull 	s32 status;
3246*dea5f973SBhosale, Yogeshnull 	u8 values;
3247*dea5f973SBhosale, Yogeshnull 
3248*dea5f973SBhosale, Yogeshnull 	u8 cmd_flags = IXGBE_ACI_SANITIZE_REQ_OPERATE |
3249*dea5f973SBhosale, Yogeshnull 		       IXGBE_ACI_SANITIZE_OPERATE_SUBJECT_CLEAR;
3250*dea5f973SBhosale, Yogeshnull 
3251*dea5f973SBhosale, Yogeshnull 	status = ixgbe_sanitize_nvm(hw, cmd_flags, &values);
3252*dea5f973SBhosale, Yogeshnull 	if (status)
3253*dea5f973SBhosale, Yogeshnull 		return status;
3254*dea5f973SBhosale, Yogeshnull 	if ((!(values & IXGBE_ACI_SANITIZE_OPERATE_HOST_CLEAN_DONE) &&
3255*dea5f973SBhosale, Yogeshnull 	     !(values & IXGBE_ACI_SANITIZE_OPERATE_BMC_CLEAN_DONE)) ||
3256*dea5f973SBhosale, Yogeshnull 	    ((values & IXGBE_ACI_SANITIZE_OPERATE_HOST_CLEAN_DONE) &&
3257*dea5f973SBhosale, Yogeshnull 	     !(values & IXGBE_ACI_SANITIZE_OPERATE_HOST_CLEAN_SUCCESS)) ||
3258*dea5f973SBhosale, Yogeshnull 	    ((values & IXGBE_ACI_SANITIZE_OPERATE_BMC_CLEAN_DONE) &&
3259*dea5f973SBhosale, Yogeshnull 	     !(values & IXGBE_ACI_SANITIZE_OPERATE_BMC_CLEAN_SUCCESS)))
3260*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_ACI_ERROR;
3261*dea5f973SBhosale, Yogeshnull 
3262*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
3263*dea5f973SBhosale, Yogeshnull }
3264*dea5f973SBhosale, Yogeshnull 
3265*dea5f973SBhosale, Yogeshnull /**
3266*dea5f973SBhosale, Yogeshnull  * ixgbe_sanitize_nvm - Sanitize NVM
3267*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
3268*dea5f973SBhosale, Yogeshnull  * @cmd_flags: flag to the ACI command
3269*dea5f973SBhosale, Yogeshnull  * @values: values returned from the command
3270*dea5f973SBhosale, Yogeshnull  *
3271*dea5f973SBhosale, Yogeshnull  * Sanitize NVM using ACI command (0x070C).
3272*dea5f973SBhosale, Yogeshnull  *
3273*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3274*dea5f973SBhosale, Yogeshnull  */
ixgbe_sanitize_nvm(struct ixgbe_hw * hw,u8 cmd_flags,u8 * values)3275*dea5f973SBhosale, Yogeshnull s32 ixgbe_sanitize_nvm(struct ixgbe_hw *hw, u8 cmd_flags, u8 *values)
3276*dea5f973SBhosale, Yogeshnull {
3277*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
3278*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_nvm_sanitization *cmd;
3279*dea5f973SBhosale, Yogeshnull 	s32 status;
3280*dea5f973SBhosale, Yogeshnull 
3281*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.nvm_sanitization;
3282*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_sanitization);
3283*dea5f973SBhosale, Yogeshnull 	cmd->cmd_flags = cmd_flags;
3284*dea5f973SBhosale, Yogeshnull 
3285*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
3286*dea5f973SBhosale, Yogeshnull 	if (values)
3287*dea5f973SBhosale, Yogeshnull 		*values = cmd->values;
3288*dea5f973SBhosale, Yogeshnull 
3289*dea5f973SBhosale, Yogeshnull 	return status;
3290*dea5f973SBhosale, Yogeshnull }
3291*dea5f973SBhosale, Yogeshnull 
3292*dea5f973SBhosale, Yogeshnull /**
3293*dea5f973SBhosale, Yogeshnull  * ixgbe_read_sr_word_aci - Reads Shadow RAM via ACI
3294*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
3295*dea5f973SBhosale, Yogeshnull  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
3296*dea5f973SBhosale, Yogeshnull  * @data: word read from the Shadow RAM
3297*dea5f973SBhosale, Yogeshnull  *
3298*dea5f973SBhosale, Yogeshnull  * Reads one 16 bit word from the Shadow RAM using ixgbe_read_flat_nvm.
3299*dea5f973SBhosale, Yogeshnull  *
3300*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3301*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_sr_word_aci(struct ixgbe_hw * hw,u16 offset,u16 * data)3302*dea5f973SBhosale, Yogeshnull s32 ixgbe_read_sr_word_aci(struct ixgbe_hw  *hw, u16 offset, u16 *data)
3303*dea5f973SBhosale, Yogeshnull {
3304*dea5f973SBhosale, Yogeshnull 	u32 bytes = sizeof(u16);
3305*dea5f973SBhosale, Yogeshnull 	__le16 data_local;
3306*dea5f973SBhosale, Yogeshnull 	s32 status;
3307*dea5f973SBhosale, Yogeshnull 
3308*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_flat_nvm(hw, offset * sizeof(u16), &bytes,
3309*dea5f973SBhosale, Yogeshnull 				     (u8 *)&data_local, true);
3310*dea5f973SBhosale, Yogeshnull 	if (status)
3311*dea5f973SBhosale, Yogeshnull 		return status;
3312*dea5f973SBhosale, Yogeshnull 
3313*dea5f973SBhosale, Yogeshnull 	*data = IXGBE_LE16_TO_CPU(data_local);
3314*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
3315*dea5f973SBhosale, Yogeshnull }
3316*dea5f973SBhosale, Yogeshnull 
3317*dea5f973SBhosale, Yogeshnull /**
3318*dea5f973SBhosale, Yogeshnull  * ixgbe_read_sr_buf_aci - Reads Shadow RAM buf via ACI
3319*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
3320*dea5f973SBhosale, Yogeshnull  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
3321*dea5f973SBhosale, Yogeshnull  * @words: (in) number of words to read; (out) number of words actually read
3322*dea5f973SBhosale, Yogeshnull  * @data: words read from the Shadow RAM
3323*dea5f973SBhosale, Yogeshnull  *
3324*dea5f973SBhosale, Yogeshnull  * Reads 16 bit words (data buf) from the Shadow RAM. Ownership of the NVM is
3325*dea5f973SBhosale, Yogeshnull  * taken before reading the buffer and later released.
3326*dea5f973SBhosale, Yogeshnull  *
3327*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3328*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_sr_buf_aci(struct ixgbe_hw * hw,u16 offset,u16 * words,u16 * data)3329*dea5f973SBhosale, Yogeshnull s32 ixgbe_read_sr_buf_aci(struct ixgbe_hw *hw, u16 offset, u16 *words,
3330*dea5f973SBhosale, Yogeshnull 			  u16 *data)
3331*dea5f973SBhosale, Yogeshnull {
3332*dea5f973SBhosale, Yogeshnull 	u32 bytes = *words * 2, i;
3333*dea5f973SBhosale, Yogeshnull 	s32 status;
3334*dea5f973SBhosale, Yogeshnull 
3335*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_flat_nvm(hw, offset * 2, &bytes, (u8 *)data, true);
3336*dea5f973SBhosale, Yogeshnull 
3337*dea5f973SBhosale, Yogeshnull 	*words = bytes / 2;
3338*dea5f973SBhosale, Yogeshnull 
3339*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < *words; i++)
3340*dea5f973SBhosale, Yogeshnull 		data[i] = IXGBE_LE16_TO_CPU(((__le16 *)data)[i]);
3341*dea5f973SBhosale, Yogeshnull 
3342*dea5f973SBhosale, Yogeshnull 	return status;
3343*dea5f973SBhosale, Yogeshnull }
3344*dea5f973SBhosale, Yogeshnull 
3345*dea5f973SBhosale, Yogeshnull /**
3346*dea5f973SBhosale, Yogeshnull  * ixgbe_read_flat_nvm - Read portion of NVM by flat offset
3347*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
3348*dea5f973SBhosale, Yogeshnull  * @offset: offset from beginning of NVM
3349*dea5f973SBhosale, Yogeshnull  * @length: (in) number of bytes to read; (out) number of bytes actually read
3350*dea5f973SBhosale, Yogeshnull  * @data: buffer to return data in (sized to fit the specified length)
3351*dea5f973SBhosale, Yogeshnull  * @read_shadow_ram: if true, read from shadow RAM instead of NVM
3352*dea5f973SBhosale, Yogeshnull  *
3353*dea5f973SBhosale, Yogeshnull  * Reads a portion of the NVM, as a flat memory space. This function correctly
3354*dea5f973SBhosale, Yogeshnull  * breaks read requests across Shadow RAM sectors, prevents Shadow RAM size
3355*dea5f973SBhosale, Yogeshnull  * from being exceeded in case of Shadow RAM read requests and ensures that no
3356*dea5f973SBhosale, Yogeshnull  * single read request exceeds the maximum 4KB read for a single admin command.
3357*dea5f973SBhosale, Yogeshnull  *
3358*dea5f973SBhosale, Yogeshnull  * Returns a status code on failure. Note that the data pointer may be
3359*dea5f973SBhosale, Yogeshnull  * partially updated if some reads succeed before a failure.
3360*dea5f973SBhosale, Yogeshnull  *
3361*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3362*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_flat_nvm(struct ixgbe_hw * hw,u32 offset,u32 * length,u8 * data,bool read_shadow_ram)3363*dea5f973SBhosale, Yogeshnull s32 ixgbe_read_flat_nvm(struct ixgbe_hw  *hw, u32 offset, u32 *length,
3364*dea5f973SBhosale, Yogeshnull 			u8 *data, bool read_shadow_ram)
3365*dea5f973SBhosale, Yogeshnull {
3366*dea5f973SBhosale, Yogeshnull 	u32 inlen = *length;
3367*dea5f973SBhosale, Yogeshnull 	u32 bytes_read = 0;
3368*dea5f973SBhosale, Yogeshnull 	bool last_cmd;
3369*dea5f973SBhosale, Yogeshnull 	s32 status;
3370*dea5f973SBhosale, Yogeshnull 
3371*dea5f973SBhosale, Yogeshnull 	*length = 0;
3372*dea5f973SBhosale, Yogeshnull 
3373*dea5f973SBhosale, Yogeshnull 	/* Verify the length of the read if this is for the Shadow RAM */
3374*dea5f973SBhosale, Yogeshnull 	if (read_shadow_ram && ((offset + inlen) >
3375*dea5f973SBhosale, Yogeshnull 				(hw->eeprom.word_size * 2u))) {
3376*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
3377*dea5f973SBhosale, Yogeshnull 	}
3378*dea5f973SBhosale, Yogeshnull 
3379*dea5f973SBhosale, Yogeshnull 	do {
3380*dea5f973SBhosale, Yogeshnull 		u32 read_size, sector_offset;
3381*dea5f973SBhosale, Yogeshnull 
3382*dea5f973SBhosale, Yogeshnull 		/* ixgbe_aci_read_nvm cannot read more than 4KB at a time.
3383*dea5f973SBhosale, Yogeshnull 		 * Additionally, a read from the Shadow RAM may not cross over
3384*dea5f973SBhosale, Yogeshnull 		 * a sector boundary. Conveniently, the sector size is also 4KB.
3385*dea5f973SBhosale, Yogeshnull 		 */
3386*dea5f973SBhosale, Yogeshnull 		sector_offset = offset % IXGBE_ACI_MAX_BUFFER_SIZE;
3387*dea5f973SBhosale, Yogeshnull 		read_size = MIN_T(u32,
3388*dea5f973SBhosale, Yogeshnull 				  IXGBE_ACI_MAX_BUFFER_SIZE - sector_offset,
3389*dea5f973SBhosale, Yogeshnull 				  inlen - bytes_read);
3390*dea5f973SBhosale, Yogeshnull 
3391*dea5f973SBhosale, Yogeshnull 		last_cmd = !(bytes_read + read_size < inlen);
3392*dea5f973SBhosale, Yogeshnull 
3393*dea5f973SBhosale, Yogeshnull 		/* ixgbe_aci_read_nvm takes the length as a u16. Our read_size
3394*dea5f973SBhosale, Yogeshnull 		 * is calculated using a u32, but the IXGBE_ACI_MAX_BUFFER_SIZE
3395*dea5f973SBhosale, Yogeshnull 		 * maximum size guarantees that it will fit within the 2 bytes.
3396*dea5f973SBhosale, Yogeshnull 		 */
3397*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_read_nvm(hw, IXGBE_ACI_NVM_START_POINT,
3398*dea5f973SBhosale, Yogeshnull 					    offset, (u16)read_size,
3399*dea5f973SBhosale, Yogeshnull 					    data + bytes_read, last_cmd,
3400*dea5f973SBhosale, Yogeshnull 					    read_shadow_ram);
3401*dea5f973SBhosale, Yogeshnull 		if (status)
3402*dea5f973SBhosale, Yogeshnull 			break;
3403*dea5f973SBhosale, Yogeshnull 
3404*dea5f973SBhosale, Yogeshnull 		bytes_read += read_size;
3405*dea5f973SBhosale, Yogeshnull 		offset += read_size;
3406*dea5f973SBhosale, Yogeshnull 	} while (!last_cmd);
3407*dea5f973SBhosale, Yogeshnull 
3408*dea5f973SBhosale, Yogeshnull 	*length = bytes_read;
3409*dea5f973SBhosale, Yogeshnull 	return status;
3410*dea5f973SBhosale, Yogeshnull }
3411*dea5f973SBhosale, Yogeshnull 
3412*dea5f973SBhosale, Yogeshnull /**
3413*dea5f973SBhosale, Yogeshnull  * ixgbe_check_sr_access_params - verify params for Shadow RAM R/W operations.
3414*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
3415*dea5f973SBhosale, Yogeshnull  * @offset: offset in words from module start
3416*dea5f973SBhosale, Yogeshnull  * @words: number of words to access
3417*dea5f973SBhosale, Yogeshnull  *
3418*dea5f973SBhosale, Yogeshnull  * Check if all the parameters are valid
3419*dea5f973SBhosale, Yogeshnull  * before performing any Shadow RAM read/write operations.
3420*dea5f973SBhosale, Yogeshnull  *
3421*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3422*dea5f973SBhosale, Yogeshnull  * * - IXGBE_SUCCESS - success.
3423*dea5f973SBhosale, Yogeshnull  * * - IXGBE_ERR_PARAM - NVM error: offset beyond SR limit or
3424*dea5f973SBhosale, Yogeshnull  * NVM error: tried to access more words then the set limit or
3425*dea5f973SBhosale, Yogeshnull  * NVM error: cannot spread over two sectors.
3426*dea5f973SBhosale, Yogeshnull  */
ixgbe_check_sr_access_params(struct ixgbe_hw * hw,u32 offset,u16 words)3427*dea5f973SBhosale, Yogeshnull static s32 ixgbe_check_sr_access_params(struct ixgbe_hw *hw, u32 offset,
3428*dea5f973SBhosale, Yogeshnull 					u16 words)
3429*dea5f973SBhosale, Yogeshnull {
3430*dea5f973SBhosale, Yogeshnull 	if ((offset + words) > hw->eeprom.word_size) {
3431*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
3432*dea5f973SBhosale, Yogeshnull 	}
3433*dea5f973SBhosale, Yogeshnull 
3434*dea5f973SBhosale, Yogeshnull 	if (words > IXGBE_SR_SECTOR_SIZE_IN_WORDS) {
3435*dea5f973SBhosale, Yogeshnull 		/* We can access only up to 4KB (one sector),
3436*dea5f973SBhosale, Yogeshnull 		 * in one Admin Command write
3437*dea5f973SBhosale, Yogeshnull 		 */
3438*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
3439*dea5f973SBhosale, Yogeshnull 	}
3440*dea5f973SBhosale, Yogeshnull 
3441*dea5f973SBhosale, Yogeshnull 	if (((offset + (words - 1)) / IXGBE_SR_SECTOR_SIZE_IN_WORDS) !=
3442*dea5f973SBhosale, Yogeshnull 	    (offset / IXGBE_SR_SECTOR_SIZE_IN_WORDS)) {
3443*dea5f973SBhosale, Yogeshnull 		/* A single access cannot spread over two sectors */
3444*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
3445*dea5f973SBhosale, Yogeshnull 	}
3446*dea5f973SBhosale, Yogeshnull 
3447*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
3448*dea5f973SBhosale, Yogeshnull }
3449*dea5f973SBhosale, Yogeshnull 
3450*dea5f973SBhosale, Yogeshnull /**
3451*dea5f973SBhosale, Yogeshnull  * ixgbe_write_sr_word_aci - Writes Shadow RAM word
3452*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
3453*dea5f973SBhosale, Yogeshnull  * @offset: offset of the Shadow RAM word to write
3454*dea5f973SBhosale, Yogeshnull  * @data: word to write to the Shadow RAM
3455*dea5f973SBhosale, Yogeshnull  *
3456*dea5f973SBhosale, Yogeshnull  * Writes a 16 bit word to the Shadow RAM using the admin command.
3457*dea5f973SBhosale, Yogeshnull  * NVM ownership must be acquired before calling this function and released
3458*dea5f973SBhosale, Yogeshnull  * by a caller. To commit SR to NVM update checksum function should be called.
3459*dea5f973SBhosale, Yogeshnull  *
3460*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3461*dea5f973SBhosale, Yogeshnull  */
ixgbe_write_sr_word_aci(struct ixgbe_hw * hw,u32 offset,const u16 * data)3462*dea5f973SBhosale, Yogeshnull s32 ixgbe_write_sr_word_aci(struct ixgbe_hw *hw, u32 offset, const u16 *data)
3463*dea5f973SBhosale, Yogeshnull {
3464*dea5f973SBhosale, Yogeshnull 	__le16 data_local = IXGBE_CPU_TO_LE16(*data);
3465*dea5f973SBhosale, Yogeshnull 	s32 status;
3466*dea5f973SBhosale, Yogeshnull 
3467*dea5f973SBhosale, Yogeshnull 	status = ixgbe_check_sr_access_params(hw, offset, 1);
3468*dea5f973SBhosale, Yogeshnull 	if (!status)
3469*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_update_nvm(hw, 0, BYTES_PER_WORD * offset,
3470*dea5f973SBhosale, Yogeshnull 					      BYTES_PER_WORD, &data_local,
3471*dea5f973SBhosale, Yogeshnull 					      false, 0);
3472*dea5f973SBhosale, Yogeshnull 
3473*dea5f973SBhosale, Yogeshnull 	return status;
3474*dea5f973SBhosale, Yogeshnull }
3475*dea5f973SBhosale, Yogeshnull 
3476*dea5f973SBhosale, Yogeshnull /**
3477*dea5f973SBhosale, Yogeshnull  * ixgbe_write_sr_buf_aci - Writes Shadow RAM buf
3478*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
3479*dea5f973SBhosale, Yogeshnull  * @offset: offset of the Shadow RAM buffer to write
3480*dea5f973SBhosale, Yogeshnull  * @words: number of words to write
3481*dea5f973SBhosale, Yogeshnull  * @data: words to write to the Shadow RAM
3482*dea5f973SBhosale, Yogeshnull  *
3483*dea5f973SBhosale, Yogeshnull  * Writes a 16 bit word to the Shadow RAM using the admin command.
3484*dea5f973SBhosale, Yogeshnull  * NVM ownership must be acquired before calling this function and released
3485*dea5f973SBhosale, Yogeshnull  * by a caller. To commit SR to NVM update checksum function should be called.
3486*dea5f973SBhosale, Yogeshnull  *
3487*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3488*dea5f973SBhosale, Yogeshnull  */
ixgbe_write_sr_buf_aci(struct ixgbe_hw * hw,u32 offset,u16 words,const u16 * data)3489*dea5f973SBhosale, Yogeshnull s32 ixgbe_write_sr_buf_aci(struct ixgbe_hw *hw, u32 offset, u16 words,
3490*dea5f973SBhosale, Yogeshnull 			   const u16 *data)
3491*dea5f973SBhosale, Yogeshnull {
3492*dea5f973SBhosale, Yogeshnull 	__le16 *data_local;
3493*dea5f973SBhosale, Yogeshnull 	s32 status;
3494*dea5f973SBhosale, Yogeshnull 	void *vmem;
3495*dea5f973SBhosale, Yogeshnull 	u32 i;
3496*dea5f973SBhosale, Yogeshnull 
3497*dea5f973SBhosale, Yogeshnull 	vmem = ixgbe_calloc(hw, words, sizeof(u16));
3498*dea5f973SBhosale, Yogeshnull 	if (!vmem)
3499*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_OUT_OF_MEM;
3500*dea5f973SBhosale, Yogeshnull 	data_local = (__le16 *)vmem;
3501*dea5f973SBhosale, Yogeshnull 
3502*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < words; i++)
3503*dea5f973SBhosale, Yogeshnull 		data_local[i] = IXGBE_CPU_TO_LE16(data[i]);
3504*dea5f973SBhosale, Yogeshnull 
3505*dea5f973SBhosale, Yogeshnull 	/* Here we will only write one buffer as the size of the modules
3506*dea5f973SBhosale, Yogeshnull 	 * mirrored in the Shadow RAM is always less than 4K.
3507*dea5f973SBhosale, Yogeshnull 	 */
3508*dea5f973SBhosale, Yogeshnull 	status = ixgbe_check_sr_access_params(hw, offset, words);
3509*dea5f973SBhosale, Yogeshnull 	if (!status)
3510*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_update_nvm(hw, 0, BYTES_PER_WORD * offset,
3511*dea5f973SBhosale, Yogeshnull 					      BYTES_PER_WORD * words,
3512*dea5f973SBhosale, Yogeshnull 					      data_local, false, 0);
3513*dea5f973SBhosale, Yogeshnull 
3514*dea5f973SBhosale, Yogeshnull 	ixgbe_free(hw, vmem);
3515*dea5f973SBhosale, Yogeshnull 
3516*dea5f973SBhosale, Yogeshnull 	return status;
3517*dea5f973SBhosale, Yogeshnull }
3518*dea5f973SBhosale, Yogeshnull 
3519*dea5f973SBhosale, Yogeshnull /**
3520*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_alternate_write - write to alternate structure
3521*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hardware structure
3522*dea5f973SBhosale, Yogeshnull  * @reg_addr0: address of first dword to be written
3523*dea5f973SBhosale, Yogeshnull  * @reg_val0: value to be written under 'reg_addr0'
3524*dea5f973SBhosale, Yogeshnull  * @reg_addr1: address of second dword to be written
3525*dea5f973SBhosale, Yogeshnull  * @reg_val1: value to be written under 'reg_addr1'
3526*dea5f973SBhosale, Yogeshnull  *
3527*dea5f973SBhosale, Yogeshnull  * Write one or two dwords to alternate structure using ACI command (0x0900).
3528*dea5f973SBhosale, Yogeshnull  * Fields are indicated by 'reg_addr0' and 'reg_addr1' register numbers.
3529*dea5f973SBhosale, Yogeshnull  *
3530*dea5f973SBhosale, Yogeshnull  * Return: 0 on success and error code on failure.
3531*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_alternate_write(struct ixgbe_hw * hw,u32 reg_addr0,u32 reg_val0,u32 reg_addr1,u32 reg_val1)3532*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_alternate_write(struct ixgbe_hw *hw, u32 reg_addr0,
3533*dea5f973SBhosale, Yogeshnull 			      u32 reg_val0, u32 reg_addr1, u32 reg_val1)
3534*dea5f973SBhosale, Yogeshnull {
3535*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_read_write_alt_direct *cmd;
3536*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
3537*dea5f973SBhosale, Yogeshnull 	s32 status;
3538*dea5f973SBhosale, Yogeshnull 
3539*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.read_write_alt_direct;
3540*dea5f973SBhosale, Yogeshnull 
3541*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_write_alt_direct);
3542*dea5f973SBhosale, Yogeshnull 	cmd->dword0_addr = IXGBE_CPU_TO_LE32(reg_addr0);
3543*dea5f973SBhosale, Yogeshnull 	cmd->dword1_addr = IXGBE_CPU_TO_LE32(reg_addr1);
3544*dea5f973SBhosale, Yogeshnull 	cmd->dword0_value = IXGBE_CPU_TO_LE32(reg_val0);
3545*dea5f973SBhosale, Yogeshnull 	cmd->dword1_value = IXGBE_CPU_TO_LE32(reg_val1);
3546*dea5f973SBhosale, Yogeshnull 
3547*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
3548*dea5f973SBhosale, Yogeshnull 
3549*dea5f973SBhosale, Yogeshnull 	return status;
3550*dea5f973SBhosale, Yogeshnull }
3551*dea5f973SBhosale, Yogeshnull 
3552*dea5f973SBhosale, Yogeshnull /**
3553*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_alternate_read - read from alternate structure
3554*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hardware structure
3555*dea5f973SBhosale, Yogeshnull  * @reg_addr0: address of first dword to be read
3556*dea5f973SBhosale, Yogeshnull  * @reg_val0: pointer for data read from 'reg_addr0'
3557*dea5f973SBhosale, Yogeshnull  * @reg_addr1: address of second dword to be read
3558*dea5f973SBhosale, Yogeshnull  * @reg_val1: pointer for data read from 'reg_addr1'
3559*dea5f973SBhosale, Yogeshnull  *
3560*dea5f973SBhosale, Yogeshnull  * Read one or two dwords from alternate structure using ACI command (0x0902).
3561*dea5f973SBhosale, Yogeshnull  * Fields are indicated by 'reg_addr0' and 'reg_addr1' register numbers.
3562*dea5f973SBhosale, Yogeshnull  * If 'reg_val1' pointer is not passed then only register at 'reg_addr0'
3563*dea5f973SBhosale, Yogeshnull  * is read.
3564*dea5f973SBhosale, Yogeshnull  *
3565*dea5f973SBhosale, Yogeshnull  * Return: 0 on success and error code on failure.
3566*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_alternate_read(struct ixgbe_hw * hw,u32 reg_addr0,u32 * reg_val0,u32 reg_addr1,u32 * reg_val1)3567*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_alternate_read(struct ixgbe_hw *hw, u32 reg_addr0,
3568*dea5f973SBhosale, Yogeshnull 			     u32 *reg_val0, u32 reg_addr1, u32 *reg_val1)
3569*dea5f973SBhosale, Yogeshnull {
3570*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_read_write_alt_direct *cmd;
3571*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
3572*dea5f973SBhosale, Yogeshnull 	s32 status;
3573*dea5f973SBhosale, Yogeshnull 
3574*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.read_write_alt_direct;
3575*dea5f973SBhosale, Yogeshnull 
3576*dea5f973SBhosale, Yogeshnull 	if (!reg_val0)
3577*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
3578*dea5f973SBhosale, Yogeshnull 
3579*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_read_alt_direct);
3580*dea5f973SBhosale, Yogeshnull 	cmd->dword0_addr = IXGBE_CPU_TO_LE32(reg_addr0);
3581*dea5f973SBhosale, Yogeshnull 	cmd->dword1_addr = IXGBE_CPU_TO_LE32(reg_addr1);
3582*dea5f973SBhosale, Yogeshnull 
3583*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
3584*dea5f973SBhosale, Yogeshnull 
3585*dea5f973SBhosale, Yogeshnull 	if (status == IXGBE_SUCCESS) {
3586*dea5f973SBhosale, Yogeshnull 		*reg_val0 = IXGBE_LE32_TO_CPU(cmd->dword0_value);
3587*dea5f973SBhosale, Yogeshnull 
3588*dea5f973SBhosale, Yogeshnull 		if (reg_val1)
3589*dea5f973SBhosale, Yogeshnull 			*reg_val1 = IXGBE_LE32_TO_CPU(cmd->dword1_value);
3590*dea5f973SBhosale, Yogeshnull 	}
3591*dea5f973SBhosale, Yogeshnull 
3592*dea5f973SBhosale, Yogeshnull 	return status;
3593*dea5f973SBhosale, Yogeshnull }
3594*dea5f973SBhosale, Yogeshnull 
3595*dea5f973SBhosale, Yogeshnull /**
3596*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_alternate_write_done - check if writing to alternate structure
3597*dea5f973SBhosale, Yogeshnull  * is done
3598*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure.
3599*dea5f973SBhosale, Yogeshnull  * @bios_mode: indicates whether the command is executed by UEFI or legacy BIOS
3600*dea5f973SBhosale, Yogeshnull  * @reset_needed: indicates the SW should trigger GLOBAL reset
3601*dea5f973SBhosale, Yogeshnull  *
3602*dea5f973SBhosale, Yogeshnull  * Indicates to the FW that alternate structures have been changed.
3603*dea5f973SBhosale, Yogeshnull  *
3604*dea5f973SBhosale, Yogeshnull  * Return: 0 on success and error code on failure.
3605*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_alternate_write_done(struct ixgbe_hw * hw,u8 bios_mode,bool * reset_needed)3606*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_alternate_write_done(struct ixgbe_hw *hw, u8 bios_mode,
3607*dea5f973SBhosale, Yogeshnull 				   bool *reset_needed)
3608*dea5f973SBhosale, Yogeshnull {
3609*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_done_alt_write *cmd;
3610*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
3611*dea5f973SBhosale, Yogeshnull 	s32 status;
3612*dea5f973SBhosale, Yogeshnull 
3613*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.done_alt_write;
3614*dea5f973SBhosale, Yogeshnull 
3615*dea5f973SBhosale, Yogeshnull 	if (!reset_needed)
3616*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
3617*dea5f973SBhosale, Yogeshnull 
3618*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_done_alt_write);
3619*dea5f973SBhosale, Yogeshnull 	cmd->flags = bios_mode;
3620*dea5f973SBhosale, Yogeshnull 
3621*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
3622*dea5f973SBhosale, Yogeshnull 	if (!status)
3623*dea5f973SBhosale, Yogeshnull 		*reset_needed = (IXGBE_LE16_TO_CPU(cmd->flags) &
3624*dea5f973SBhosale, Yogeshnull 				 IXGBE_ACI_RESP_RESET_NEEDED) != 0;
3625*dea5f973SBhosale, Yogeshnull 
3626*dea5f973SBhosale, Yogeshnull 	return status;
3627*dea5f973SBhosale, Yogeshnull }
3628*dea5f973SBhosale, Yogeshnull 
3629*dea5f973SBhosale, Yogeshnull /**
3630*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_alternate_clear - clear alternate structure
3631*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure.
3632*dea5f973SBhosale, Yogeshnull  *
3633*dea5f973SBhosale, Yogeshnull  * Clear the alternate structures of the port from which the function
3634*dea5f973SBhosale, Yogeshnull  * is called.
3635*dea5f973SBhosale, Yogeshnull  *
3636*dea5f973SBhosale, Yogeshnull  * Return: 0 on success and error code on failure.
3637*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_alternate_clear(struct ixgbe_hw * hw)3638*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_alternate_clear(struct ixgbe_hw *hw)
3639*dea5f973SBhosale, Yogeshnull {
3640*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
3641*dea5f973SBhosale, Yogeshnull 	s32 status;
3642*dea5f973SBhosale, Yogeshnull 
3643*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc,
3644*dea5f973SBhosale, Yogeshnull 					ixgbe_aci_opc_clear_port_alt_write);
3645*dea5f973SBhosale, Yogeshnull 
3646*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
3647*dea5f973SBhosale, Yogeshnull 
3648*dea5f973SBhosale, Yogeshnull 	return status;
3649*dea5f973SBhosale, Yogeshnull }
3650*dea5f973SBhosale, Yogeshnull 
3651*dea5f973SBhosale, Yogeshnull /**
3652*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_get_internal_data - get internal FW/HW data
3653*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the hardware structure
3654*dea5f973SBhosale, Yogeshnull  * @cluster_id: specific cluster to dump
3655*dea5f973SBhosale, Yogeshnull  * @table_id: table ID within cluster
3656*dea5f973SBhosale, Yogeshnull  * @start: index of line in the block to read
3657*dea5f973SBhosale, Yogeshnull  * @buf: dump buffer
3658*dea5f973SBhosale, Yogeshnull  * @buf_size: dump buffer size
3659*dea5f973SBhosale, Yogeshnull  * @ret_buf_size: return buffer size (returned by FW)
3660*dea5f973SBhosale, Yogeshnull  * @ret_next_cluster: next cluster to read (returned by FW)
3661*dea5f973SBhosale, Yogeshnull  * @ret_next_table: next block to read (returned by FW)
3662*dea5f973SBhosale, Yogeshnull  * @ret_next_index: next index to read (returned by FW)
3663*dea5f973SBhosale, Yogeshnull  *
3664*dea5f973SBhosale, Yogeshnull  * Get internal FW/HW data using ACI command (0xFF08) for debug purposes.
3665*dea5f973SBhosale, Yogeshnull  *
3666*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3667*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_get_internal_data(struct ixgbe_hw * hw,u16 cluster_id,u16 table_id,u32 start,void * buf,u16 buf_size,u16 * ret_buf_size,u16 * ret_next_cluster,u16 * ret_next_table,u32 * ret_next_index)3668*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_get_internal_data(struct ixgbe_hw *hw, u16 cluster_id,
3669*dea5f973SBhosale, Yogeshnull 				u16 table_id, u32 start, void *buf,
3670*dea5f973SBhosale, Yogeshnull 				u16 buf_size, u16 *ret_buf_size,
3671*dea5f973SBhosale, Yogeshnull 				u16 *ret_next_cluster, u16 *ret_next_table,
3672*dea5f973SBhosale, Yogeshnull 				u32 *ret_next_index)
3673*dea5f973SBhosale, Yogeshnull {
3674*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_debug_dump_internals *cmd;
3675*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
3676*dea5f973SBhosale, Yogeshnull 	s32 status;
3677*dea5f973SBhosale, Yogeshnull 
3678*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.debug_dump;
3679*dea5f973SBhosale, Yogeshnull 
3680*dea5f973SBhosale, Yogeshnull 	if (buf_size == 0 || !buf)
3681*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
3682*dea5f973SBhosale, Yogeshnull 
3683*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc,
3684*dea5f973SBhosale, Yogeshnull 					ixgbe_aci_opc_debug_dump_internals);
3685*dea5f973SBhosale, Yogeshnull 
3686*dea5f973SBhosale, Yogeshnull 	cmd->cluster_id = IXGBE_CPU_TO_LE16(cluster_id);
3687*dea5f973SBhosale, Yogeshnull 	cmd->table_id = IXGBE_CPU_TO_LE16(table_id);
3688*dea5f973SBhosale, Yogeshnull 	cmd->idx = IXGBE_CPU_TO_LE32(start);
3689*dea5f973SBhosale, Yogeshnull 
3690*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, buf, buf_size);
3691*dea5f973SBhosale, Yogeshnull 
3692*dea5f973SBhosale, Yogeshnull 	if (!status) {
3693*dea5f973SBhosale, Yogeshnull 		if (ret_buf_size)
3694*dea5f973SBhosale, Yogeshnull 			*ret_buf_size = IXGBE_LE16_TO_CPU(desc.datalen);
3695*dea5f973SBhosale, Yogeshnull 		if (ret_next_cluster)
3696*dea5f973SBhosale, Yogeshnull 			*ret_next_cluster = IXGBE_LE16_TO_CPU(cmd->cluster_id);
3697*dea5f973SBhosale, Yogeshnull 		if (ret_next_table)
3698*dea5f973SBhosale, Yogeshnull 			*ret_next_table = IXGBE_LE16_TO_CPU(cmd->table_id);
3699*dea5f973SBhosale, Yogeshnull 		if (ret_next_index)
3700*dea5f973SBhosale, Yogeshnull 			*ret_next_index = IXGBE_LE32_TO_CPU(cmd->idx);
3701*dea5f973SBhosale, Yogeshnull 	}
3702*dea5f973SBhosale, Yogeshnull 
3703*dea5f973SBhosale, Yogeshnull 	return status;
3704*dea5f973SBhosale, Yogeshnull }
3705*dea5f973SBhosale, Yogeshnull 
3706*dea5f973SBhosale, Yogeshnull /**
3707*dea5f973SBhosale, Yogeshnull  * ixgbe_validate_nvm_rw_reg - Check that an NVM access request is valid
3708*dea5f973SBhosale, Yogeshnull  * @cmd: NVM access command structure
3709*dea5f973SBhosale, Yogeshnull  *
3710*dea5f973SBhosale, Yogeshnull  * Validates that an NVM access structure is request to read or write a valid
3711*dea5f973SBhosale, Yogeshnull  * register offset. First validates that the module and flags are correct, and
3712*dea5f973SBhosale, Yogeshnull  * then ensures that the register offset is one of the accepted registers.
3713*dea5f973SBhosale, Yogeshnull  *
3714*dea5f973SBhosale, Yogeshnull  * Return: 0 if the register access is valid, out of range error code otherwise.
3715*dea5f973SBhosale, Yogeshnull  */
3716*dea5f973SBhosale, Yogeshnull static s32
ixgbe_validate_nvm_rw_reg(struct ixgbe_nvm_access_cmd * cmd)3717*dea5f973SBhosale, Yogeshnull ixgbe_validate_nvm_rw_reg(struct ixgbe_nvm_access_cmd *cmd)
3718*dea5f973SBhosale, Yogeshnull {
3719*dea5f973SBhosale, Yogeshnull 	u16 i;
3720*dea5f973SBhosale, Yogeshnull 
3721*dea5f973SBhosale, Yogeshnull 	switch (cmd->offset) {
3722*dea5f973SBhosale, Yogeshnull 	case GL_HICR:
3723*dea5f973SBhosale, Yogeshnull 	case GL_HICR_EN: /* Note, this register is read only */
3724*dea5f973SBhosale, Yogeshnull 	case GL_FWSTS:
3725*dea5f973SBhosale, Yogeshnull 	case GL_MNG_FWSM:
3726*dea5f973SBhosale, Yogeshnull 	case GLNVM_GENS:
3727*dea5f973SBhosale, Yogeshnull 	case GLNVM_FLA:
3728*dea5f973SBhosale, Yogeshnull 	case GL_FWRESETCNT:
3729*dea5f973SBhosale, Yogeshnull 		return 0;
3730*dea5f973SBhosale, Yogeshnull 	default:
3731*dea5f973SBhosale, Yogeshnull 		break;
3732*dea5f973SBhosale, Yogeshnull 	}
3733*dea5f973SBhosale, Yogeshnull 
3734*dea5f973SBhosale, Yogeshnull 	for (i = 0; i <= GL_HIDA_MAX_INDEX; i++)
3735*dea5f973SBhosale, Yogeshnull 		if (cmd->offset == (u32)GL_HIDA(i))
3736*dea5f973SBhosale, Yogeshnull 			return 0;
3737*dea5f973SBhosale, Yogeshnull 
3738*dea5f973SBhosale, Yogeshnull 	for (i = 0; i <= GL_HIBA_MAX_INDEX; i++)
3739*dea5f973SBhosale, Yogeshnull 		if (cmd->offset == (u32)GL_HIBA(i))
3740*dea5f973SBhosale, Yogeshnull 			return 0;
3741*dea5f973SBhosale, Yogeshnull 
3742*dea5f973SBhosale, Yogeshnull 	/* All other register offsets are not valid */
3743*dea5f973SBhosale, Yogeshnull 	return IXGBE_ERR_OUT_OF_RANGE;
3744*dea5f973SBhosale, Yogeshnull }
3745*dea5f973SBhosale, Yogeshnull 
3746*dea5f973SBhosale, Yogeshnull /**
3747*dea5f973SBhosale, Yogeshnull  * ixgbe_nvm_access_read - Handle an NVM read request
3748*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
3749*dea5f973SBhosale, Yogeshnull  * @cmd: NVM access command to process
3750*dea5f973SBhosale, Yogeshnull  * @data: storage for the register value read
3751*dea5f973SBhosale, Yogeshnull  *
3752*dea5f973SBhosale, Yogeshnull  * Process an NVM access request to read a register.
3753*dea5f973SBhosale, Yogeshnull  *
3754*dea5f973SBhosale, Yogeshnull  * Return: 0 if the register read is valid and successful,
3755*dea5f973SBhosale, Yogeshnull  * out of range error code otherwise.
3756*dea5f973SBhosale, Yogeshnull  */
ixgbe_nvm_access_read(struct ixgbe_hw * hw,struct ixgbe_nvm_access_cmd * cmd,struct ixgbe_nvm_access_data * data)3757*dea5f973SBhosale, Yogeshnull static s32 ixgbe_nvm_access_read(struct ixgbe_hw *hw,
3758*dea5f973SBhosale, Yogeshnull 			struct ixgbe_nvm_access_cmd *cmd,
3759*dea5f973SBhosale, Yogeshnull 			struct ixgbe_nvm_access_data *data)
3760*dea5f973SBhosale, Yogeshnull {
3761*dea5f973SBhosale, Yogeshnull 	s32 status;
3762*dea5f973SBhosale, Yogeshnull 
3763*dea5f973SBhosale, Yogeshnull 	/* Always initialize the output data, even on failure */
3764*dea5f973SBhosale, Yogeshnull 	memset(&data->regval, 0, cmd->data_size);
3765*dea5f973SBhosale, Yogeshnull 
3766*dea5f973SBhosale, Yogeshnull 	/* Make sure this is a valid read/write access request */
3767*dea5f973SBhosale, Yogeshnull 	status = ixgbe_validate_nvm_rw_reg(cmd);
3768*dea5f973SBhosale, Yogeshnull 	if (status)
3769*dea5f973SBhosale, Yogeshnull 		return status;
3770*dea5f973SBhosale, Yogeshnull 
3771*dea5f973SBhosale, Yogeshnull 	DEBUGOUT1("NVM access: reading register %08x\n", cmd->offset);
3772*dea5f973SBhosale, Yogeshnull 
3773*dea5f973SBhosale, Yogeshnull 	/* Read the register and store the contents in the data field */
3774*dea5f973SBhosale, Yogeshnull 	data->regval = IXGBE_READ_REG(hw, cmd->offset);
3775*dea5f973SBhosale, Yogeshnull 
3776*dea5f973SBhosale, Yogeshnull 	return 0;
3777*dea5f973SBhosale, Yogeshnull }
3778*dea5f973SBhosale, Yogeshnull 
3779*dea5f973SBhosale, Yogeshnull /**
3780*dea5f973SBhosale, Yogeshnull  * ixgbe_nvm_access_write - Handle an NVM write request
3781*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
3782*dea5f973SBhosale, Yogeshnull  * @cmd: NVM access command to process
3783*dea5f973SBhosale, Yogeshnull  * @data: NVM access data to write
3784*dea5f973SBhosale, Yogeshnull  *
3785*dea5f973SBhosale, Yogeshnull  * Process an NVM access request to write a register.
3786*dea5f973SBhosale, Yogeshnull  *
3787*dea5f973SBhosale, Yogeshnull  * Return: 0 if the register write is valid and successful,
3788*dea5f973SBhosale, Yogeshnull  * out of range error code otherwise.
3789*dea5f973SBhosale, Yogeshnull  */
ixgbe_nvm_access_write(struct ixgbe_hw * hw,struct ixgbe_nvm_access_cmd * cmd,struct ixgbe_nvm_access_data * data)3790*dea5f973SBhosale, Yogeshnull static s32 ixgbe_nvm_access_write(struct ixgbe_hw *hw,
3791*dea5f973SBhosale, Yogeshnull 			struct ixgbe_nvm_access_cmd *cmd,
3792*dea5f973SBhosale, Yogeshnull 			struct ixgbe_nvm_access_data *data)
3793*dea5f973SBhosale, Yogeshnull {
3794*dea5f973SBhosale, Yogeshnull 	s32 status;
3795*dea5f973SBhosale, Yogeshnull 
3796*dea5f973SBhosale, Yogeshnull 	/* Make sure this is a valid read/write access request */
3797*dea5f973SBhosale, Yogeshnull 	status = ixgbe_validate_nvm_rw_reg(cmd);
3798*dea5f973SBhosale, Yogeshnull 	if (status)
3799*dea5f973SBhosale, Yogeshnull 		return status;
3800*dea5f973SBhosale, Yogeshnull 
3801*dea5f973SBhosale, Yogeshnull 	/* Reject requests to write to read-only registers */
3802*dea5f973SBhosale, Yogeshnull 	switch (cmd->offset) {
3803*dea5f973SBhosale, Yogeshnull 	case GL_HICR_EN:
3804*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_OUT_OF_RANGE;
3805*dea5f973SBhosale, Yogeshnull 	default:
3806*dea5f973SBhosale, Yogeshnull 		break;
3807*dea5f973SBhosale, Yogeshnull 	}
3808*dea5f973SBhosale, Yogeshnull 
3809*dea5f973SBhosale, Yogeshnull 	DEBUGOUT2("NVM access: writing register %08x with value %08x\n",
3810*dea5f973SBhosale, Yogeshnull 		cmd->offset, data->regval);
3811*dea5f973SBhosale, Yogeshnull 
3812*dea5f973SBhosale, Yogeshnull 	/* Write the data field to the specified register */
3813*dea5f973SBhosale, Yogeshnull 	IXGBE_WRITE_REG(hw, cmd->offset, data->regval);
3814*dea5f973SBhosale, Yogeshnull 
3815*dea5f973SBhosale, Yogeshnull 	return 0;
3816*dea5f973SBhosale, Yogeshnull }
3817*dea5f973SBhosale, Yogeshnull 
3818*dea5f973SBhosale, Yogeshnull /**
3819*dea5f973SBhosale, Yogeshnull  * ixgbe_handle_nvm_access - Handle an NVM access request
3820*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
3821*dea5f973SBhosale, Yogeshnull  * @cmd: NVM access command info
3822*dea5f973SBhosale, Yogeshnull  * @data: pointer to read or return data
3823*dea5f973SBhosale, Yogeshnull  *
3824*dea5f973SBhosale, Yogeshnull  * Process an NVM access request. Read the command structure information and
3825*dea5f973SBhosale, Yogeshnull  * determine if it is valid. If not, report an error indicating the command
3826*dea5f973SBhosale, Yogeshnull  * was invalid.
3827*dea5f973SBhosale, Yogeshnull  *
3828*dea5f973SBhosale, Yogeshnull  * For valid commands, perform the necessary function, copying the data into
3829*dea5f973SBhosale, Yogeshnull  * the provided data buffer.
3830*dea5f973SBhosale, Yogeshnull  *
3831*dea5f973SBhosale, Yogeshnull  * Return: 0 if the nvm access request is valid and successful,
3832*dea5f973SBhosale, Yogeshnull  * error code otherwise.
3833*dea5f973SBhosale, Yogeshnull  */
ixgbe_handle_nvm_access(struct ixgbe_hw * hw,struct ixgbe_nvm_access_cmd * cmd,struct ixgbe_nvm_access_data * data)3834*dea5f973SBhosale, Yogeshnull s32 ixgbe_handle_nvm_access(struct ixgbe_hw *hw,
3835*dea5f973SBhosale, Yogeshnull 			struct ixgbe_nvm_access_cmd *cmd,
3836*dea5f973SBhosale, Yogeshnull 			struct ixgbe_nvm_access_data *data)
3837*dea5f973SBhosale, Yogeshnull {
3838*dea5f973SBhosale, Yogeshnull 	switch (cmd->command) {
3839*dea5f973SBhosale, Yogeshnull 	case IXGBE_NVM_CMD_READ:
3840*dea5f973SBhosale, Yogeshnull 		return ixgbe_nvm_access_read(hw, cmd, data);
3841*dea5f973SBhosale, Yogeshnull 	case IXGBE_NVM_CMD_WRITE:
3842*dea5f973SBhosale, Yogeshnull 		return ixgbe_nvm_access_write(hw, cmd, data);
3843*dea5f973SBhosale, Yogeshnull 	default:
3844*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
3845*dea5f973SBhosale, Yogeshnull 	}
3846*dea5f973SBhosale, Yogeshnull }
3847*dea5f973SBhosale, Yogeshnull 
3848*dea5f973SBhosale, Yogeshnull /**
3849*dea5f973SBhosale, Yogeshnull  * ixgbe_aci_set_health_status_config - Configure FW health events
3850*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
3851*dea5f973SBhosale, Yogeshnull  * @event_source: type of diagnostic events to enable
3852*dea5f973SBhosale, Yogeshnull  *
3853*dea5f973SBhosale, Yogeshnull  * Configure the health status event types that the firmware will send to this
3854*dea5f973SBhosale, Yogeshnull  * PF using ACI command (0xFF20). The supported event types are: PF-specific,
3855*dea5f973SBhosale, Yogeshnull  * all PFs, and global.
3856*dea5f973SBhosale, Yogeshnull  *
3857*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3858*dea5f973SBhosale, Yogeshnull  */
ixgbe_aci_set_health_status_config(struct ixgbe_hw * hw,u8 event_source)3859*dea5f973SBhosale, Yogeshnull s32 ixgbe_aci_set_health_status_config(struct ixgbe_hw *hw, u8 event_source)
3860*dea5f973SBhosale, Yogeshnull {
3861*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_set_health_status_config *cmd;
3862*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
3863*dea5f973SBhosale, Yogeshnull 
3864*dea5f973SBhosale, Yogeshnull 	cmd = &desc.params.set_health_status_config;
3865*dea5f973SBhosale, Yogeshnull 
3866*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc,
3867*dea5f973SBhosale, Yogeshnull 				      ixgbe_aci_opc_set_health_status_config);
3868*dea5f973SBhosale, Yogeshnull 
3869*dea5f973SBhosale, Yogeshnull 	cmd->event_source = event_source;
3870*dea5f973SBhosale, Yogeshnull 
3871*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
3872*dea5f973SBhosale, Yogeshnull }
3873*dea5f973SBhosale, Yogeshnull 
3874*dea5f973SBhosale, Yogeshnull /**
3875*dea5f973SBhosale, Yogeshnull  * ixgbe_init_ops_E610 - Inits func ptrs and MAC type
3876*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
3877*dea5f973SBhosale, Yogeshnull  *
3878*dea5f973SBhosale, Yogeshnull  * Initialize the function pointers and assign the MAC type for E610.
3879*dea5f973SBhosale, Yogeshnull  * Does not touch the hardware.
3880*dea5f973SBhosale, Yogeshnull  *
3881*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3882*dea5f973SBhosale, Yogeshnull  */
ixgbe_init_ops_E610(struct ixgbe_hw * hw)3883*dea5f973SBhosale, Yogeshnull s32 ixgbe_init_ops_E610(struct ixgbe_hw *hw)
3884*dea5f973SBhosale, Yogeshnull {
3885*dea5f973SBhosale, Yogeshnull 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
3886*dea5f973SBhosale, Yogeshnull 	struct ixgbe_mac_info *mac = &hw->mac;
3887*dea5f973SBhosale, Yogeshnull 	struct ixgbe_phy_info *phy = &hw->phy;
3888*dea5f973SBhosale, Yogeshnull 	s32 ret_val;
3889*dea5f973SBhosale, Yogeshnull 
3890*dea5f973SBhosale, Yogeshnull 	ret_val = ixgbe_init_ops_X550(hw);
3891*dea5f973SBhosale, Yogeshnull 
3892*dea5f973SBhosale, Yogeshnull 	/* MAC */
3893*dea5f973SBhosale, Yogeshnull 	mac->ops.reset_hw = ixgbe_reset_hw_E610;
3894*dea5f973SBhosale, Yogeshnull 	mac->ops.start_hw = ixgbe_start_hw_E610;
3895*dea5f973SBhosale, Yogeshnull 	mac->ops.get_media_type = ixgbe_get_media_type_E610;
3896*dea5f973SBhosale, Yogeshnull 	mac->ops.get_supported_physical_layer =
3897*dea5f973SBhosale, Yogeshnull 		ixgbe_get_supported_physical_layer_E610;
3898*dea5f973SBhosale, Yogeshnull 	mac->ops.get_san_mac_addr = NULL;
3899*dea5f973SBhosale, Yogeshnull 	mac->ops.set_san_mac_addr = NULL;
3900*dea5f973SBhosale, Yogeshnull 	mac->ops.get_wwn_prefix = NULL;
3901*dea5f973SBhosale, Yogeshnull 	mac->ops.setup_link = ixgbe_setup_link_E610;
3902*dea5f973SBhosale, Yogeshnull 	mac->ops.check_link = ixgbe_check_link_E610;
3903*dea5f973SBhosale, Yogeshnull 	mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_E610;
3904*dea5f973SBhosale, Yogeshnull 	mac->ops.setup_fc = ixgbe_setup_fc_E610;
3905*dea5f973SBhosale, Yogeshnull 	mac->ops.fc_autoneg = ixgbe_fc_autoneg_E610;
3906*dea5f973SBhosale, Yogeshnull 	mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_E610;
3907*dea5f973SBhosale, Yogeshnull 	mac->ops.disable_rx = ixgbe_disable_rx_E610;
3908*dea5f973SBhosale, Yogeshnull 	mac->ops.setup_eee = ixgbe_setup_eee_E610;
3909*dea5f973SBhosale, Yogeshnull 	mac->ops.fw_recovery_mode = ixgbe_fw_recovery_mode_E610;
3910*dea5f973SBhosale, Yogeshnull 	mac->ops.fw_rollback_mode = ixgbe_fw_rollback_mode_E610;
3911*dea5f973SBhosale, Yogeshnull 	mac->ops.get_fw_tsam_mode = ixgbe_get_fw_tsam_mode_E610;
3912*dea5f973SBhosale, Yogeshnull 	mac->ops.get_fw_version = ixgbe_aci_get_fw_ver;
3913*dea5f973SBhosale, Yogeshnull 	mac->ops.get_nvm_version = ixgbe_get_active_nvm_ver;
3914*dea5f973SBhosale, Yogeshnull        mac->ops.get_thermal_sensor_data = NULL;
3915*dea5f973SBhosale, Yogeshnull        mac->ops.init_thermal_sensor_thresh = NULL;
3916*dea5f973SBhosale, Yogeshnull 
3917*dea5f973SBhosale, Yogeshnull 	/* PHY */
3918*dea5f973SBhosale, Yogeshnull 	phy->ops.init = ixgbe_init_phy_ops_E610;
3919*dea5f973SBhosale, Yogeshnull 	phy->ops.identify = ixgbe_identify_phy_E610;
3920*dea5f973SBhosale, Yogeshnull 	phy->eee_speeds_supported = IXGBE_LINK_SPEED_10_FULL |
3921*dea5f973SBhosale, Yogeshnull 				    IXGBE_LINK_SPEED_100_FULL |
3922*dea5f973SBhosale, Yogeshnull 				    IXGBE_LINK_SPEED_1GB_FULL;
3923*dea5f973SBhosale, Yogeshnull 	phy->eee_speeds_advertised = phy->eee_speeds_supported;
3924*dea5f973SBhosale, Yogeshnull 
3925*dea5f973SBhosale, Yogeshnull 	/* Additional ops overrides for e610 to go here */
3926*dea5f973SBhosale, Yogeshnull 	eeprom->ops.init_params = ixgbe_init_eeprom_params_E610;
3927*dea5f973SBhosale, Yogeshnull 	eeprom->ops.read = ixgbe_read_ee_aci_E610;
3928*dea5f973SBhosale, Yogeshnull 	eeprom->ops.read_buffer = ixgbe_read_ee_aci_buffer_E610;
3929*dea5f973SBhosale, Yogeshnull 	eeprom->ops.write = ixgbe_write_ee_aci_E610;
3930*dea5f973SBhosale, Yogeshnull 	eeprom->ops.write_buffer = ixgbe_write_ee_aci_buffer_E610;
3931*dea5f973SBhosale, Yogeshnull 	eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_E610;
3932*dea5f973SBhosale, Yogeshnull 	eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_E610;
3933*dea5f973SBhosale, Yogeshnull 	eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_E610;
3934*dea5f973SBhosale, Yogeshnull 	eeprom->ops.read_pba_string = ixgbe_read_pba_string_E610;
3935*dea5f973SBhosale, Yogeshnull 
3936*dea5f973SBhosale, Yogeshnull 	/* Initialize bus function number */
3937*dea5f973SBhosale, Yogeshnull 	hw->mac.ops.set_lan_id(hw);
3938*dea5f973SBhosale, Yogeshnull 
3939*dea5f973SBhosale, Yogeshnull 	return ret_val;
3940*dea5f973SBhosale, Yogeshnull }
3941*dea5f973SBhosale, Yogeshnull 
3942*dea5f973SBhosale, Yogeshnull /**
3943*dea5f973SBhosale, Yogeshnull  * ixgbe_reset_hw_E610 - Perform hardware reset
3944*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
3945*dea5f973SBhosale, Yogeshnull  *
3946*dea5f973SBhosale, Yogeshnull  * Resets the hardware by resetting the transmit and receive units, masks
3947*dea5f973SBhosale, Yogeshnull  * and clears all interrupts, and perform a reset.
3948*dea5f973SBhosale, Yogeshnull  *
3949*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
3950*dea5f973SBhosale, Yogeshnull  */
ixgbe_reset_hw_E610(struct ixgbe_hw * hw)3951*dea5f973SBhosale, Yogeshnull s32 ixgbe_reset_hw_E610(struct ixgbe_hw *hw)
3952*dea5f973SBhosale, Yogeshnull {
3953*dea5f973SBhosale, Yogeshnull 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
3954*dea5f973SBhosale, Yogeshnull 	u32 ctrl, i;
3955*dea5f973SBhosale, Yogeshnull 	s32 status;
3956*dea5f973SBhosale, Yogeshnull 
3957*dea5f973SBhosale, Yogeshnull 	DEBUGFUNC("ixgbe_reset_hw_E610");
3958*dea5f973SBhosale, Yogeshnull 
3959*dea5f973SBhosale, Yogeshnull 	/* Call adapter stop to disable tx/rx and clear interrupts */
3960*dea5f973SBhosale, Yogeshnull 	status = hw->mac.ops.stop_adapter(hw);
3961*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS)
3962*dea5f973SBhosale, Yogeshnull 		goto reset_hw_out;
3963*dea5f973SBhosale, Yogeshnull 
3964*dea5f973SBhosale, Yogeshnull 	/* flush pending Tx transactions */
3965*dea5f973SBhosale, Yogeshnull 	ixgbe_clear_tx_pending(hw);
3966*dea5f973SBhosale, Yogeshnull 
3967*dea5f973SBhosale, Yogeshnull 	status = hw->phy.ops.init(hw);
3968*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS)
3969*dea5f973SBhosale, Yogeshnull 		DEBUGOUT1("Failed to initialize PHY ops, STATUS = %d\n",
3970*dea5f973SBhosale, Yogeshnull 			  status);
3971*dea5f973SBhosale, Yogeshnull mac_reset_top:
3972*dea5f973SBhosale, Yogeshnull 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
3973*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS) {
3974*dea5f973SBhosale, Yogeshnull 		ERROR_REPORT2(IXGBE_ERROR_CAUTION,
3975*dea5f973SBhosale, Yogeshnull 			      "semaphore failed with %d", status);
3976*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_SWFW_SYNC;
3977*dea5f973SBhosale, Yogeshnull 	}
3978*dea5f973SBhosale, Yogeshnull 	ctrl = IXGBE_CTRL_RST;
3979*dea5f973SBhosale, Yogeshnull 	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
3980*dea5f973SBhosale, Yogeshnull 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
3981*dea5f973SBhosale, Yogeshnull 	IXGBE_WRITE_FLUSH(hw);
3982*dea5f973SBhosale, Yogeshnull 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
3983*dea5f973SBhosale, Yogeshnull 
3984*dea5f973SBhosale, Yogeshnull 	/* Poll for reset bit to self-clear indicating reset is complete */
3985*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < 10; i++) {
3986*dea5f973SBhosale, Yogeshnull 		usec_delay(1);
3987*dea5f973SBhosale, Yogeshnull 		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
3988*dea5f973SBhosale, Yogeshnull 		if (!(ctrl & IXGBE_CTRL_RST_MASK))
3989*dea5f973SBhosale, Yogeshnull 			break;
3990*dea5f973SBhosale, Yogeshnull 	}
3991*dea5f973SBhosale, Yogeshnull 
3992*dea5f973SBhosale, Yogeshnull 	if (ctrl & IXGBE_CTRL_RST_MASK) {
3993*dea5f973SBhosale, Yogeshnull 		status = IXGBE_ERR_RESET_FAILED;
3994*dea5f973SBhosale, Yogeshnull 		ERROR_REPORT1(IXGBE_ERROR_POLLING,
3995*dea5f973SBhosale, Yogeshnull 			      "Reset polling failed to complete.\n");
3996*dea5f973SBhosale, Yogeshnull 	}
3997*dea5f973SBhosale, Yogeshnull 	msec_delay(100);
3998*dea5f973SBhosale, Yogeshnull 
3999*dea5f973SBhosale, Yogeshnull 	/*
4000*dea5f973SBhosale, Yogeshnull 	 * Double resets are required for recovery from certain error
4001*dea5f973SBhosale, Yogeshnull 	 * conditions.  Between resets, it is necessary to stall to allow time
4002*dea5f973SBhosale, Yogeshnull 	 * for any pending HW events to complete.
4003*dea5f973SBhosale, Yogeshnull 	 */
4004*dea5f973SBhosale, Yogeshnull 	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
4005*dea5f973SBhosale, Yogeshnull 		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
4006*dea5f973SBhosale, Yogeshnull 		goto mac_reset_top;
4007*dea5f973SBhosale, Yogeshnull 	}
4008*dea5f973SBhosale, Yogeshnull 
4009*dea5f973SBhosale, Yogeshnull 	/* Set the Rx packet buffer size. */
4010*dea5f973SBhosale, Yogeshnull 	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT);
4011*dea5f973SBhosale, Yogeshnull 
4012*dea5f973SBhosale, Yogeshnull 	/* Store the permanent mac address */
4013*dea5f973SBhosale, Yogeshnull 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
4014*dea5f973SBhosale, Yogeshnull 
4015*dea5f973SBhosale, Yogeshnull 	/*
4016*dea5f973SBhosale, Yogeshnull 	 * Store MAC address from RAR0, clear receive address registers, and
4017*dea5f973SBhosale, Yogeshnull 	 * clear the multicast table.  Also reset num_rar_entries to 128,
4018*dea5f973SBhosale, Yogeshnull 	 * since we modify this value when programming the SAN MAC address.
4019*dea5f973SBhosale, Yogeshnull 	 */
4020*dea5f973SBhosale, Yogeshnull 	hw->mac.num_rar_entries = 128;
4021*dea5f973SBhosale, Yogeshnull 	hw->mac.ops.init_rx_addrs(hw);
4022*dea5f973SBhosale, Yogeshnull 
4023*dea5f973SBhosale, Yogeshnull reset_hw_out:
4024*dea5f973SBhosale, Yogeshnull 	return status;
4025*dea5f973SBhosale, Yogeshnull }
4026*dea5f973SBhosale, Yogeshnull 
4027*dea5f973SBhosale, Yogeshnull /**
4028*dea5f973SBhosale, Yogeshnull  * ixgbe_start_hw_E610 - Prepare hardware for Tx/Rx
4029*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4030*dea5f973SBhosale, Yogeshnull  *
4031*dea5f973SBhosale, Yogeshnull  * Gets firmware version and if API version matches it
4032*dea5f973SBhosale, Yogeshnull  * starts the hardware using the generic start_hw function
4033*dea5f973SBhosale, Yogeshnull  * and the generation start_hw function.
4034*dea5f973SBhosale, Yogeshnull  * Then performs revision-specific operations, if any.
4035*dea5f973SBhosale, Yogeshnull  **/
ixgbe_start_hw_E610(struct ixgbe_hw * hw)4036*dea5f973SBhosale, Yogeshnull s32 ixgbe_start_hw_E610(struct ixgbe_hw *hw)
4037*dea5f973SBhosale, Yogeshnull {
4038*dea5f973SBhosale, Yogeshnull 	s32 ret_val = IXGBE_SUCCESS;
4039*dea5f973SBhosale, Yogeshnull 
4040*dea5f973SBhosale, Yogeshnull 	ret_val = hw->mac.ops.get_fw_version(hw);
4041*dea5f973SBhosale, Yogeshnull 	if (ret_val)
4042*dea5f973SBhosale, Yogeshnull 		goto out;
4043*dea5f973SBhosale, Yogeshnull 
4044*dea5f973SBhosale, Yogeshnull 	ret_val = ixgbe_start_hw_generic(hw);
4045*dea5f973SBhosale, Yogeshnull 	if (ret_val != IXGBE_SUCCESS)
4046*dea5f973SBhosale, Yogeshnull 		goto out;
4047*dea5f973SBhosale, Yogeshnull 
4048*dea5f973SBhosale, Yogeshnull 	ixgbe_start_hw_gen2(hw);
4049*dea5f973SBhosale, Yogeshnull 
4050*dea5f973SBhosale, Yogeshnull out:
4051*dea5f973SBhosale, Yogeshnull 	return ret_val;
4052*dea5f973SBhosale, Yogeshnull }
4053*dea5f973SBhosale, Yogeshnull 
4054*dea5f973SBhosale, Yogeshnull /**
4055*dea5f973SBhosale, Yogeshnull  * ixgbe_get_media_type_E610 - Gets media type
4056*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW struct
4057*dea5f973SBhosale, Yogeshnull  *
4058*dea5f973SBhosale, Yogeshnull  * In order to get the media type, the function gets PHY
4059*dea5f973SBhosale, Yogeshnull  * capabilities and later on use them to identify the PHY type
4060*dea5f973SBhosale, Yogeshnull  * checking phy_type_high and phy_type_low.
4061*dea5f973SBhosale, Yogeshnull  *
4062*dea5f973SBhosale, Yogeshnull  * Return: the type of media in form of ixgbe_media_type enum
4063*dea5f973SBhosale, Yogeshnull  * or ixgbe_media_type_unknown in case of an error.
4064*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_media_type_E610(struct ixgbe_hw * hw)4065*dea5f973SBhosale, Yogeshnull enum ixgbe_media_type ixgbe_get_media_type_E610(struct ixgbe_hw *hw)
4066*dea5f973SBhosale, Yogeshnull {
4067*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data pcaps;
4068*dea5f973SBhosale, Yogeshnull 	u64 phy_mask = 0;
4069*dea5f973SBhosale, Yogeshnull 	s32 rc;
4070*dea5f973SBhosale, Yogeshnull 	u8 i;
4071*dea5f973SBhosale, Yogeshnull 
4072*dea5f973SBhosale, Yogeshnull 	rc = ixgbe_update_link_info(hw);
4073*dea5f973SBhosale, Yogeshnull 	if (rc) {
4074*dea5f973SBhosale, Yogeshnull 		return ixgbe_media_type_unknown;
4075*dea5f973SBhosale, Yogeshnull 	}
4076*dea5f973SBhosale, Yogeshnull 
4077*dea5f973SBhosale, Yogeshnull 	/* If there is no link but PHY (dongle) is available SW should use
4078*dea5f973SBhosale, Yogeshnull 	 * Get PHY Caps admin command instead of Get Link Status, find most
4079*dea5f973SBhosale, Yogeshnull 	 * significant bit that is set in PHY types reported by the command
4080*dea5f973SBhosale, Yogeshnull 	 * and use it to discover media type.
4081*dea5f973SBhosale, Yogeshnull 	 */
4082*dea5f973SBhosale, Yogeshnull 	if (!(hw->link.link_info.link_info & IXGBE_ACI_LINK_UP) &&
4083*dea5f973SBhosale, Yogeshnull 	    (hw->link.link_info.link_info & IXGBE_ACI_MEDIA_AVAILABLE)) {
4084*dea5f973SBhosale, Yogeshnull 		/* Get PHY Capabilities */
4085*dea5f973SBhosale, Yogeshnull 		rc = ixgbe_aci_get_phy_caps(hw, false,
4086*dea5f973SBhosale, Yogeshnull 					    IXGBE_ACI_REPORT_TOPO_CAP_MEDIA,
4087*dea5f973SBhosale, Yogeshnull 					    &pcaps);
4088*dea5f973SBhosale, Yogeshnull 		if (rc) {
4089*dea5f973SBhosale, Yogeshnull 			return ixgbe_media_type_unknown;
4090*dea5f973SBhosale, Yogeshnull 		}
4091*dea5f973SBhosale, Yogeshnull 
4092*dea5f973SBhosale, Yogeshnull 		/* Check if there is some bit set in phy_type_high */
4093*dea5f973SBhosale, Yogeshnull 		for (i = 64; i > 0; i--) {
4094*dea5f973SBhosale, Yogeshnull 			phy_mask = (u64)((u64)1 << (i - 1));
4095*dea5f973SBhosale, Yogeshnull 			if ((pcaps.phy_type_high & phy_mask) != 0) {
4096*dea5f973SBhosale, Yogeshnull 				/* If any bit is set treat it as PHY type */
4097*dea5f973SBhosale, Yogeshnull 				hw->link.link_info.phy_type_high = phy_mask;
4098*dea5f973SBhosale, Yogeshnull 				hw->link.link_info.phy_type_low = 0;
4099*dea5f973SBhosale, Yogeshnull 				break;
4100*dea5f973SBhosale, Yogeshnull 			}
4101*dea5f973SBhosale, Yogeshnull 			phy_mask = 0;
4102*dea5f973SBhosale, Yogeshnull 		}
4103*dea5f973SBhosale, Yogeshnull 
4104*dea5f973SBhosale, Yogeshnull 		/* If nothing found in phy_type_high search in phy_type_low */
4105*dea5f973SBhosale, Yogeshnull 		if (phy_mask == 0) {
4106*dea5f973SBhosale, Yogeshnull 			for (i = 64; i > 0; i--) {
4107*dea5f973SBhosale, Yogeshnull 				phy_mask = (u64)((u64)1 << (i - 1));
4108*dea5f973SBhosale, Yogeshnull 				if ((pcaps.phy_type_low & phy_mask) != 0) {
4109*dea5f973SBhosale, Yogeshnull 					/* If any bit is set treat it as PHY type */
4110*dea5f973SBhosale, Yogeshnull 					hw->link.link_info.phy_type_high = 0;
4111*dea5f973SBhosale, Yogeshnull 					hw->link.link_info.phy_type_low = phy_mask;
4112*dea5f973SBhosale, Yogeshnull 					break;
4113*dea5f973SBhosale, Yogeshnull 				}
4114*dea5f973SBhosale, Yogeshnull 			}
4115*dea5f973SBhosale, Yogeshnull 		}
4116*dea5f973SBhosale, Yogeshnull 
4117*dea5f973SBhosale, Yogeshnull 	}
4118*dea5f973SBhosale, Yogeshnull 
4119*dea5f973SBhosale, Yogeshnull 	/* Based on link status or search above try to discover media type */
4120*dea5f973SBhosale, Yogeshnull 	hw->phy.media_type = ixgbe_get_media_type_from_phy_type(hw);
4121*dea5f973SBhosale, Yogeshnull 
4122*dea5f973SBhosale, Yogeshnull 	return hw->phy.media_type;
4123*dea5f973SBhosale, Yogeshnull }
4124*dea5f973SBhosale, Yogeshnull 
4125*dea5f973SBhosale, Yogeshnull /**
4126*dea5f973SBhosale, Yogeshnull  * ixgbe_get_supported_physical_layer_E610 - Returns physical layer type
4127*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4128*dea5f973SBhosale, Yogeshnull  *
4129*dea5f973SBhosale, Yogeshnull  * Determines physical layer capabilities of the current configuration.
4130*dea5f973SBhosale, Yogeshnull  *
4131*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4132*dea5f973SBhosale, Yogeshnull  **/
ixgbe_get_supported_physical_layer_E610(struct ixgbe_hw * hw)4133*dea5f973SBhosale, Yogeshnull u64 ixgbe_get_supported_physical_layer_E610(struct ixgbe_hw *hw)
4134*dea5f973SBhosale, Yogeshnull {
4135*dea5f973SBhosale, Yogeshnull 	u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
4136*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data pcaps;
4137*dea5f973SBhosale, Yogeshnull 	u64 phy_type;
4138*dea5f973SBhosale, Yogeshnull 	s32 rc;
4139*dea5f973SBhosale, Yogeshnull 
4140*dea5f973SBhosale, Yogeshnull 	rc = ixgbe_aci_get_phy_caps(hw, false, IXGBE_ACI_REPORT_TOPO_CAP_MEDIA,
4141*dea5f973SBhosale, Yogeshnull 				    &pcaps);
4142*dea5f973SBhosale, Yogeshnull 	if (rc)
4143*dea5f973SBhosale, Yogeshnull 		return IXGBE_PHYSICAL_LAYER_UNKNOWN;
4144*dea5f973SBhosale, Yogeshnull 
4145*dea5f973SBhosale, Yogeshnull 	phy_type = IXGBE_LE64_TO_CPU(pcaps.phy_type_low);
4146*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_10GBASE_T)
4147*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
4148*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_1000BASE_T)
4149*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
4150*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_100BASE_TX)
4151*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
4152*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_10GBASE_LR)
4153*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_LR;
4154*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_10GBASE_SR)
4155*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_SR;
4156*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_1000BASE_KX)
4157*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
4158*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_10GBASE_KR_CR1)
4159*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR;
4160*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_1000BASE_SX)
4161*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_SX;
4162*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_2500BASE_KX)
4163*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_2500BASE_KX;
4164*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_2500BASE_T)
4165*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_2500BASE_T;
4166*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_LOW_5GBASE_T)
4167*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_5000BASE_T;
4168*dea5f973SBhosale, Yogeshnull 
4169*dea5f973SBhosale, Yogeshnull 	phy_type = IXGBE_LE64_TO_CPU(pcaps.phy_type_high);
4170*dea5f973SBhosale, Yogeshnull 	if(phy_type & IXGBE_PHY_TYPE_HIGH_10BASE_T)
4171*dea5f973SBhosale, Yogeshnull 		physical_layer |= IXGBE_PHYSICAL_LAYER_10BASE_T;
4172*dea5f973SBhosale, Yogeshnull 
4173*dea5f973SBhosale, Yogeshnull 	return physical_layer;
4174*dea5f973SBhosale, Yogeshnull }
4175*dea5f973SBhosale, Yogeshnull 
4176*dea5f973SBhosale, Yogeshnull /**
4177*dea5f973SBhosale, Yogeshnull  * ixgbe_setup_link_E610 - Set up link
4178*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4179*dea5f973SBhosale, Yogeshnull  * @speed: new link speed
4180*dea5f973SBhosale, Yogeshnull  * @autoneg_wait: true when waiting for completion is needed
4181*dea5f973SBhosale, Yogeshnull  *
4182*dea5f973SBhosale, Yogeshnull  * Set up the link with the specified speed.
4183*dea5f973SBhosale, Yogeshnull  *
4184*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4185*dea5f973SBhosale, Yogeshnull  */
ixgbe_setup_link_E610(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait)4186*dea5f973SBhosale, Yogeshnull s32 ixgbe_setup_link_E610(struct ixgbe_hw *hw, ixgbe_link_speed speed,
4187*dea5f973SBhosale, Yogeshnull 			  bool autoneg_wait)
4188*dea5f973SBhosale, Yogeshnull {
4189*dea5f973SBhosale, Yogeshnull 	/* Simply request FW to perform proper PHY setup */
4190*dea5f973SBhosale, Yogeshnull 	return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
4191*dea5f973SBhosale, Yogeshnull }
4192*dea5f973SBhosale, Yogeshnull 
4193*dea5f973SBhosale, Yogeshnull /**
4194*dea5f973SBhosale, Yogeshnull  * ixgbe_check_link_E610 - Determine link and speed status
4195*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4196*dea5f973SBhosale, Yogeshnull  * @speed: pointer to link speed
4197*dea5f973SBhosale, Yogeshnull  * @link_up: true when link is up
4198*dea5f973SBhosale, Yogeshnull  * @link_up_wait_to_complete: bool used to wait for link up or not
4199*dea5f973SBhosale, Yogeshnull  *
4200*dea5f973SBhosale, Yogeshnull  * Determine if the link is up and the current link speed
4201*dea5f973SBhosale, Yogeshnull  * using ACI command (0x0607).
4202*dea5f973SBhosale, Yogeshnull  *
4203*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4204*dea5f973SBhosale, Yogeshnull  */
ixgbe_check_link_E610(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * link_up,bool link_up_wait_to_complete)4205*dea5f973SBhosale, Yogeshnull s32 ixgbe_check_link_E610(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
4206*dea5f973SBhosale, Yogeshnull 			  bool *link_up, bool link_up_wait_to_complete)
4207*dea5f973SBhosale, Yogeshnull {
4208*dea5f973SBhosale, Yogeshnull 	s32 rc;
4209*dea5f973SBhosale, Yogeshnull 	u32 i;
4210*dea5f973SBhosale, Yogeshnull 
4211*dea5f973SBhosale, Yogeshnull 	if (!speed || !link_up)
4212*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
4213*dea5f973SBhosale, Yogeshnull 
4214*dea5f973SBhosale, Yogeshnull 	/* Set get_link_info flag to ensure that fresh
4215*dea5f973SBhosale, Yogeshnull 	 * link information will be obtained from FW
4216*dea5f973SBhosale, Yogeshnull 	 * by sending Get Link Status admin command. */
4217*dea5f973SBhosale, Yogeshnull 	hw->link.get_link_info = true;
4218*dea5f973SBhosale, Yogeshnull 
4219*dea5f973SBhosale, Yogeshnull 	/* Update link information in adapter context. */
4220*dea5f973SBhosale, Yogeshnull 	rc = ixgbe_get_link_status(hw, link_up);
4221*dea5f973SBhosale, Yogeshnull 	if (rc)
4222*dea5f973SBhosale, Yogeshnull 		return rc;
4223*dea5f973SBhosale, Yogeshnull 
4224*dea5f973SBhosale, Yogeshnull 	/* Wait for link up if it was requested. */
4225*dea5f973SBhosale, Yogeshnull 	if (link_up_wait_to_complete && *link_up == false) {
4226*dea5f973SBhosale, Yogeshnull 		for (i = 0; i < hw->mac.max_link_up_time; i++) {
4227*dea5f973SBhosale, Yogeshnull 			msec_delay(100);
4228*dea5f973SBhosale, Yogeshnull 			hw->link.get_link_info = true;
4229*dea5f973SBhosale, Yogeshnull 			rc = ixgbe_get_link_status(hw, link_up);
4230*dea5f973SBhosale, Yogeshnull 			if (rc)
4231*dea5f973SBhosale, Yogeshnull 				return rc;
4232*dea5f973SBhosale, Yogeshnull 			if (*link_up)
4233*dea5f973SBhosale, Yogeshnull 				break;
4234*dea5f973SBhosale, Yogeshnull 		}
4235*dea5f973SBhosale, Yogeshnull 	}
4236*dea5f973SBhosale, Yogeshnull 
4237*dea5f973SBhosale, Yogeshnull 	/* Use link information in adapter context updated by the call
4238*dea5f973SBhosale, Yogeshnull 	 * to ixgbe_get_link_status() to determine current link speed.
4239*dea5f973SBhosale, Yogeshnull 	 * Link speed information is valid only when link up was
4240*dea5f973SBhosale, Yogeshnull 	 * reported by FW. */
4241*dea5f973SBhosale, Yogeshnull 	if (*link_up) {
4242*dea5f973SBhosale, Yogeshnull 		switch (hw->link.link_info.link_speed) {
4243*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_LINK_SPEED_10MB:
4244*dea5f973SBhosale, Yogeshnull 			*speed = IXGBE_LINK_SPEED_10_FULL;
4245*dea5f973SBhosale, Yogeshnull 			break;
4246*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_LINK_SPEED_100MB:
4247*dea5f973SBhosale, Yogeshnull 			*speed = IXGBE_LINK_SPEED_100_FULL;
4248*dea5f973SBhosale, Yogeshnull 			break;
4249*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_LINK_SPEED_1000MB:
4250*dea5f973SBhosale, Yogeshnull 			*speed = IXGBE_LINK_SPEED_1GB_FULL;
4251*dea5f973SBhosale, Yogeshnull 			break;
4252*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_LINK_SPEED_2500MB:
4253*dea5f973SBhosale, Yogeshnull 			*speed = IXGBE_LINK_SPEED_2_5GB_FULL;
4254*dea5f973SBhosale, Yogeshnull 			break;
4255*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_LINK_SPEED_5GB:
4256*dea5f973SBhosale, Yogeshnull 			*speed = IXGBE_LINK_SPEED_5GB_FULL;
4257*dea5f973SBhosale, Yogeshnull 			break;
4258*dea5f973SBhosale, Yogeshnull 		case IXGBE_ACI_LINK_SPEED_10GB:
4259*dea5f973SBhosale, Yogeshnull 			*speed = IXGBE_LINK_SPEED_10GB_FULL;
4260*dea5f973SBhosale, Yogeshnull 			break;
4261*dea5f973SBhosale, Yogeshnull 		default:
4262*dea5f973SBhosale, Yogeshnull 			*speed = IXGBE_LINK_SPEED_UNKNOWN;
4263*dea5f973SBhosale, Yogeshnull 			break;
4264*dea5f973SBhosale, Yogeshnull 		}
4265*dea5f973SBhosale, Yogeshnull 	} else {
4266*dea5f973SBhosale, Yogeshnull 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
4267*dea5f973SBhosale, Yogeshnull 	}
4268*dea5f973SBhosale, Yogeshnull 
4269*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
4270*dea5f973SBhosale, Yogeshnull }
4271*dea5f973SBhosale, Yogeshnull 
4272*dea5f973SBhosale, Yogeshnull /**
4273*dea5f973SBhosale, Yogeshnull  * ixgbe_get_link_capabilities_E610 - Determine link capabilities
4274*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4275*dea5f973SBhosale, Yogeshnull  * @speed: pointer to link speed
4276*dea5f973SBhosale, Yogeshnull  * @autoneg: true when autoneg or autotry is enabled
4277*dea5f973SBhosale, Yogeshnull  *
4278*dea5f973SBhosale, Yogeshnull  * Determine speed and AN parameters of a link.
4279*dea5f973SBhosale, Yogeshnull  *
4280*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4281*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_link_capabilities_E610(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * autoneg)4282*dea5f973SBhosale, Yogeshnull s32 ixgbe_get_link_capabilities_E610(struct ixgbe_hw *hw,
4283*dea5f973SBhosale, Yogeshnull 				     ixgbe_link_speed *speed,
4284*dea5f973SBhosale, Yogeshnull 				     bool *autoneg)
4285*dea5f973SBhosale, Yogeshnull {
4286*dea5f973SBhosale, Yogeshnull 	if (!speed || !autoneg)
4287*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
4288*dea5f973SBhosale, Yogeshnull 
4289*dea5f973SBhosale, Yogeshnull 	*autoneg = true;
4290*dea5f973SBhosale, Yogeshnull 	*speed = hw->phy.speeds_supported;
4291*dea5f973SBhosale, Yogeshnull 
4292*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
4293*dea5f973SBhosale, Yogeshnull }
4294*dea5f973SBhosale, Yogeshnull 
4295*dea5f973SBhosale, Yogeshnull /**
4296*dea5f973SBhosale, Yogeshnull  * ixgbe_cfg_phy_fc - Configure PHY Flow Control (FC) data based on FC mode
4297*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4298*dea5f973SBhosale, Yogeshnull  * @cfg: PHY configuration data to set FC mode
4299*dea5f973SBhosale, Yogeshnull  * @req_mode: FC mode to configure
4300*dea5f973SBhosale, Yogeshnull  *
4301*dea5f973SBhosale, Yogeshnull  * Configures PHY Flow Control according to the provided configuration.
4302*dea5f973SBhosale, Yogeshnull  *
4303*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4304*dea5f973SBhosale, Yogeshnull  */
ixgbe_cfg_phy_fc(struct ixgbe_hw * hw,struct ixgbe_aci_cmd_set_phy_cfg_data * cfg,enum ixgbe_fc_mode req_mode)4305*dea5f973SBhosale, Yogeshnull s32 ixgbe_cfg_phy_fc(struct ixgbe_hw *hw,
4306*dea5f973SBhosale, Yogeshnull 		     struct ixgbe_aci_cmd_set_phy_cfg_data *cfg,
4307*dea5f973SBhosale, Yogeshnull 		     enum ixgbe_fc_mode req_mode)
4308*dea5f973SBhosale, Yogeshnull {
4309*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data* pcaps = NULL;
4310*dea5f973SBhosale, Yogeshnull 	s32 status = IXGBE_SUCCESS;
4311*dea5f973SBhosale, Yogeshnull 	u8 pause_mask = 0x0;
4312*dea5f973SBhosale, Yogeshnull 
4313*dea5f973SBhosale, Yogeshnull 	if (!cfg)
4314*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
4315*dea5f973SBhosale, Yogeshnull 
4316*dea5f973SBhosale, Yogeshnull 	switch (req_mode) {
4317*dea5f973SBhosale, Yogeshnull 	case ixgbe_fc_auto:
4318*dea5f973SBhosale, Yogeshnull 	{
4319*dea5f973SBhosale, Yogeshnull 		pcaps = (struct ixgbe_aci_cmd_get_phy_caps_data *)
4320*dea5f973SBhosale, Yogeshnull 			ixgbe_malloc(hw, sizeof(*pcaps));
4321*dea5f973SBhosale, Yogeshnull 		if (!pcaps) {
4322*dea5f973SBhosale, Yogeshnull 			status = IXGBE_ERR_OUT_OF_MEM;
4323*dea5f973SBhosale, Yogeshnull 			goto out;
4324*dea5f973SBhosale, Yogeshnull 		}
4325*dea5f973SBhosale, Yogeshnull 
4326*dea5f973SBhosale, Yogeshnull 		/* Query the value of FC that both the NIC and the attached
4327*dea5f973SBhosale, Yogeshnull 		 * media can do. */
4328*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_get_phy_caps(hw, false,
4329*dea5f973SBhosale, Yogeshnull 			IXGBE_ACI_REPORT_TOPO_CAP_MEDIA, pcaps);
4330*dea5f973SBhosale, Yogeshnull 		if (status)
4331*dea5f973SBhosale, Yogeshnull 			goto out;
4332*dea5f973SBhosale, Yogeshnull 
4333*dea5f973SBhosale, Yogeshnull 		pause_mask |= pcaps->caps & IXGBE_ACI_PHY_EN_TX_LINK_PAUSE;
4334*dea5f973SBhosale, Yogeshnull 		pause_mask |= pcaps->caps & IXGBE_ACI_PHY_EN_RX_LINK_PAUSE;
4335*dea5f973SBhosale, Yogeshnull 
4336*dea5f973SBhosale, Yogeshnull 		break;
4337*dea5f973SBhosale, Yogeshnull 	}
4338*dea5f973SBhosale, Yogeshnull 	case ixgbe_fc_full:
4339*dea5f973SBhosale, Yogeshnull 		pause_mask |= IXGBE_ACI_PHY_EN_TX_LINK_PAUSE;
4340*dea5f973SBhosale, Yogeshnull 		pause_mask |= IXGBE_ACI_PHY_EN_RX_LINK_PAUSE;
4341*dea5f973SBhosale, Yogeshnull 		break;
4342*dea5f973SBhosale, Yogeshnull 	case ixgbe_fc_rx_pause:
4343*dea5f973SBhosale, Yogeshnull 		pause_mask |= IXGBE_ACI_PHY_EN_RX_LINK_PAUSE;
4344*dea5f973SBhosale, Yogeshnull 		break;
4345*dea5f973SBhosale, Yogeshnull 	case ixgbe_fc_tx_pause:
4346*dea5f973SBhosale, Yogeshnull 		pause_mask |= IXGBE_ACI_PHY_EN_TX_LINK_PAUSE;
4347*dea5f973SBhosale, Yogeshnull 		break;
4348*dea5f973SBhosale, Yogeshnull 	default:
4349*dea5f973SBhosale, Yogeshnull 		break;
4350*dea5f973SBhosale, Yogeshnull 	}
4351*dea5f973SBhosale, Yogeshnull 
4352*dea5f973SBhosale, Yogeshnull 	/* clear the old pause settings */
4353*dea5f973SBhosale, Yogeshnull 	cfg->caps &= ~(IXGBE_ACI_PHY_EN_TX_LINK_PAUSE |
4354*dea5f973SBhosale, Yogeshnull 		IXGBE_ACI_PHY_EN_RX_LINK_PAUSE);
4355*dea5f973SBhosale, Yogeshnull 
4356*dea5f973SBhosale, Yogeshnull 	/* set the new capabilities */
4357*dea5f973SBhosale, Yogeshnull 	cfg->caps |= pause_mask;
4358*dea5f973SBhosale, Yogeshnull 
4359*dea5f973SBhosale, Yogeshnull out:
4360*dea5f973SBhosale, Yogeshnull 	if (pcaps)
4361*dea5f973SBhosale, Yogeshnull 		ixgbe_free(hw, pcaps);
4362*dea5f973SBhosale, Yogeshnull 	return status;
4363*dea5f973SBhosale, Yogeshnull }
4364*dea5f973SBhosale, Yogeshnull 
4365*dea5f973SBhosale, Yogeshnull /**
4366*dea5f973SBhosale, Yogeshnull  * ixgbe_setup_fc_E610 - Set up flow control
4367*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4368*dea5f973SBhosale, Yogeshnull  *
4369*dea5f973SBhosale, Yogeshnull  * Set up flow control. This has to be done during init time.
4370*dea5f973SBhosale, Yogeshnull  *
4371*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4372*dea5f973SBhosale, Yogeshnull  */
ixgbe_setup_fc_E610(struct ixgbe_hw * hw)4373*dea5f973SBhosale, Yogeshnull s32 ixgbe_setup_fc_E610(struct ixgbe_hw *hw)
4374*dea5f973SBhosale, Yogeshnull {
4375*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data pcaps = { 0 };
4376*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_set_phy_cfg_data cfg = { 0 };
4377*dea5f973SBhosale, Yogeshnull 	s32 status;
4378*dea5f973SBhosale, Yogeshnull 
4379*dea5f973SBhosale, Yogeshnull 	/* Get the current PHY config */
4380*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_get_phy_caps(hw, false,
4381*dea5f973SBhosale, Yogeshnull 		IXGBE_ACI_REPORT_ACTIVE_CFG, &pcaps);
4382*dea5f973SBhosale, Yogeshnull 	if (status)
4383*dea5f973SBhosale, Yogeshnull 		return status;
4384*dea5f973SBhosale, Yogeshnull 
4385*dea5f973SBhosale, Yogeshnull 	ixgbe_copy_phy_caps_to_cfg(&pcaps, &cfg);
4386*dea5f973SBhosale, Yogeshnull 
4387*dea5f973SBhosale, Yogeshnull 	/* Configure the set PHY data */
4388*dea5f973SBhosale, Yogeshnull 	status = ixgbe_cfg_phy_fc(hw, &cfg, hw->fc.requested_mode);
4389*dea5f973SBhosale, Yogeshnull 	if (status)
4390*dea5f973SBhosale, Yogeshnull 		return status;
4391*dea5f973SBhosale, Yogeshnull 
4392*dea5f973SBhosale, Yogeshnull 	/* If the capabilities have changed, then set the new config */
4393*dea5f973SBhosale, Yogeshnull 	if (cfg.caps != pcaps.caps) {
4394*dea5f973SBhosale, Yogeshnull 		cfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
4395*dea5f973SBhosale, Yogeshnull 
4396*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_set_phy_cfg(hw, &cfg);
4397*dea5f973SBhosale, Yogeshnull 		if (status)
4398*dea5f973SBhosale, Yogeshnull 			return status;
4399*dea5f973SBhosale, Yogeshnull 	}
4400*dea5f973SBhosale, Yogeshnull 
4401*dea5f973SBhosale, Yogeshnull 	return status;
4402*dea5f973SBhosale, Yogeshnull }
4403*dea5f973SBhosale, Yogeshnull 
4404*dea5f973SBhosale, Yogeshnull /**
4405*dea5f973SBhosale, Yogeshnull  * ixgbe_fc_autoneg_E610 - Configure flow control
4406*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4407*dea5f973SBhosale, Yogeshnull  *
4408*dea5f973SBhosale, Yogeshnull  * Configure Flow Control.
4409*dea5f973SBhosale, Yogeshnull  */
ixgbe_fc_autoneg_E610(struct ixgbe_hw * hw)4410*dea5f973SBhosale, Yogeshnull void ixgbe_fc_autoneg_E610(struct ixgbe_hw *hw)
4411*dea5f973SBhosale, Yogeshnull {
4412*dea5f973SBhosale, Yogeshnull 	s32 status;
4413*dea5f973SBhosale, Yogeshnull 
4414*dea5f973SBhosale, Yogeshnull 	/* Get current link status.
4415*dea5f973SBhosale, Yogeshnull 	 * Current FC mode will be stored in the hw context. */
4416*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_get_link_info(hw, false, NULL);
4417*dea5f973SBhosale, Yogeshnull 	if (status) {
4418*dea5f973SBhosale, Yogeshnull 		goto out;
4419*dea5f973SBhosale, Yogeshnull 	}
4420*dea5f973SBhosale, Yogeshnull 
4421*dea5f973SBhosale, Yogeshnull 	/* Check if the link is up */
4422*dea5f973SBhosale, Yogeshnull 	if (!(hw->link.link_info.link_info & IXGBE_ACI_LINK_UP)) {
4423*dea5f973SBhosale, Yogeshnull 		status = IXGBE_ERR_FC_NOT_NEGOTIATED;
4424*dea5f973SBhosale, Yogeshnull 		goto out;
4425*dea5f973SBhosale, Yogeshnull 	}
4426*dea5f973SBhosale, Yogeshnull 
4427*dea5f973SBhosale, Yogeshnull 	/* Check if auto-negotiation has completed */
4428*dea5f973SBhosale, Yogeshnull 	if (!(hw->link.link_info.an_info & IXGBE_ACI_AN_COMPLETED)) {
4429*dea5f973SBhosale, Yogeshnull 		status = IXGBE_ERR_FC_NOT_NEGOTIATED;
4430*dea5f973SBhosale, Yogeshnull 		goto out;
4431*dea5f973SBhosale, Yogeshnull 	}
4432*dea5f973SBhosale, Yogeshnull 
4433*dea5f973SBhosale, Yogeshnull out:
4434*dea5f973SBhosale, Yogeshnull 	if (status == IXGBE_SUCCESS) {
4435*dea5f973SBhosale, Yogeshnull 		hw->fc.fc_was_autonegged = true;
4436*dea5f973SBhosale, Yogeshnull 	} else {
4437*dea5f973SBhosale, Yogeshnull 		hw->fc.fc_was_autonegged = false;
4438*dea5f973SBhosale, Yogeshnull 		hw->fc.current_mode = hw->fc.requested_mode;
4439*dea5f973SBhosale, Yogeshnull 	}
4440*dea5f973SBhosale, Yogeshnull }
4441*dea5f973SBhosale, Yogeshnull 
4442*dea5f973SBhosale, Yogeshnull /**
4443*dea5f973SBhosale, Yogeshnull  * ixgbe_set_fw_drv_ver_E610 - Send driver version to FW
4444*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
4445*dea5f973SBhosale, Yogeshnull  * @maj: driver version major number
4446*dea5f973SBhosale, Yogeshnull  * @minor: driver version minor number
4447*dea5f973SBhosale, Yogeshnull  * @build: driver version build number
4448*dea5f973SBhosale, Yogeshnull  * @sub: driver version sub build number
4449*dea5f973SBhosale, Yogeshnull  * @len: length of driver_ver string
4450*dea5f973SBhosale, Yogeshnull  * @driver_ver: driver string
4451*dea5f973SBhosale, Yogeshnull  *
4452*dea5f973SBhosale, Yogeshnull  * Send driver version number to Firmware using ACI command (0x0002).
4453*dea5f973SBhosale, Yogeshnull  *
4454*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4455*dea5f973SBhosale, Yogeshnull  * IXGBE_SUCCESS - OK
4456*dea5f973SBhosale, Yogeshnull  * IXGBE_ERR_PARAM - incorrect parameters were given
4457*dea5f973SBhosale, Yogeshnull  * IXGBE_ERR_ACI_ERROR - encountered an error during sending the command
4458*dea5f973SBhosale, Yogeshnull  * IXGBE_ERR_ACI_TIMEOUT - a timeout occurred
4459*dea5f973SBhosale, Yogeshnull  * IXGBE_ERR_OUT_OF_MEM - ran out of memory
4460*dea5f973SBhosale, Yogeshnull  */
ixgbe_set_fw_drv_ver_E610(struct ixgbe_hw * hw,u8 maj,u8 minor,u8 build,u8 sub,u16 len,const char * driver_ver)4461*dea5f973SBhosale, Yogeshnull s32 ixgbe_set_fw_drv_ver_E610(struct ixgbe_hw *hw, u8 maj, u8 minor, u8 build,
4462*dea5f973SBhosale, Yogeshnull 			      u8 sub, u16 len, const char *driver_ver)
4463*dea5f973SBhosale, Yogeshnull {
4464*dea5f973SBhosale, Yogeshnull 	size_t limited_len = min(len, (u16)IXGBE_DRV_VER_STR_LEN_E610);
4465*dea5f973SBhosale, Yogeshnull 	struct ixgbe_driver_ver dv;
4466*dea5f973SBhosale, Yogeshnull 
4467*dea5f973SBhosale, Yogeshnull 	DEBUGFUNC("ixgbe_set_fw_drv_ver_E610");
4468*dea5f973SBhosale, Yogeshnull 
4469*dea5f973SBhosale, Yogeshnull 	if (!len || !driver_ver)
4470*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
4471*dea5f973SBhosale, Yogeshnull 
4472*dea5f973SBhosale, Yogeshnull 	dv.major_ver = maj;
4473*dea5f973SBhosale, Yogeshnull 	dv.minor_ver = minor;
4474*dea5f973SBhosale, Yogeshnull 	dv.build_ver = build;
4475*dea5f973SBhosale, Yogeshnull 	dv.subbuild_ver = sub;
4476*dea5f973SBhosale, Yogeshnull 
4477*dea5f973SBhosale, Yogeshnull 	memset(dv.driver_string, 0, IXGBE_DRV_VER_STR_LEN_E610);
4478*dea5f973SBhosale, Yogeshnull 	memcpy(dv.driver_string, driver_ver, limited_len);
4479*dea5f973SBhosale, Yogeshnull 
4480*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_send_driver_ver(hw, &dv);
4481*dea5f973SBhosale, Yogeshnull }
4482*dea5f973SBhosale, Yogeshnull 
4483*dea5f973SBhosale, Yogeshnull /**
4484*dea5f973SBhosale, Yogeshnull  * ixgbe_disable_rx_E610 - Disable RX unit
4485*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4486*dea5f973SBhosale, Yogeshnull  *
4487*dea5f973SBhosale, Yogeshnull  * Disable RX DMA unit on E610 with use of ACI command (0x000C).
4488*dea5f973SBhosale, Yogeshnull  *
4489*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4490*dea5f973SBhosale, Yogeshnull  */
ixgbe_disable_rx_E610(struct ixgbe_hw * hw)4491*dea5f973SBhosale, Yogeshnull void ixgbe_disable_rx_E610(struct ixgbe_hw *hw)
4492*dea5f973SBhosale, Yogeshnull {
4493*dea5f973SBhosale, Yogeshnull 	u32 rxctrl;
4494*dea5f973SBhosale, Yogeshnull 
4495*dea5f973SBhosale, Yogeshnull 	DEBUGFUNC("ixgbe_disable_rx_E610");
4496*dea5f973SBhosale, Yogeshnull 
4497*dea5f973SBhosale, Yogeshnull 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
4498*dea5f973SBhosale, Yogeshnull 	if (rxctrl & IXGBE_RXCTRL_RXEN) {
4499*dea5f973SBhosale, Yogeshnull 		u32 pfdtxgswc;
4500*dea5f973SBhosale, Yogeshnull 		s32 status;
4501*dea5f973SBhosale, Yogeshnull 
4502*dea5f973SBhosale, Yogeshnull 		pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
4503*dea5f973SBhosale, Yogeshnull 		if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
4504*dea5f973SBhosale, Yogeshnull 			pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
4505*dea5f973SBhosale, Yogeshnull 			IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
4506*dea5f973SBhosale, Yogeshnull 			hw->mac.set_lben = true;
4507*dea5f973SBhosale, Yogeshnull 		} else {
4508*dea5f973SBhosale, Yogeshnull 			hw->mac.set_lben = false;
4509*dea5f973SBhosale, Yogeshnull 		}
4510*dea5f973SBhosale, Yogeshnull 
4511*dea5f973SBhosale, Yogeshnull 		status = ixgbe_aci_disable_rxen(hw);
4512*dea5f973SBhosale, Yogeshnull 
4513*dea5f973SBhosale, Yogeshnull 		/* If we fail - disable RX using register write */
4514*dea5f973SBhosale, Yogeshnull 		if (status) {
4515*dea5f973SBhosale, Yogeshnull 			rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
4516*dea5f973SBhosale, Yogeshnull 			if (rxctrl & IXGBE_RXCTRL_RXEN) {
4517*dea5f973SBhosale, Yogeshnull 				rxctrl &= ~IXGBE_RXCTRL_RXEN;
4518*dea5f973SBhosale, Yogeshnull 				IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
4519*dea5f973SBhosale, Yogeshnull 			}
4520*dea5f973SBhosale, Yogeshnull 		}
4521*dea5f973SBhosale, Yogeshnull 	}
4522*dea5f973SBhosale, Yogeshnull }
4523*dea5f973SBhosale, Yogeshnull 
4524*dea5f973SBhosale, Yogeshnull /**
4525*dea5f973SBhosale, Yogeshnull  * ixgbe_setup_eee_E610 - Enable/disable EEE support
4526*dea5f973SBhosale, Yogeshnull  * @hw: pointer to the HW structure
4527*dea5f973SBhosale, Yogeshnull  * @enable_eee: boolean flag to enable EEE
4528*dea5f973SBhosale, Yogeshnull  *
4529*dea5f973SBhosale, Yogeshnull  * Enables/disable EEE based on enable_eee flag.
4530*dea5f973SBhosale, Yogeshnull  *
4531*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4532*dea5f973SBhosale, Yogeshnull  */
ixgbe_setup_eee_E610(struct ixgbe_hw * hw,bool enable_eee)4533*dea5f973SBhosale, Yogeshnull s32 ixgbe_setup_eee_E610(struct ixgbe_hw *hw, bool enable_eee)
4534*dea5f973SBhosale, Yogeshnull {
4535*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data phy_caps = { 0 };
4536*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_set_phy_cfg_data phy_cfg = { 0 };
4537*dea5f973SBhosale, Yogeshnull 	u16 eee_cap = 0;
4538*dea5f973SBhosale, Yogeshnull 	s32 status;
4539*dea5f973SBhosale, Yogeshnull 
4540*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_get_phy_caps(hw, false,
4541*dea5f973SBhosale, Yogeshnull 		IXGBE_ACI_REPORT_ACTIVE_CFG, &phy_caps);
4542*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS)
4543*dea5f973SBhosale, Yogeshnull 		return status;
4544*dea5f973SBhosale, Yogeshnull 
4545*dea5f973SBhosale, Yogeshnull 	ixgbe_copy_phy_caps_to_cfg(&phy_caps, &phy_cfg);
4546*dea5f973SBhosale, Yogeshnull 
4547*dea5f973SBhosale, Yogeshnull 	phy_cfg.caps |= IXGBE_ACI_PHY_ENA_LINK;
4548*dea5f973SBhosale, Yogeshnull 	phy_cfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
4549*dea5f973SBhosale, Yogeshnull 
4550*dea5f973SBhosale, Yogeshnull 	if (enable_eee) {
4551*dea5f973SBhosale, Yogeshnull 		if (phy_caps.phy_type_low & IXGBE_PHY_TYPE_LOW_100BASE_TX)
4552*dea5f973SBhosale, Yogeshnull 			eee_cap |= IXGBE_ACI_PHY_EEE_EN_100BASE_TX;
4553*dea5f973SBhosale, Yogeshnull 		if (phy_caps.phy_type_low & IXGBE_PHY_TYPE_LOW_1000BASE_T)
4554*dea5f973SBhosale, Yogeshnull 			eee_cap |= IXGBE_ACI_PHY_EEE_EN_1000BASE_T;
4555*dea5f973SBhosale, Yogeshnull 		if (phy_caps.phy_type_low & IXGBE_PHY_TYPE_LOW_1000BASE_KX)
4556*dea5f973SBhosale, Yogeshnull 			eee_cap |= IXGBE_ACI_PHY_EEE_EN_1000BASE_KX;
4557*dea5f973SBhosale, Yogeshnull 		if (phy_caps.phy_type_low & IXGBE_PHY_TYPE_LOW_10GBASE_T)
4558*dea5f973SBhosale, Yogeshnull 			eee_cap |= IXGBE_ACI_PHY_EEE_EN_10GBASE_T;
4559*dea5f973SBhosale, Yogeshnull 		if (phy_caps.phy_type_low & IXGBE_PHY_TYPE_LOW_10GBASE_KR_CR1)
4560*dea5f973SBhosale, Yogeshnull 			eee_cap |= IXGBE_ACI_PHY_EEE_EN_10GBASE_KR;
4561*dea5f973SBhosale, Yogeshnull 		if (phy_caps.phy_type_high & IXGBE_PHY_TYPE_HIGH_10BASE_T)
4562*dea5f973SBhosale, Yogeshnull 			eee_cap |= IXGBE_ACI_PHY_EEE_EN_10BASE_T;
4563*dea5f973SBhosale, Yogeshnull 	}
4564*dea5f973SBhosale, Yogeshnull 
4565*dea5f973SBhosale, Yogeshnull 	/* Set EEE capability for particular PHY types */
4566*dea5f973SBhosale, Yogeshnull 	phy_cfg.eee_cap = IXGBE_CPU_TO_LE16(eee_cap);
4567*dea5f973SBhosale, Yogeshnull 
4568*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_set_phy_cfg(hw, &phy_cfg);
4569*dea5f973SBhosale, Yogeshnull 
4570*dea5f973SBhosale, Yogeshnull 	return status;
4571*dea5f973SBhosale, Yogeshnull }
4572*dea5f973SBhosale, Yogeshnull 
4573*dea5f973SBhosale, Yogeshnull /**
4574*dea5f973SBhosale, Yogeshnull  * ixgbe_fw_recovery_mode_E610 - Check FW NVM recovery mode
4575*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4576*dea5f973SBhosale, Yogeshnull  *
4577*dea5f973SBhosale, Yogeshnull  * Checks FW NVM recovery mode by
4578*dea5f973SBhosale, Yogeshnull  * reading the value of the dedicated register.
4579*dea5f973SBhosale, Yogeshnull  *
4580*dea5f973SBhosale, Yogeshnull  * Return: true if FW is in recovery mode, otherwise false.
4581*dea5f973SBhosale, Yogeshnull  */
ixgbe_fw_recovery_mode_E610(struct ixgbe_hw * hw)4582*dea5f973SBhosale, Yogeshnull bool ixgbe_fw_recovery_mode_E610(struct ixgbe_hw *hw)
4583*dea5f973SBhosale, Yogeshnull {
4584*dea5f973SBhosale, Yogeshnull 	u32 fwsm = IXGBE_READ_REG(hw, GL_MNG_FWSM);
4585*dea5f973SBhosale, Yogeshnull 
4586*dea5f973SBhosale, Yogeshnull 	return !!(fwsm & GL_MNG_FWSM_FW_MODES_RECOVERY_M);
4587*dea5f973SBhosale, Yogeshnull }
4588*dea5f973SBhosale, Yogeshnull 
4589*dea5f973SBhosale, Yogeshnull /**
4590*dea5f973SBhosale, Yogeshnull  * ixgbe_fw_rollback_mode_E610 - Check FW NVM Rollback
4591*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4592*dea5f973SBhosale, Yogeshnull  *
4593*dea5f973SBhosale, Yogeshnull  * Checks FW NVM Rollback mode by reading the
4594*dea5f973SBhosale, Yogeshnull  * value of the dedicated register.
4595*dea5f973SBhosale, Yogeshnull  *
4596*dea5f973SBhosale, Yogeshnull  * Return: true if FW is in Rollback mode, otherwise false.
4597*dea5f973SBhosale, Yogeshnull  */
ixgbe_fw_rollback_mode_E610(struct ixgbe_hw * hw)4598*dea5f973SBhosale, Yogeshnull bool ixgbe_fw_rollback_mode_E610(struct ixgbe_hw *hw)
4599*dea5f973SBhosale, Yogeshnull {
4600*dea5f973SBhosale, Yogeshnull 	u32 fwsm = IXGBE_READ_REG(hw, GL_MNG_FWSM);
4601*dea5f973SBhosale, Yogeshnull 
4602*dea5f973SBhosale, Yogeshnull 	return !!(fwsm & GL_MNG_FWSM_FW_MODES_ROLLBACK_M);
4603*dea5f973SBhosale, Yogeshnull }
4604*dea5f973SBhosale, Yogeshnull 
4605*dea5f973SBhosale, Yogeshnull /**
4606*dea5f973SBhosale, Yogeshnull  * ixgbe_get_fw_tsam_mode_E610 - Check FW NVM Thermal Sensor Autonomous Mode
4607*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4608*dea5f973SBhosale, Yogeshnull  *
4609*dea5f973SBhosale, Yogeshnull  * Checks Thermal Sensor Autonomous Mode by reading the
4610*dea5f973SBhosale, Yogeshnull  * value of the dedicated register.
4611*dea5f973SBhosale, Yogeshnull  *
4612*dea5f973SBhosale, Yogeshnull  * Return: true if FW is in TSAM, otherwise false.
4613*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_fw_tsam_mode_E610(struct ixgbe_hw * hw)4614*dea5f973SBhosale, Yogeshnull bool ixgbe_get_fw_tsam_mode_E610(struct ixgbe_hw *hw)
4615*dea5f973SBhosale, Yogeshnull {
4616*dea5f973SBhosale, Yogeshnull 	u32 fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_X550EM_a);
4617*dea5f973SBhosale, Yogeshnull 
4618*dea5f973SBhosale, Yogeshnull 	return !!(fwsm & IXGBE_FWSM_TS_ENABLED);
4619*dea5f973SBhosale, Yogeshnull }
4620*dea5f973SBhosale, Yogeshnull 
4621*dea5f973SBhosale, Yogeshnull /**
4622*dea5f973SBhosale, Yogeshnull  * ixgbe_init_phy_ops_E610 - PHY specific init
4623*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4624*dea5f973SBhosale, Yogeshnull  *
4625*dea5f973SBhosale, Yogeshnull  * Initialize any function pointers that were not able to be
4626*dea5f973SBhosale, Yogeshnull  * set during init_shared_code because the PHY type was not known.
4627*dea5f973SBhosale, Yogeshnull  *
4628*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4629*dea5f973SBhosale, Yogeshnull  */
ixgbe_init_phy_ops_E610(struct ixgbe_hw * hw)4630*dea5f973SBhosale, Yogeshnull s32 ixgbe_init_phy_ops_E610(struct ixgbe_hw *hw)
4631*dea5f973SBhosale, Yogeshnull {
4632*dea5f973SBhosale, Yogeshnull 	struct ixgbe_mac_info *mac = &hw->mac;
4633*dea5f973SBhosale, Yogeshnull 	struct ixgbe_phy_info *phy = &hw->phy;
4634*dea5f973SBhosale, Yogeshnull 	s32 ret_val;
4635*dea5f973SBhosale, Yogeshnull 
4636*dea5f973SBhosale, Yogeshnull 	phy->ops.identify_sfp = ixgbe_identify_module_E610;
4637*dea5f973SBhosale, Yogeshnull 	phy->ops.read_reg = NULL; /* PHY reg access is not required */
4638*dea5f973SBhosale, Yogeshnull 	phy->ops.write_reg = NULL;
4639*dea5f973SBhosale, Yogeshnull 	phy->ops.read_reg_mdi = NULL;
4640*dea5f973SBhosale, Yogeshnull 	phy->ops.write_reg_mdi = NULL;
4641*dea5f973SBhosale, Yogeshnull 	phy->ops.setup_link = ixgbe_setup_phy_link_E610;
4642*dea5f973SBhosale, Yogeshnull 	phy->ops.get_firmware_version = ixgbe_get_phy_firmware_version_E610;
4643*dea5f973SBhosale, Yogeshnull 	phy->ops.read_i2c_byte = NULL; /* disabled for E610 */
4644*dea5f973SBhosale, Yogeshnull 	phy->ops.write_i2c_byte = NULL; /* disabled for E610 */
4645*dea5f973SBhosale, Yogeshnull 	phy->ops.read_i2c_sff8472 = ixgbe_read_i2c_sff8472_E610;
4646*dea5f973SBhosale, Yogeshnull 	phy->ops.read_i2c_eeprom = ixgbe_read_i2c_eeprom_E610;
4647*dea5f973SBhosale, Yogeshnull 	phy->ops.write_i2c_eeprom = ixgbe_write_i2c_eeprom_E610;
4648*dea5f973SBhosale, Yogeshnull 	phy->ops.i2c_bus_clear = NULL; /* do not use generic implementation  */
4649*dea5f973SBhosale, Yogeshnull 	phy->ops.check_overtemp = ixgbe_check_overtemp_E610;
4650*dea5f973SBhosale, Yogeshnull 	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper)
4651*dea5f973SBhosale, Yogeshnull 		phy->ops.set_phy_power = ixgbe_set_phy_power_E610;
4652*dea5f973SBhosale, Yogeshnull 	else
4653*dea5f973SBhosale, Yogeshnull 		phy->ops.set_phy_power = NULL;
4654*dea5f973SBhosale, Yogeshnull 	phy->ops.enter_lplu = ixgbe_enter_lplu_E610;
4655*dea5f973SBhosale, Yogeshnull 	phy->ops.handle_lasi = NULL; /* no implementation for E610 */
4656*dea5f973SBhosale, Yogeshnull 	phy->ops.read_i2c_byte_unlocked = NULL; /* disabled for E610 */
4657*dea5f973SBhosale, Yogeshnull 	phy->ops.write_i2c_byte_unlocked = NULL; /* disabled for E610 */
4658*dea5f973SBhosale, Yogeshnull 
4659*dea5f973SBhosale, Yogeshnull 	/* TODO: Set functions pointers based on device ID */
4660*dea5f973SBhosale, Yogeshnull 
4661*dea5f973SBhosale, Yogeshnull 	/* Identify the PHY */
4662*dea5f973SBhosale, Yogeshnull 	ret_val = phy->ops.identify(hw);
4663*dea5f973SBhosale, Yogeshnull 	if (ret_val != IXGBE_SUCCESS)
4664*dea5f973SBhosale, Yogeshnull 		return ret_val;
4665*dea5f973SBhosale, Yogeshnull 
4666*dea5f973SBhosale, Yogeshnull 	/* TODO: Set functions pointers based on PHY type */
4667*dea5f973SBhosale, Yogeshnull 
4668*dea5f973SBhosale, Yogeshnull 	return ret_val;
4669*dea5f973SBhosale, Yogeshnull }
4670*dea5f973SBhosale, Yogeshnull 
4671*dea5f973SBhosale, Yogeshnull /**
4672*dea5f973SBhosale, Yogeshnull  * ixgbe_identify_phy_E610 - Identify PHY
4673*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4674*dea5f973SBhosale, Yogeshnull  *
4675*dea5f973SBhosale, Yogeshnull  * Determine PHY type, supported speeds and PHY ID.
4676*dea5f973SBhosale, Yogeshnull  *
4677*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4678*dea5f973SBhosale, Yogeshnull  */
ixgbe_identify_phy_E610(struct ixgbe_hw * hw)4679*dea5f973SBhosale, Yogeshnull s32 ixgbe_identify_phy_E610(struct ixgbe_hw *hw)
4680*dea5f973SBhosale, Yogeshnull {
4681*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data pcaps;
4682*dea5f973SBhosale, Yogeshnull 	s32 rc;
4683*dea5f973SBhosale, Yogeshnull 
4684*dea5f973SBhosale, Yogeshnull 	/* Set PHY type */
4685*dea5f973SBhosale, Yogeshnull 	hw->phy.type = ixgbe_phy_fw;
4686*dea5f973SBhosale, Yogeshnull 
4687*dea5f973SBhosale, Yogeshnull 	rc = ixgbe_aci_get_phy_caps(hw, false, IXGBE_ACI_REPORT_TOPO_CAP_MEDIA,
4688*dea5f973SBhosale, Yogeshnull 				    &pcaps);
4689*dea5f973SBhosale, Yogeshnull 	if (rc)
4690*dea5f973SBhosale, Yogeshnull 		return rc;
4691*dea5f973SBhosale, Yogeshnull 
4692*dea5f973SBhosale, Yogeshnull 	if (!(pcaps.module_compliance_enforcement &
4693*dea5f973SBhosale, Yogeshnull 	      IXGBE_ACI_MOD_ENFORCE_STRICT_MODE)) {
4694*dea5f973SBhosale, Yogeshnull 		/* Handle lenient mode */
4695*dea5f973SBhosale, Yogeshnull 		rc = ixgbe_aci_get_phy_caps(hw, false,
4696*dea5f973SBhosale, Yogeshnull 					    IXGBE_ACI_REPORT_TOPO_CAP_NO_MEDIA,
4697*dea5f973SBhosale, Yogeshnull 					    &pcaps);
4698*dea5f973SBhosale, Yogeshnull 		if (rc)
4699*dea5f973SBhosale, Yogeshnull 			return rc;
4700*dea5f973SBhosale, Yogeshnull 	}
4701*dea5f973SBhosale, Yogeshnull 
4702*dea5f973SBhosale, Yogeshnull 	/* Determine supported speeds */
4703*dea5f973SBhosale, Yogeshnull 	hw->phy.speeds_supported = IXGBE_LINK_SPEED_UNKNOWN;
4704*dea5f973SBhosale, Yogeshnull 
4705*dea5f973SBhosale, Yogeshnull 	if (pcaps.phy_type_high & IXGBE_PHY_TYPE_HIGH_10BASE_T ||
4706*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_high & IXGBE_PHY_TYPE_HIGH_10M_SGMII)
4707*dea5f973SBhosale, Yogeshnull 		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10_FULL;
4708*dea5f973SBhosale, Yogeshnull 	if (pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_100BASE_TX ||
4709*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_100M_SGMII ||
4710*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_high & IXGBE_PHY_TYPE_HIGH_100M_USXGMII)
4711*dea5f973SBhosale, Yogeshnull 		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_100_FULL;
4712*dea5f973SBhosale, Yogeshnull 	if (pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_1000BASE_T  ||
4713*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_1000BASE_SX ||
4714*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_1000BASE_LX ||
4715*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_1000BASE_KX ||
4716*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_1G_SGMII    ||
4717*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_high & IXGBE_PHY_TYPE_HIGH_1G_USXGMII)
4718*dea5f973SBhosale, Yogeshnull 		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_1GB_FULL;
4719*dea5f973SBhosale, Yogeshnull 	if (pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_10GBASE_T       ||
4720*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_10G_SFI_DA      ||
4721*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_10GBASE_SR      ||
4722*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_10GBASE_LR      ||
4723*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_10GBASE_KR_CR1  ||
4724*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_10G_SFI_AOC_ACC ||
4725*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_10G_SFI_C2C     ||
4726*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_high & IXGBE_PHY_TYPE_HIGH_10G_USXGMII)
4727*dea5f973SBhosale, Yogeshnull 		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10GB_FULL;
4728*dea5f973SBhosale, Yogeshnull 
4729*dea5f973SBhosale, Yogeshnull 	/* 2.5 and 5 Gbps link speeds must be excluded from the
4730*dea5f973SBhosale, Yogeshnull 	 * auto-negotiation set used during driver initialization due to
4731*dea5f973SBhosale, Yogeshnull 	 * compatibility issues with certain switches. Those issues do not
4732*dea5f973SBhosale, Yogeshnull 	 * exist in case of E610 2.5G SKU device (0x57b1).
4733*dea5f973SBhosale, Yogeshnull 	 */
4734*dea5f973SBhosale, Yogeshnull 	if (!hw->phy.autoneg_advertised &&
4735*dea5f973SBhosale, Yogeshnull 	    hw->device_id != IXGBE_DEV_ID_E610_2_5G_T)
4736*dea5f973SBhosale, Yogeshnull 		hw->phy.autoneg_advertised = hw->phy.speeds_supported;
4737*dea5f973SBhosale, Yogeshnull 
4738*dea5f973SBhosale, Yogeshnull 	if (pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_2500BASE_T   ||
4739*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_2500BASE_X   ||
4740*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_2500BASE_KX  ||
4741*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_high & IXGBE_PHY_TYPE_HIGH_2500M_SGMII ||
4742*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_high & IXGBE_PHY_TYPE_HIGH_2500M_USXGMII)
4743*dea5f973SBhosale, Yogeshnull 		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL;
4744*dea5f973SBhosale, Yogeshnull 
4745*dea5f973SBhosale, Yogeshnull 	if (!hw->phy.autoneg_advertised &&
4746*dea5f973SBhosale, Yogeshnull 	    hw->device_id == IXGBE_DEV_ID_E610_2_5G_T)
4747*dea5f973SBhosale, Yogeshnull 		hw->phy.autoneg_advertised = hw->phy.speeds_supported;
4748*dea5f973SBhosale, Yogeshnull 
4749*dea5f973SBhosale, Yogeshnull 	if (pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_5GBASE_T  ||
4750*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_low  & IXGBE_PHY_TYPE_LOW_5GBASE_KR ||
4751*dea5f973SBhosale, Yogeshnull 	    pcaps.phy_type_high & IXGBE_PHY_TYPE_HIGH_5G_USXGMII)
4752*dea5f973SBhosale, Yogeshnull 		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
4753*dea5f973SBhosale, Yogeshnull 
4754*dea5f973SBhosale, Yogeshnull 	/* Set PHY ID */
4755*dea5f973SBhosale, Yogeshnull 	memcpy(&hw->phy.id, pcaps.phy_id_oui, sizeof(u32));
4756*dea5f973SBhosale, Yogeshnull 
4757*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
4758*dea5f973SBhosale, Yogeshnull }
4759*dea5f973SBhosale, Yogeshnull 
4760*dea5f973SBhosale, Yogeshnull /**
4761*dea5f973SBhosale, Yogeshnull  * ixgbe_identify_module_E610 - Identify SFP module type
4762*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4763*dea5f973SBhosale, Yogeshnull  *
4764*dea5f973SBhosale, Yogeshnull  * Identify the SFP module type.
4765*dea5f973SBhosale, Yogeshnull  *
4766*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4767*dea5f973SBhosale, Yogeshnull  */
ixgbe_identify_module_E610(struct ixgbe_hw * hw)4768*dea5f973SBhosale, Yogeshnull s32 ixgbe_identify_module_E610(struct ixgbe_hw *hw)
4769*dea5f973SBhosale, Yogeshnull {
4770*dea5f973SBhosale, Yogeshnull 	bool media_available;
4771*dea5f973SBhosale, Yogeshnull 	u8 module_type;
4772*dea5f973SBhosale, Yogeshnull 	s32 rc;
4773*dea5f973SBhosale, Yogeshnull 
4774*dea5f973SBhosale, Yogeshnull 	rc = ixgbe_update_link_info(hw);
4775*dea5f973SBhosale, Yogeshnull 	if (rc)
4776*dea5f973SBhosale, Yogeshnull 		goto err;
4777*dea5f973SBhosale, Yogeshnull 
4778*dea5f973SBhosale, Yogeshnull 	media_available =
4779*dea5f973SBhosale, Yogeshnull 		(hw->link.link_info.link_info &
4780*dea5f973SBhosale, Yogeshnull 		 IXGBE_ACI_MEDIA_AVAILABLE) ? true : false;
4781*dea5f973SBhosale, Yogeshnull 
4782*dea5f973SBhosale, Yogeshnull 	if (media_available) {
4783*dea5f973SBhosale, Yogeshnull 		hw->phy.sfp_type = ixgbe_sfp_type_unknown;
4784*dea5f973SBhosale, Yogeshnull 
4785*dea5f973SBhosale, Yogeshnull 		/* Get module type from hw context updated by ixgbe_update_link_info() */
4786*dea5f973SBhosale, Yogeshnull 		module_type = hw->link.link_info.module_type[IXGBE_ACI_MOD_TYPE_IDENT];
4787*dea5f973SBhosale, Yogeshnull 
4788*dea5f973SBhosale, Yogeshnull 		if ((module_type & IXGBE_ACI_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE) ||
4789*dea5f973SBhosale, Yogeshnull 		    (module_type & IXGBE_ACI_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE)) {
4790*dea5f973SBhosale, Yogeshnull 			hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
4791*dea5f973SBhosale, Yogeshnull 		} else if (module_type & IXGBE_ACI_MOD_TYPE_BYTE1_10G_BASE_SR) {
4792*dea5f973SBhosale, Yogeshnull 			hw->phy.sfp_type = ixgbe_sfp_type_sr;
4793*dea5f973SBhosale, Yogeshnull 		} else if ((module_type & IXGBE_ACI_MOD_TYPE_BYTE1_10G_BASE_LR) ||
4794*dea5f973SBhosale, Yogeshnull 			   (module_type & IXGBE_ACI_MOD_TYPE_BYTE1_10G_BASE_LRM)) {
4795*dea5f973SBhosale, Yogeshnull 			hw->phy.sfp_type = ixgbe_sfp_type_lr;
4796*dea5f973SBhosale, Yogeshnull 		}
4797*dea5f973SBhosale, Yogeshnull 		rc = IXGBE_SUCCESS;
4798*dea5f973SBhosale, Yogeshnull 	} else {
4799*dea5f973SBhosale, Yogeshnull 		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
4800*dea5f973SBhosale, Yogeshnull 		rc = IXGBE_ERR_SFP_NOT_PRESENT;
4801*dea5f973SBhosale, Yogeshnull 	}
4802*dea5f973SBhosale, Yogeshnull err:
4803*dea5f973SBhosale, Yogeshnull 	return rc;
4804*dea5f973SBhosale, Yogeshnull }
4805*dea5f973SBhosale, Yogeshnull 
4806*dea5f973SBhosale, Yogeshnull /**
4807*dea5f973SBhosale, Yogeshnull  * ixgbe_setup_phy_link_E610 - Sets up firmware-controlled PHYs
4808*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4809*dea5f973SBhosale, Yogeshnull  *
4810*dea5f973SBhosale, Yogeshnull  * Set the parameters for the firmware-controlled PHYs.
4811*dea5f973SBhosale, Yogeshnull  *
4812*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4813*dea5f973SBhosale, Yogeshnull  */
ixgbe_setup_phy_link_E610(struct ixgbe_hw * hw)4814*dea5f973SBhosale, Yogeshnull s32 ixgbe_setup_phy_link_E610(struct ixgbe_hw *hw)
4815*dea5f973SBhosale, Yogeshnull {
4816*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data pcaps;
4817*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_set_phy_cfg_data pcfg;
4818*dea5f973SBhosale, Yogeshnull 	u8 rmode = IXGBE_ACI_REPORT_TOPO_CAP_MEDIA;
4819*dea5f973SBhosale, Yogeshnull 	u64 sup_phy_type_low, sup_phy_type_high;
4820*dea5f973SBhosale, Yogeshnull 	s32 rc;
4821*dea5f973SBhosale, Yogeshnull 
4822*dea5f973SBhosale, Yogeshnull 	rc = ixgbe_aci_get_link_info(hw, false, NULL);
4823*dea5f973SBhosale, Yogeshnull 	if (rc) {
4824*dea5f973SBhosale, Yogeshnull 		goto err;
4825*dea5f973SBhosale, Yogeshnull 	}
4826*dea5f973SBhosale, Yogeshnull 
4827*dea5f973SBhosale, Yogeshnull 	/* If media is not available get default config */
4828*dea5f973SBhosale, Yogeshnull 	if (!(hw->link.link_info.link_info & IXGBE_ACI_MEDIA_AVAILABLE))
4829*dea5f973SBhosale, Yogeshnull 		rmode = IXGBE_ACI_REPORT_DFLT_CFG;
4830*dea5f973SBhosale, Yogeshnull 
4831*dea5f973SBhosale, Yogeshnull 	rc = ixgbe_aci_get_phy_caps(hw, false, rmode, &pcaps);
4832*dea5f973SBhosale, Yogeshnull 	if (rc) {
4833*dea5f973SBhosale, Yogeshnull 		goto err;
4834*dea5f973SBhosale, Yogeshnull 	}
4835*dea5f973SBhosale, Yogeshnull 
4836*dea5f973SBhosale, Yogeshnull 	sup_phy_type_low = pcaps.phy_type_low;
4837*dea5f973SBhosale, Yogeshnull 	sup_phy_type_high = pcaps.phy_type_high;
4838*dea5f973SBhosale, Yogeshnull 
4839*dea5f973SBhosale, Yogeshnull 	/* Get Active configuration to avoid unintended changes */
4840*dea5f973SBhosale, Yogeshnull 	rc = ixgbe_aci_get_phy_caps(hw, false, IXGBE_ACI_REPORT_ACTIVE_CFG,
4841*dea5f973SBhosale, Yogeshnull 				    &pcaps);
4842*dea5f973SBhosale, Yogeshnull 	if (rc) {
4843*dea5f973SBhosale, Yogeshnull 		goto err;
4844*dea5f973SBhosale, Yogeshnull 	}
4845*dea5f973SBhosale, Yogeshnull 	ixgbe_copy_phy_caps_to_cfg(&pcaps, &pcfg);
4846*dea5f973SBhosale, Yogeshnull 
4847*dea5f973SBhosale, Yogeshnull 	/* Set default PHY types for a given speed */
4848*dea5f973SBhosale, Yogeshnull 	pcfg.phy_type_low = 0;
4849*dea5f973SBhosale, Yogeshnull 	pcfg.phy_type_high = 0;
4850*dea5f973SBhosale, Yogeshnull 
4851*dea5f973SBhosale, Yogeshnull 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10_FULL) {
4852*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_high |= IXGBE_PHY_TYPE_HIGH_10BASE_T;
4853*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_high |= IXGBE_PHY_TYPE_HIGH_10M_SGMII;
4854*dea5f973SBhosale, Yogeshnull 	}
4855*dea5f973SBhosale, Yogeshnull 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) {
4856*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_100BASE_TX;
4857*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_100M_SGMII;
4858*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_high |= IXGBE_PHY_TYPE_HIGH_100M_USXGMII;
4859*dea5f973SBhosale, Yogeshnull 	}
4860*dea5f973SBhosale, Yogeshnull 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) {
4861*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_1000BASE_T;
4862*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_1000BASE_SX;
4863*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_1000BASE_LX;
4864*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_1000BASE_KX;
4865*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_1G_SGMII;
4866*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_high |= IXGBE_PHY_TYPE_HIGH_1G_USXGMII;
4867*dea5f973SBhosale, Yogeshnull 	}
4868*dea5f973SBhosale, Yogeshnull 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) {
4869*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_2500BASE_T;
4870*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_2500BASE_X;
4871*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_2500BASE_KX;
4872*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_high |= IXGBE_PHY_TYPE_HIGH_2500M_SGMII;
4873*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_high |= IXGBE_PHY_TYPE_HIGH_2500M_USXGMII;
4874*dea5f973SBhosale, Yogeshnull 	}
4875*dea5f973SBhosale, Yogeshnull 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) {
4876*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_5GBASE_T;
4877*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_5GBASE_KR;
4878*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_high |= IXGBE_PHY_TYPE_HIGH_5G_USXGMII;
4879*dea5f973SBhosale, Yogeshnull 	}
4880*dea5f973SBhosale, Yogeshnull 	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) {
4881*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_10GBASE_T;
4882*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_10G_SFI_DA;
4883*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_10GBASE_SR;
4884*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_10GBASE_LR;
4885*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_10GBASE_KR_CR1;
4886*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_10G_SFI_AOC_ACC;
4887*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_low  |= IXGBE_PHY_TYPE_LOW_10G_SFI_C2C;
4888*dea5f973SBhosale, Yogeshnull 		pcfg.phy_type_high |= IXGBE_PHY_TYPE_HIGH_10G_USXGMII;
4889*dea5f973SBhosale, Yogeshnull 	}
4890*dea5f973SBhosale, Yogeshnull 
4891*dea5f973SBhosale, Yogeshnull 	/* Mask the set values to avoid requesting unsupported link types */
4892*dea5f973SBhosale, Yogeshnull 	pcfg.phy_type_low &= sup_phy_type_low;
4893*dea5f973SBhosale, Yogeshnull 	pcfg.phy_type_high &= sup_phy_type_high;
4894*dea5f973SBhosale, Yogeshnull 
4895*dea5f973SBhosale, Yogeshnull 	if (pcfg.phy_type_high != pcaps.phy_type_high ||
4896*dea5f973SBhosale, Yogeshnull 	    pcfg.phy_type_low != pcaps.phy_type_low ||
4897*dea5f973SBhosale, Yogeshnull 	    pcfg.caps != pcaps.caps) {
4898*dea5f973SBhosale, Yogeshnull 		pcfg.caps |= IXGBE_ACI_PHY_ENA_LINK;
4899*dea5f973SBhosale, Yogeshnull 		pcfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
4900*dea5f973SBhosale, Yogeshnull 
4901*dea5f973SBhosale, Yogeshnull 		rc = ixgbe_aci_set_phy_cfg(hw, &pcfg);
4902*dea5f973SBhosale, Yogeshnull 	}
4903*dea5f973SBhosale, Yogeshnull 
4904*dea5f973SBhosale, Yogeshnull err:
4905*dea5f973SBhosale, Yogeshnull 	return rc;
4906*dea5f973SBhosale, Yogeshnull }
4907*dea5f973SBhosale, Yogeshnull 
4908*dea5f973SBhosale, Yogeshnull /**
4909*dea5f973SBhosale, Yogeshnull  * ixgbe_get_phy_firmware_version_E610 - Gets the PHY Firmware Version
4910*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4911*dea5f973SBhosale, Yogeshnull  * @firmware_version: pointer to the PHY Firmware Version
4912*dea5f973SBhosale, Yogeshnull  *
4913*dea5f973SBhosale, Yogeshnull  * Determines PHY FW version based on response to Get PHY Capabilities
4914*dea5f973SBhosale, Yogeshnull  * admin command (0x0600).
4915*dea5f973SBhosale, Yogeshnull  *
4916*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4917*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_phy_firmware_version_E610(struct ixgbe_hw * hw,u16 * firmware_version)4918*dea5f973SBhosale, Yogeshnull s32 ixgbe_get_phy_firmware_version_E610(struct ixgbe_hw *hw,
4919*dea5f973SBhosale, Yogeshnull 					u16 *firmware_version)
4920*dea5f973SBhosale, Yogeshnull {
4921*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data pcaps;
4922*dea5f973SBhosale, Yogeshnull 	s32 status;
4923*dea5f973SBhosale, Yogeshnull 
4924*dea5f973SBhosale, Yogeshnull 	if (!firmware_version)
4925*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
4926*dea5f973SBhosale, Yogeshnull 
4927*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_get_phy_caps(hw, false,
4928*dea5f973SBhosale, Yogeshnull 					IXGBE_ACI_REPORT_ACTIVE_CFG,
4929*dea5f973SBhosale, Yogeshnull 					&pcaps);
4930*dea5f973SBhosale, Yogeshnull 	if (status)
4931*dea5f973SBhosale, Yogeshnull 		return status;
4932*dea5f973SBhosale, Yogeshnull 
4933*dea5f973SBhosale, Yogeshnull 	/* TODO: determine which bytes of the 8-byte phy_fw_ver
4934*dea5f973SBhosale, Yogeshnull 	 * field should be written to the 2-byte firmware_version
4935*dea5f973SBhosale, Yogeshnull 	 * output argument. */
4936*dea5f973SBhosale, Yogeshnull 	memcpy(firmware_version, pcaps.phy_fw_ver, sizeof(u16));
4937*dea5f973SBhosale, Yogeshnull 
4938*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
4939*dea5f973SBhosale, Yogeshnull }
4940*dea5f973SBhosale, Yogeshnull 
4941*dea5f973SBhosale, Yogeshnull /**
4942*dea5f973SBhosale, Yogeshnull  * ixgbe_read_i2c_sff8472_E610 - Reads 8 bit word over I2C interface
4943*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4944*dea5f973SBhosale, Yogeshnull  * @byte_offset: byte offset at address 0xA2
4945*dea5f973SBhosale, Yogeshnull  * @sff8472_data: value read
4946*dea5f973SBhosale, Yogeshnull  *
4947*dea5f973SBhosale, Yogeshnull  * Performs byte read operation from SFP module's SFF-8472 data over I2C.
4948*dea5f973SBhosale, Yogeshnull  *
4949*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4950*dea5f973SBhosale, Yogeshnull  **/
ixgbe_read_i2c_sff8472_E610(struct ixgbe_hw * hw,u8 byte_offset,u8 * sff8472_data)4951*dea5f973SBhosale, Yogeshnull s32 ixgbe_read_i2c_sff8472_E610(struct ixgbe_hw *hw, u8 byte_offset,
4952*dea5f973SBhosale, Yogeshnull 				u8 *sff8472_data)
4953*dea5f973SBhosale, Yogeshnull {
4954*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_sff_eeprom(hw, 0, IXGBE_I2C_EEPROM_DEV_ADDR2,
4955*dea5f973SBhosale, Yogeshnull 				    byte_offset, 0,
4956*dea5f973SBhosale, Yogeshnull 				    IXGBE_ACI_SFF_NO_PAGE_BANK_UPDATE,
4957*dea5f973SBhosale, Yogeshnull 				    sff8472_data, 1, false);
4958*dea5f973SBhosale, Yogeshnull }
4959*dea5f973SBhosale, Yogeshnull 
4960*dea5f973SBhosale, Yogeshnull /**
4961*dea5f973SBhosale, Yogeshnull  * ixgbe_read_i2c_eeprom_E610 - Reads 8 bit EEPROM word over I2C interface
4962*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4963*dea5f973SBhosale, Yogeshnull  * @byte_offset: EEPROM byte offset to read
4964*dea5f973SBhosale, Yogeshnull  * @eeprom_data: value read
4965*dea5f973SBhosale, Yogeshnull  *
4966*dea5f973SBhosale, Yogeshnull  * Performs byte read operation from SFP module's EEPROM over I2C interface.
4967*dea5f973SBhosale, Yogeshnull  *
4968*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4969*dea5f973SBhosale, Yogeshnull  **/
ixgbe_read_i2c_eeprom_E610(struct ixgbe_hw * hw,u8 byte_offset,u8 * eeprom_data)4970*dea5f973SBhosale, Yogeshnull s32 ixgbe_read_i2c_eeprom_E610(struct ixgbe_hw *hw, u8 byte_offset,
4971*dea5f973SBhosale, Yogeshnull 			       u8 *eeprom_data)
4972*dea5f973SBhosale, Yogeshnull {
4973*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_sff_eeprom(hw, 0, IXGBE_I2C_EEPROM_DEV_ADDR,
4974*dea5f973SBhosale, Yogeshnull 				    byte_offset, 0,
4975*dea5f973SBhosale, Yogeshnull 				    IXGBE_ACI_SFF_NO_PAGE_BANK_UPDATE,
4976*dea5f973SBhosale, Yogeshnull 				    eeprom_data, 1, false);
4977*dea5f973SBhosale, Yogeshnull }
4978*dea5f973SBhosale, Yogeshnull 
4979*dea5f973SBhosale, Yogeshnull /**
4980*dea5f973SBhosale, Yogeshnull  * ixgbe_write_i2c_eeprom_E610 - Writes 8 bit EEPROM word over I2C interface
4981*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
4982*dea5f973SBhosale, Yogeshnull  * @byte_offset: EEPROM byte offset to write
4983*dea5f973SBhosale, Yogeshnull  * @eeprom_data: value to write
4984*dea5f973SBhosale, Yogeshnull  *
4985*dea5f973SBhosale, Yogeshnull  * Performs byte write operation to SFP module's EEPROM over I2C interface.
4986*dea5f973SBhosale, Yogeshnull  *
4987*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
4988*dea5f973SBhosale, Yogeshnull  **/
ixgbe_write_i2c_eeprom_E610(struct ixgbe_hw * hw,u8 byte_offset,u8 eeprom_data)4989*dea5f973SBhosale, Yogeshnull s32 ixgbe_write_i2c_eeprom_E610(struct ixgbe_hw *hw, u8 byte_offset,
4990*dea5f973SBhosale, Yogeshnull 				u8 eeprom_data)
4991*dea5f973SBhosale, Yogeshnull {
4992*dea5f973SBhosale, Yogeshnull 	return ixgbe_aci_sff_eeprom(hw, 0, IXGBE_I2C_EEPROM_DEV_ADDR,
4993*dea5f973SBhosale, Yogeshnull 				    byte_offset, 0,
4994*dea5f973SBhosale, Yogeshnull 				    IXGBE_ACI_SFF_NO_PAGE_BANK_UPDATE,
4995*dea5f973SBhosale, Yogeshnull 				    &eeprom_data, 1, true);
4996*dea5f973SBhosale, Yogeshnull }
4997*dea5f973SBhosale, Yogeshnull 
4998*dea5f973SBhosale, Yogeshnull /**
4999*dea5f973SBhosale, Yogeshnull  * ixgbe_check_overtemp_E610 - Check firmware-controlled PHYs for overtemp
5000*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5001*dea5f973SBhosale, Yogeshnull  *
5002*dea5f973SBhosale, Yogeshnull  * Get the link status and check if the PHY temperature alarm detected.
5003*dea5f973SBhosale, Yogeshnull  *
5004*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5005*dea5f973SBhosale, Yogeshnull  */
ixgbe_check_overtemp_E610(struct ixgbe_hw * hw)5006*dea5f973SBhosale, Yogeshnull s32 ixgbe_check_overtemp_E610(struct ixgbe_hw *hw)
5007*dea5f973SBhosale, Yogeshnull {
5008*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_link_status_data link_data = { 0 };
5009*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_link_status *resp;
5010*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_desc desc;
5011*dea5f973SBhosale, Yogeshnull 	s32 status = IXGBE_SUCCESS;
5012*dea5f973SBhosale, Yogeshnull 
5013*dea5f973SBhosale, Yogeshnull 	if (!hw)
5014*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
5015*dea5f973SBhosale, Yogeshnull 
5016*dea5f973SBhosale, Yogeshnull 	ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_link_status);
5017*dea5f973SBhosale, Yogeshnull 	resp = &desc.params.get_link_status;
5018*dea5f973SBhosale, Yogeshnull 	resp->cmd_flags = IXGBE_CPU_TO_LE16(IXGBE_ACI_LSE_NOP);
5019*dea5f973SBhosale, Yogeshnull 
5020*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_send_cmd(hw, &desc, &link_data, sizeof(link_data));
5021*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS)
5022*dea5f973SBhosale, Yogeshnull 		return status;
5023*dea5f973SBhosale, Yogeshnull 
5024*dea5f973SBhosale, Yogeshnull 	if (link_data.ext_info & IXGBE_ACI_LINK_PHY_TEMP_ALARM) {
5025*dea5f973SBhosale, Yogeshnull 		ERROR_REPORT1(IXGBE_ERROR_CAUTION,
5026*dea5f973SBhosale, Yogeshnull 			      "PHY Temperature Alarm detected");
5027*dea5f973SBhosale, Yogeshnull 		status = IXGBE_ERR_OVERTEMP;
5028*dea5f973SBhosale, Yogeshnull 	}
5029*dea5f973SBhosale, Yogeshnull 
5030*dea5f973SBhosale, Yogeshnull 	return status;
5031*dea5f973SBhosale, Yogeshnull }
5032*dea5f973SBhosale, Yogeshnull 
5033*dea5f973SBhosale, Yogeshnull /**
5034*dea5f973SBhosale, Yogeshnull  * ixgbe_set_phy_power_E610 - Control power for copper PHY
5035*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5036*dea5f973SBhosale, Yogeshnull  * @on: true for on, false for off
5037*dea5f973SBhosale, Yogeshnull  *
5038*dea5f973SBhosale, Yogeshnull  * Set the power on/off of the PHY
5039*dea5f973SBhosale, Yogeshnull  * by getting its capabilities and setting the appropriate
5040*dea5f973SBhosale, Yogeshnull  * configuration parameters.
5041*dea5f973SBhosale, Yogeshnull  *
5042*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5043*dea5f973SBhosale, Yogeshnull  */
ixgbe_set_phy_power_E610(struct ixgbe_hw * hw,bool on)5044*dea5f973SBhosale, Yogeshnull s32 ixgbe_set_phy_power_E610(struct ixgbe_hw *hw, bool on)
5045*dea5f973SBhosale, Yogeshnull {
5046*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data phy_caps = { 0 };
5047*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_set_phy_cfg_data phy_cfg = { 0 };
5048*dea5f973SBhosale, Yogeshnull 	s32 status;
5049*dea5f973SBhosale, Yogeshnull 
5050*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_get_phy_caps(hw, false,
5051*dea5f973SBhosale, Yogeshnull 		IXGBE_ACI_REPORT_ACTIVE_CFG, &phy_caps);
5052*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS)
5053*dea5f973SBhosale, Yogeshnull 		return status;
5054*dea5f973SBhosale, Yogeshnull 
5055*dea5f973SBhosale, Yogeshnull 	ixgbe_copy_phy_caps_to_cfg(&phy_caps, &phy_cfg);
5056*dea5f973SBhosale, Yogeshnull 
5057*dea5f973SBhosale, Yogeshnull 	if (on) {
5058*dea5f973SBhosale, Yogeshnull 		phy_cfg.caps &= ~IXGBE_ACI_PHY_ENA_LOW_POWER;
5059*dea5f973SBhosale, Yogeshnull 	} else {
5060*dea5f973SBhosale, Yogeshnull 		phy_cfg.caps |= IXGBE_ACI_PHY_ENA_LOW_POWER;
5061*dea5f973SBhosale, Yogeshnull 	}
5062*dea5f973SBhosale, Yogeshnull 
5063*dea5f973SBhosale, Yogeshnull 	/* PHY is already in requested power mode */
5064*dea5f973SBhosale, Yogeshnull 	if (phy_caps.caps == phy_cfg.caps)
5065*dea5f973SBhosale, Yogeshnull 		return IXGBE_SUCCESS;
5066*dea5f973SBhosale, Yogeshnull 
5067*dea5f973SBhosale, Yogeshnull 	phy_cfg.caps |= IXGBE_ACI_PHY_ENA_LINK;
5068*dea5f973SBhosale, Yogeshnull 	phy_cfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
5069*dea5f973SBhosale, Yogeshnull 
5070*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_set_phy_cfg(hw, &phy_cfg);
5071*dea5f973SBhosale, Yogeshnull 
5072*dea5f973SBhosale, Yogeshnull 	return status;
5073*dea5f973SBhosale, Yogeshnull }
5074*dea5f973SBhosale, Yogeshnull 
5075*dea5f973SBhosale, Yogeshnull /**
5076*dea5f973SBhosale, Yogeshnull  * ixgbe_enter_lplu_E610 - Transition to low power states
5077*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5078*dea5f973SBhosale, Yogeshnull  *
5079*dea5f973SBhosale, Yogeshnull  * Configures Low Power Link Up on transition to low power states
5080*dea5f973SBhosale, Yogeshnull  * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting the
5081*dea5f973SBhosale, Yogeshnull  * X557 PHY immediately prior to entering LPLU.
5082*dea5f973SBhosale, Yogeshnull  *
5083*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5084*dea5f973SBhosale, Yogeshnull  */
ixgbe_enter_lplu_E610(struct ixgbe_hw * hw)5085*dea5f973SBhosale, Yogeshnull s32 ixgbe_enter_lplu_E610(struct ixgbe_hw *hw)
5086*dea5f973SBhosale, Yogeshnull {
5087*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_get_phy_caps_data phy_caps = { 0 };
5088*dea5f973SBhosale, Yogeshnull 	struct ixgbe_aci_cmd_set_phy_cfg_data phy_cfg = { 0 };
5089*dea5f973SBhosale, Yogeshnull 	s32 status;
5090*dea5f973SBhosale, Yogeshnull 
5091*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_get_phy_caps(hw, false,
5092*dea5f973SBhosale, Yogeshnull 		IXGBE_ACI_REPORT_ACTIVE_CFG, &phy_caps);
5093*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS)
5094*dea5f973SBhosale, Yogeshnull 		return status;
5095*dea5f973SBhosale, Yogeshnull 
5096*dea5f973SBhosale, Yogeshnull 	ixgbe_copy_phy_caps_to_cfg(&phy_caps, &phy_cfg);
5097*dea5f973SBhosale, Yogeshnull 
5098*dea5f973SBhosale, Yogeshnull 	phy_cfg.low_power_ctrl_an |= IXGBE_ACI_PHY_EN_D3COLD_LOW_POWER_AUTONEG;
5099*dea5f973SBhosale, Yogeshnull 
5100*dea5f973SBhosale, Yogeshnull 	status = ixgbe_aci_set_phy_cfg(hw, &phy_cfg);
5101*dea5f973SBhosale, Yogeshnull 
5102*dea5f973SBhosale, Yogeshnull 	return status;
5103*dea5f973SBhosale, Yogeshnull }
5104*dea5f973SBhosale, Yogeshnull 
5105*dea5f973SBhosale, Yogeshnull /**
5106*dea5f973SBhosale, Yogeshnull  * ixgbe_init_eeprom_params_E610 - Initialize EEPROM params
5107*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5108*dea5f973SBhosale, Yogeshnull  *
5109*dea5f973SBhosale, Yogeshnull  * Initializes the EEPROM parameters ixgbe_eeprom_info within the
5110*dea5f973SBhosale, Yogeshnull  * ixgbe_hw struct in order to set up EEPROM access.
5111*dea5f973SBhosale, Yogeshnull  *
5112*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5113*dea5f973SBhosale, Yogeshnull  */
ixgbe_init_eeprom_params_E610(struct ixgbe_hw * hw)5114*dea5f973SBhosale, Yogeshnull s32 ixgbe_init_eeprom_params_E610(struct ixgbe_hw *hw)
5115*dea5f973SBhosale, Yogeshnull {
5116*dea5f973SBhosale, Yogeshnull 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
5117*dea5f973SBhosale, Yogeshnull 	u32 gens_stat;
5118*dea5f973SBhosale, Yogeshnull 	u8 sr_size;
5119*dea5f973SBhosale, Yogeshnull 
5120*dea5f973SBhosale, Yogeshnull 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
5121*dea5f973SBhosale, Yogeshnull 		eeprom->type = ixgbe_flash;
5122*dea5f973SBhosale, Yogeshnull 
5123*dea5f973SBhosale, Yogeshnull 		gens_stat = IXGBE_READ_REG(hw, GLNVM_GENS);
5124*dea5f973SBhosale, Yogeshnull 		sr_size = (gens_stat & GLNVM_GENS_SR_SIZE_M) >>
5125*dea5f973SBhosale, Yogeshnull 			  GLNVM_GENS_SR_SIZE_S;
5126*dea5f973SBhosale, Yogeshnull 
5127*dea5f973SBhosale, Yogeshnull 		/* Switching to words (sr_size contains power of 2) */
5128*dea5f973SBhosale, Yogeshnull 		eeprom->word_size = BIT(sr_size) * IXGBE_SR_WORDS_IN_1KB;
5129*dea5f973SBhosale, Yogeshnull 
5130*dea5f973SBhosale, Yogeshnull 		DEBUGOUT2("Eeprom params: type = %d, size = %d\n",
5131*dea5f973SBhosale, Yogeshnull 			  eeprom->type, eeprom->word_size);
5132*dea5f973SBhosale, Yogeshnull 	}
5133*dea5f973SBhosale, Yogeshnull 
5134*dea5f973SBhosale, Yogeshnull 	return IXGBE_SUCCESS;
5135*dea5f973SBhosale, Yogeshnull }
5136*dea5f973SBhosale, Yogeshnull 
5137*dea5f973SBhosale, Yogeshnull /**
5138*dea5f973SBhosale, Yogeshnull  * ixgbe_read_ee_aci_E610 - Read EEPROM word using the admin command.
5139*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5140*dea5f973SBhosale, Yogeshnull  * @offset: offset of  word in the EEPROM to read
5141*dea5f973SBhosale, Yogeshnull  * @data: word read from the EEPROM
5142*dea5f973SBhosale, Yogeshnull  *
5143*dea5f973SBhosale, Yogeshnull  * Reads a 16 bit word from the EEPROM using the ACI.
5144*dea5f973SBhosale, Yogeshnull  * If the EEPROM params are not initialized, the function
5145*dea5f973SBhosale, Yogeshnull  * initialize them before proceeding with reading.
5146*dea5f973SBhosale, Yogeshnull  * The function acquires and then releases the NVM ownership.
5147*dea5f973SBhosale, Yogeshnull  *
5148*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5149*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_ee_aci_E610(struct ixgbe_hw * hw,u16 offset,u16 * data)5150*dea5f973SBhosale, Yogeshnull s32 ixgbe_read_ee_aci_E610(struct ixgbe_hw *hw, u16 offset, u16 *data)
5151*dea5f973SBhosale, Yogeshnull {
5152*dea5f973SBhosale, Yogeshnull 	s32 status;
5153*dea5f973SBhosale, Yogeshnull 
5154*dea5f973SBhosale, Yogeshnull 	if (hw->eeprom.type == ixgbe_eeprom_uninitialized) {
5155*dea5f973SBhosale, Yogeshnull 		status = ixgbe_init_eeprom_params(hw);
5156*dea5f973SBhosale, Yogeshnull 		if (status)
5157*dea5f973SBhosale, Yogeshnull 			return status;
5158*dea5f973SBhosale, Yogeshnull 	}
5159*dea5f973SBhosale, Yogeshnull 
5160*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
5161*dea5f973SBhosale, Yogeshnull 	if (status)
5162*dea5f973SBhosale, Yogeshnull 		return status;
5163*dea5f973SBhosale, Yogeshnull 
5164*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_sr_word_aci(hw, offset, data);
5165*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
5166*dea5f973SBhosale, Yogeshnull 
5167*dea5f973SBhosale, Yogeshnull 	return status;
5168*dea5f973SBhosale, Yogeshnull }
5169*dea5f973SBhosale, Yogeshnull 
5170*dea5f973SBhosale, Yogeshnull /**
5171*dea5f973SBhosale, Yogeshnull  * ixgbe_read_ee_aci_buffer_E610- Read EEPROM word(s) using admin commands.
5172*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5173*dea5f973SBhosale, Yogeshnull  * @offset: offset of  word in the EEPROM to read
5174*dea5f973SBhosale, Yogeshnull  * @words: number of words
5175*dea5f973SBhosale, Yogeshnull  * @data: word(s) read from the EEPROM
5176*dea5f973SBhosale, Yogeshnull  *
5177*dea5f973SBhosale, Yogeshnull  * Reads a 16 bit word(s) from the EEPROM using the ACI.
5178*dea5f973SBhosale, Yogeshnull  * If the EEPROM params are not initialized, the function
5179*dea5f973SBhosale, Yogeshnull  * initialize them before proceeding with reading.
5180*dea5f973SBhosale, Yogeshnull  * The function acquires and then releases the NVM ownership.
5181*dea5f973SBhosale, Yogeshnull  *
5182*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5183*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_ee_aci_buffer_E610(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)5184*dea5f973SBhosale, Yogeshnull s32 ixgbe_read_ee_aci_buffer_E610(struct ixgbe_hw *hw, u16 offset,
5185*dea5f973SBhosale, Yogeshnull 				  u16 words, u16 *data)
5186*dea5f973SBhosale, Yogeshnull {
5187*dea5f973SBhosale, Yogeshnull 	s32 status;
5188*dea5f973SBhosale, Yogeshnull 
5189*dea5f973SBhosale, Yogeshnull 	if (hw->eeprom.type == ixgbe_eeprom_uninitialized) {
5190*dea5f973SBhosale, Yogeshnull 		status = ixgbe_init_eeprom_params(hw);
5191*dea5f973SBhosale, Yogeshnull 		if (status)
5192*dea5f973SBhosale, Yogeshnull 			return status;
5193*dea5f973SBhosale, Yogeshnull 	}
5194*dea5f973SBhosale, Yogeshnull 
5195*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
5196*dea5f973SBhosale, Yogeshnull 	if (status)
5197*dea5f973SBhosale, Yogeshnull 		return status;
5198*dea5f973SBhosale, Yogeshnull 
5199*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_sr_buf_aci(hw, offset, &words, data);
5200*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
5201*dea5f973SBhosale, Yogeshnull 
5202*dea5f973SBhosale, Yogeshnull 	return status;
5203*dea5f973SBhosale, Yogeshnull }
5204*dea5f973SBhosale, Yogeshnull 
5205*dea5f973SBhosale, Yogeshnull /**
5206*dea5f973SBhosale, Yogeshnull  * ixgbe_write_ee_aci_E610 - Write EEPROM word using the admin command.
5207*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5208*dea5f973SBhosale, Yogeshnull  * @offset: offset of  word in the EEPROM to write
5209*dea5f973SBhosale, Yogeshnull  * @data: word write to the EEPROM
5210*dea5f973SBhosale, Yogeshnull  *
5211*dea5f973SBhosale, Yogeshnull  * Write a 16 bit word to the EEPROM using the ACI.
5212*dea5f973SBhosale, Yogeshnull  * If the EEPROM params are not initialized, the function
5213*dea5f973SBhosale, Yogeshnull  * initialize them before proceeding with writing.
5214*dea5f973SBhosale, Yogeshnull  * The function acquires and then releases the NVM ownership.
5215*dea5f973SBhosale, Yogeshnull  *
5216*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5217*dea5f973SBhosale, Yogeshnull  */
ixgbe_write_ee_aci_E610(struct ixgbe_hw * hw,u16 offset,u16 data)5218*dea5f973SBhosale, Yogeshnull s32 ixgbe_write_ee_aci_E610(struct ixgbe_hw *hw, u16 offset, u16 data)
5219*dea5f973SBhosale, Yogeshnull {
5220*dea5f973SBhosale, Yogeshnull 	s32 status;
5221*dea5f973SBhosale, Yogeshnull 
5222*dea5f973SBhosale, Yogeshnull 	if (hw->eeprom.type == ixgbe_eeprom_uninitialized) {
5223*dea5f973SBhosale, Yogeshnull 		status = ixgbe_init_eeprom_params(hw);
5224*dea5f973SBhosale, Yogeshnull 		if (status)
5225*dea5f973SBhosale, Yogeshnull 			return status;
5226*dea5f973SBhosale, Yogeshnull 	}
5227*dea5f973SBhosale, Yogeshnull 
5228*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_WRITE);
5229*dea5f973SBhosale, Yogeshnull 	if (status)
5230*dea5f973SBhosale, Yogeshnull 		return status;
5231*dea5f973SBhosale, Yogeshnull 
5232*dea5f973SBhosale, Yogeshnull 	status = ixgbe_write_sr_word_aci(hw, (u32)offset, &data);
5233*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
5234*dea5f973SBhosale, Yogeshnull 
5235*dea5f973SBhosale, Yogeshnull 	return status;
5236*dea5f973SBhosale, Yogeshnull }
5237*dea5f973SBhosale, Yogeshnull 
5238*dea5f973SBhosale, Yogeshnull /**
5239*dea5f973SBhosale, Yogeshnull  * ixgbe_write_ee_aci_buffer_E610 - Write EEPROM word(s) using admin commands.
5240*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5241*dea5f973SBhosale, Yogeshnull  * @offset: offset of  word in the EEPROM to write
5242*dea5f973SBhosale, Yogeshnull  * @words: number of words
5243*dea5f973SBhosale, Yogeshnull  * @data: word(s) write to the EEPROM
5244*dea5f973SBhosale, Yogeshnull  *
5245*dea5f973SBhosale, Yogeshnull  * Write a 16 bit word(s) to the EEPROM using the ACI.
5246*dea5f973SBhosale, Yogeshnull  * If the EEPROM params are not initialized, the function
5247*dea5f973SBhosale, Yogeshnull  * initialize them before proceeding with writing.
5248*dea5f973SBhosale, Yogeshnull  * The function acquires and then releases the NVM ownership.
5249*dea5f973SBhosale, Yogeshnull  *
5250*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5251*dea5f973SBhosale, Yogeshnull  */
ixgbe_write_ee_aci_buffer_E610(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)5252*dea5f973SBhosale, Yogeshnull s32 ixgbe_write_ee_aci_buffer_E610(struct ixgbe_hw *hw, u16 offset,
5253*dea5f973SBhosale, Yogeshnull 				   u16 words, u16 *data)
5254*dea5f973SBhosale, Yogeshnull {
5255*dea5f973SBhosale, Yogeshnull 	s32 status;
5256*dea5f973SBhosale, Yogeshnull 
5257*dea5f973SBhosale, Yogeshnull 	if (hw->eeprom.type == ixgbe_eeprom_uninitialized) {
5258*dea5f973SBhosale, Yogeshnull 		status = ixgbe_init_eeprom_params(hw);
5259*dea5f973SBhosale, Yogeshnull 		if (status)
5260*dea5f973SBhosale, Yogeshnull 			return status;
5261*dea5f973SBhosale, Yogeshnull 	}
5262*dea5f973SBhosale, Yogeshnull 
5263*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_WRITE);
5264*dea5f973SBhosale, Yogeshnull 	if (status)
5265*dea5f973SBhosale, Yogeshnull 		return status;
5266*dea5f973SBhosale, Yogeshnull 
5267*dea5f973SBhosale, Yogeshnull 	status = ixgbe_write_sr_buf_aci(hw, (u32)offset, words, data);
5268*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
5269*dea5f973SBhosale, Yogeshnull 
5270*dea5f973SBhosale, Yogeshnull 	return status;
5271*dea5f973SBhosale, Yogeshnull }
5272*dea5f973SBhosale, Yogeshnull 
5273*dea5f973SBhosale, Yogeshnull /**
5274*dea5f973SBhosale, Yogeshnull  * ixgbe_calc_eeprom_checksum_E610 - Calculates and returns the checksum
5275*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5276*dea5f973SBhosale, Yogeshnull  *
5277*dea5f973SBhosale, Yogeshnull  * Calculate SW Checksum that covers the whole 64kB shadow RAM
5278*dea5f973SBhosale, Yogeshnull  * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
5279*dea5f973SBhosale, Yogeshnull  * is customer specific and unknown. Therefore, this function skips all maximum
5280*dea5f973SBhosale, Yogeshnull  * possible size of VPD (1kB).
5281*dea5f973SBhosale, Yogeshnull  * If the EEPROM params are not initialized, the function
5282*dea5f973SBhosale, Yogeshnull  * initializes them before proceeding.
5283*dea5f973SBhosale, Yogeshnull  * The function acquires and then releases the NVM ownership.
5284*dea5f973SBhosale, Yogeshnull  *
5285*dea5f973SBhosale, Yogeshnull  * Return: the negative error code on error, or the 16-bit checksum
5286*dea5f973SBhosale, Yogeshnull  */
ixgbe_calc_eeprom_checksum_E610(struct ixgbe_hw * hw)5287*dea5f973SBhosale, Yogeshnull s32 ixgbe_calc_eeprom_checksum_E610(struct ixgbe_hw *hw)
5288*dea5f973SBhosale, Yogeshnull {
5289*dea5f973SBhosale, Yogeshnull 	bool nvm_acquired = false;
5290*dea5f973SBhosale, Yogeshnull 	u16 pcie_alt_module = 0;
5291*dea5f973SBhosale, Yogeshnull 	u16 checksum_local = 0;
5292*dea5f973SBhosale, Yogeshnull 	u16 checksum = 0;
5293*dea5f973SBhosale, Yogeshnull 	u16 vpd_module;
5294*dea5f973SBhosale, Yogeshnull 	void *vmem;
5295*dea5f973SBhosale, Yogeshnull 	s32 status;
5296*dea5f973SBhosale, Yogeshnull 	u16 *data;
5297*dea5f973SBhosale, Yogeshnull 	u16 i;
5298*dea5f973SBhosale, Yogeshnull 
5299*dea5f973SBhosale, Yogeshnull 	if (hw->eeprom.type == ixgbe_eeprom_uninitialized) {
5300*dea5f973SBhosale, Yogeshnull 		status = ixgbe_init_eeprom_params(hw);
5301*dea5f973SBhosale, Yogeshnull 		if (status)
5302*dea5f973SBhosale, Yogeshnull 			return status;
5303*dea5f973SBhosale, Yogeshnull 	}
5304*dea5f973SBhosale, Yogeshnull 
5305*dea5f973SBhosale, Yogeshnull 	vmem = ixgbe_calloc(hw, IXGBE_SR_SECTOR_SIZE_IN_WORDS, sizeof(u16));
5306*dea5f973SBhosale, Yogeshnull 	if (!vmem)
5307*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_OUT_OF_MEM;
5308*dea5f973SBhosale, Yogeshnull 	data = (u16 *)vmem;
5309*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
5310*dea5f973SBhosale, Yogeshnull 	if (status)
5311*dea5f973SBhosale, Yogeshnull 		goto ixgbe_calc_sr_checksum_exit;
5312*dea5f973SBhosale, Yogeshnull 	nvm_acquired = true;
5313*dea5f973SBhosale, Yogeshnull 
5314*dea5f973SBhosale, Yogeshnull 	/* read pointer to VPD area */
5315*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_sr_word_aci(hw, E610_SR_VPD_PTR, &vpd_module);
5316*dea5f973SBhosale, Yogeshnull 	if (status)
5317*dea5f973SBhosale, Yogeshnull 		goto ixgbe_calc_sr_checksum_exit;
5318*dea5f973SBhosale, Yogeshnull 
5319*dea5f973SBhosale, Yogeshnull 	/* read pointer to PCIe Alt Auto-load module */
5320*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_sr_word_aci(hw, E610_SR_PCIE_ALT_AUTO_LOAD_PTR,
5321*dea5f973SBhosale, Yogeshnull 					&pcie_alt_module);
5322*dea5f973SBhosale, Yogeshnull 	if (status)
5323*dea5f973SBhosale, Yogeshnull 		goto ixgbe_calc_sr_checksum_exit;
5324*dea5f973SBhosale, Yogeshnull 
5325*dea5f973SBhosale, Yogeshnull 	/* Calculate SW checksum that covers the whole 64kB shadow RAM
5326*dea5f973SBhosale, Yogeshnull 	 * except the VPD and PCIe ALT Auto-load modules
5327*dea5f973SBhosale, Yogeshnull 	 */
5328*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < hw->eeprom.word_size; i++) {
5329*dea5f973SBhosale, Yogeshnull 		/* Read SR page */
5330*dea5f973SBhosale, Yogeshnull 		if ((i % IXGBE_SR_SECTOR_SIZE_IN_WORDS) == 0) {
5331*dea5f973SBhosale, Yogeshnull 			u16 words = IXGBE_SR_SECTOR_SIZE_IN_WORDS;
5332*dea5f973SBhosale, Yogeshnull 
5333*dea5f973SBhosale, Yogeshnull 			status = ixgbe_read_sr_buf_aci(hw, i, &words, data);
5334*dea5f973SBhosale, Yogeshnull 			if (status != IXGBE_SUCCESS)
5335*dea5f973SBhosale, Yogeshnull 				goto ixgbe_calc_sr_checksum_exit;
5336*dea5f973SBhosale, Yogeshnull 		}
5337*dea5f973SBhosale, Yogeshnull 
5338*dea5f973SBhosale, Yogeshnull 		/* Skip Checksum word */
5339*dea5f973SBhosale, Yogeshnull 		if (i == E610_SR_SW_CHECKSUM_WORD)
5340*dea5f973SBhosale, Yogeshnull 			continue;
5341*dea5f973SBhosale, Yogeshnull 		/* Skip VPD module (convert byte size to word count) */
5342*dea5f973SBhosale, Yogeshnull 		if (i >= (u32)vpd_module &&
5343*dea5f973SBhosale, Yogeshnull 		    i < ((u32)vpd_module + E610_SR_VPD_SIZE_WORDS))
5344*dea5f973SBhosale, Yogeshnull 			continue;
5345*dea5f973SBhosale, Yogeshnull 		/* Skip PCIe ALT module (convert byte size to word count) */
5346*dea5f973SBhosale, Yogeshnull 		if (i >= (u32)pcie_alt_module &&
5347*dea5f973SBhosale, Yogeshnull 		    i < ((u32)pcie_alt_module + E610_SR_PCIE_ALT_SIZE_WORDS))
5348*dea5f973SBhosale, Yogeshnull 			continue;
5349*dea5f973SBhosale, Yogeshnull 
5350*dea5f973SBhosale, Yogeshnull 		checksum_local += data[i % IXGBE_SR_SECTOR_SIZE_IN_WORDS];
5351*dea5f973SBhosale, Yogeshnull 	}
5352*dea5f973SBhosale, Yogeshnull 
5353*dea5f973SBhosale, Yogeshnull 	checksum = (u16)IXGBE_SR_SW_CHECKSUM_BASE - checksum_local;
5354*dea5f973SBhosale, Yogeshnull 
5355*dea5f973SBhosale, Yogeshnull ixgbe_calc_sr_checksum_exit:
5356*dea5f973SBhosale, Yogeshnull 	if(nvm_acquired)
5357*dea5f973SBhosale, Yogeshnull 		ixgbe_release_nvm(hw);
5358*dea5f973SBhosale, Yogeshnull 	ixgbe_free(hw, vmem);
5359*dea5f973SBhosale, Yogeshnull 
5360*dea5f973SBhosale, Yogeshnull 	if(!status)
5361*dea5f973SBhosale, Yogeshnull 		return (s32)checksum;
5362*dea5f973SBhosale, Yogeshnull 	else
5363*dea5f973SBhosale, Yogeshnull 		return status;
5364*dea5f973SBhosale, Yogeshnull }
5365*dea5f973SBhosale, Yogeshnull 
5366*dea5f973SBhosale, Yogeshnull /**
5367*dea5f973SBhosale, Yogeshnull  * ixgbe_update_eeprom_checksum_E610 - Updates the EEPROM checksum and flash
5368*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5369*dea5f973SBhosale, Yogeshnull  *
5370*dea5f973SBhosale, Yogeshnull  * After writing EEPROM to Shadow RAM, software sends the admin command
5371*dea5f973SBhosale, Yogeshnull  * to recalculate and update EEPROM checksum and instructs the hardware
5372*dea5f973SBhosale, Yogeshnull  * to update the flash.
5373*dea5f973SBhosale, Yogeshnull  * If the EEPROM params are not initialized, the function
5374*dea5f973SBhosale, Yogeshnull  * initialize them before proceeding.
5375*dea5f973SBhosale, Yogeshnull  * The function acquires and then releases the NVM ownership.
5376*dea5f973SBhosale, Yogeshnull  *
5377*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5378*dea5f973SBhosale, Yogeshnull  */
ixgbe_update_eeprom_checksum_E610(struct ixgbe_hw * hw)5379*dea5f973SBhosale, Yogeshnull s32 ixgbe_update_eeprom_checksum_E610(struct ixgbe_hw *hw)
5380*dea5f973SBhosale, Yogeshnull {
5381*dea5f973SBhosale, Yogeshnull 	s32 status;
5382*dea5f973SBhosale, Yogeshnull 
5383*dea5f973SBhosale, Yogeshnull 	if (hw->eeprom.type == ixgbe_eeprom_uninitialized) {
5384*dea5f973SBhosale, Yogeshnull 		status = ixgbe_init_eeprom_params(hw);
5385*dea5f973SBhosale, Yogeshnull 		if (status)
5386*dea5f973SBhosale, Yogeshnull 			return status;
5387*dea5f973SBhosale, Yogeshnull 	}
5388*dea5f973SBhosale, Yogeshnull 
5389*dea5f973SBhosale, Yogeshnull 	status = ixgbe_nvm_recalculate_checksum(hw);
5390*dea5f973SBhosale, Yogeshnull 	if (status)
5391*dea5f973SBhosale, Yogeshnull 		return status;
5392*dea5f973SBhosale, Yogeshnull 	status = ixgbe_acquire_nvm(hw, IXGBE_RES_WRITE);
5393*dea5f973SBhosale, Yogeshnull 	if (status)
5394*dea5f973SBhosale, Yogeshnull 		return status;
5395*dea5f973SBhosale, Yogeshnull 
5396*dea5f973SBhosale, Yogeshnull 	status = ixgbe_nvm_write_activate(hw, IXGBE_ACI_NVM_ACTIV_REQ_EMPR,
5397*dea5f973SBhosale, Yogeshnull 					  NULL);
5398*dea5f973SBhosale, Yogeshnull 	ixgbe_release_nvm(hw);
5399*dea5f973SBhosale, Yogeshnull 
5400*dea5f973SBhosale, Yogeshnull 	return status;
5401*dea5f973SBhosale, Yogeshnull }
5402*dea5f973SBhosale, Yogeshnull 
5403*dea5f973SBhosale, Yogeshnull /**
5404*dea5f973SBhosale, Yogeshnull  * ixgbe_validate_eeprom_checksum_E610 - Validate EEPROM checksum
5405*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5406*dea5f973SBhosale, Yogeshnull  * @checksum_val: calculated checksum
5407*dea5f973SBhosale, Yogeshnull  *
5408*dea5f973SBhosale, Yogeshnull  * Performs checksum calculation and validates the EEPROM checksum. If the
5409*dea5f973SBhosale, Yogeshnull  * caller does not need checksum_val, the value can be NULL.
5410*dea5f973SBhosale, Yogeshnull  * If the EEPROM params are not initialized, the function
5411*dea5f973SBhosale, Yogeshnull  * initialize them before proceeding.
5412*dea5f973SBhosale, Yogeshnull  * The function acquires and then releases the NVM ownership.
5413*dea5f973SBhosale, Yogeshnull  *
5414*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5415*dea5f973SBhosale, Yogeshnull  */
ixgbe_validate_eeprom_checksum_E610(struct ixgbe_hw * hw,u16 * checksum_val)5416*dea5f973SBhosale, Yogeshnull s32 ixgbe_validate_eeprom_checksum_E610(struct ixgbe_hw *hw, u16 *checksum_val)
5417*dea5f973SBhosale, Yogeshnull {
5418*dea5f973SBhosale, Yogeshnull 	u32 status;
5419*dea5f973SBhosale, Yogeshnull 
5420*dea5f973SBhosale, Yogeshnull 	if (hw->eeprom.type == ixgbe_eeprom_uninitialized) {
5421*dea5f973SBhosale, Yogeshnull 		status = ixgbe_init_eeprom_params(hw);
5422*dea5f973SBhosale, Yogeshnull 		if (status)
5423*dea5f973SBhosale, Yogeshnull 			return status;
5424*dea5f973SBhosale, Yogeshnull 	}
5425*dea5f973SBhosale, Yogeshnull 
5426*dea5f973SBhosale, Yogeshnull 	status = ixgbe_nvm_validate_checksum(hw);
5427*dea5f973SBhosale, Yogeshnull 
5428*dea5f973SBhosale, Yogeshnull 	if (status)
5429*dea5f973SBhosale, Yogeshnull 		return status;
5430*dea5f973SBhosale, Yogeshnull 
5431*dea5f973SBhosale, Yogeshnull 	if (checksum_val) {
5432*dea5f973SBhosale, Yogeshnull 		u16 tmp_checksum;
5433*dea5f973SBhosale, Yogeshnull 		status = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
5434*dea5f973SBhosale, Yogeshnull 		if (status)
5435*dea5f973SBhosale, Yogeshnull 			return status;
5436*dea5f973SBhosale, Yogeshnull 
5437*dea5f973SBhosale, Yogeshnull 		status = ixgbe_read_sr_word_aci(hw, E610_SR_SW_CHECKSUM_WORD,
5438*dea5f973SBhosale, Yogeshnull 						&tmp_checksum);
5439*dea5f973SBhosale, Yogeshnull 		ixgbe_release_nvm(hw);
5440*dea5f973SBhosale, Yogeshnull 
5441*dea5f973SBhosale, Yogeshnull 		if (!status)
5442*dea5f973SBhosale, Yogeshnull 			*checksum_val = tmp_checksum;
5443*dea5f973SBhosale, Yogeshnull 	}
5444*dea5f973SBhosale, Yogeshnull 
5445*dea5f973SBhosale, Yogeshnull 	return status;
5446*dea5f973SBhosale, Yogeshnull }
5447*dea5f973SBhosale, Yogeshnull 
5448*dea5f973SBhosale, Yogeshnull /**
5449*dea5f973SBhosale, Yogeshnull  * ixgbe_get_pfa_module_tlv - Reads sub module TLV from NVM PFA
5450*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5451*dea5f973SBhosale, Yogeshnull  * @module_tlv: pointer to module TLV to return
5452*dea5f973SBhosale, Yogeshnull  * @module_tlv_len: pointer to module TLV length to return
5453*dea5f973SBhosale, Yogeshnull  * @module_type: module type requested
5454*dea5f973SBhosale, Yogeshnull  *
5455*dea5f973SBhosale, Yogeshnull  * Finds the requested sub module TLV type from the Preserved Field
5456*dea5f973SBhosale, Yogeshnull  * Area (PFA) and returns the TLV pointer and length. The caller can
5457*dea5f973SBhosale, Yogeshnull  * use these to read the variable length TLV value.
5458*dea5f973SBhosale, Yogeshnull  *
5459*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5460*dea5f973SBhosale, Yogeshnull  */
ixgbe_get_pfa_module_tlv(struct ixgbe_hw * hw,u16 * module_tlv,u16 * module_tlv_len,u16 module_type)5461*dea5f973SBhosale, Yogeshnull static s32 ixgbe_get_pfa_module_tlv(struct ixgbe_hw *hw, u16 *module_tlv,
5462*dea5f973SBhosale, Yogeshnull 				    u16 *module_tlv_len, u16 module_type)
5463*dea5f973SBhosale, Yogeshnull {
5464*dea5f973SBhosale, Yogeshnull 	u16 pfa_len, pfa_ptr, pfa_end_ptr;
5465*dea5f973SBhosale, Yogeshnull 	u16 next_tlv;
5466*dea5f973SBhosale, Yogeshnull 	s32 status;
5467*dea5f973SBhosale, Yogeshnull 
5468*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_ee_aci_E610(hw, E610_SR_PFA_PTR, &pfa_ptr);
5469*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS) {
5470*dea5f973SBhosale, Yogeshnull 		return status;
5471*dea5f973SBhosale, Yogeshnull 	}
5472*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_ee_aci_E610(hw, pfa_ptr, &pfa_len);
5473*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS) {
5474*dea5f973SBhosale, Yogeshnull 		return status;
5475*dea5f973SBhosale, Yogeshnull 	}
5476*dea5f973SBhosale, Yogeshnull 	/* Starting with first TLV after PFA length, iterate through the list
5477*dea5f973SBhosale, Yogeshnull 	 * of TLVs to find the requested one.
5478*dea5f973SBhosale, Yogeshnull 	 */
5479*dea5f973SBhosale, Yogeshnull 	next_tlv = pfa_ptr + 1;
5480*dea5f973SBhosale, Yogeshnull 	pfa_end_ptr = pfa_ptr + pfa_len;
5481*dea5f973SBhosale, Yogeshnull 	while (next_tlv < pfa_end_ptr) {
5482*dea5f973SBhosale, Yogeshnull 		u16 tlv_sub_module_type, tlv_len;
5483*dea5f973SBhosale, Yogeshnull 
5484*dea5f973SBhosale, Yogeshnull 		/* Read TLV type */
5485*dea5f973SBhosale, Yogeshnull 		status = ixgbe_read_ee_aci_E610(hw, next_tlv,
5486*dea5f973SBhosale, Yogeshnull 						&tlv_sub_module_type);
5487*dea5f973SBhosale, Yogeshnull 		if (status != IXGBE_SUCCESS) {
5488*dea5f973SBhosale, Yogeshnull 			break;
5489*dea5f973SBhosale, Yogeshnull 		}
5490*dea5f973SBhosale, Yogeshnull 		/* Read TLV length */
5491*dea5f973SBhosale, Yogeshnull 		status = ixgbe_read_ee_aci_E610(hw, next_tlv + 1, &tlv_len);
5492*dea5f973SBhosale, Yogeshnull 		if (status != IXGBE_SUCCESS) {
5493*dea5f973SBhosale, Yogeshnull 			break;
5494*dea5f973SBhosale, Yogeshnull 		}
5495*dea5f973SBhosale, Yogeshnull 		if (tlv_sub_module_type == module_type) {
5496*dea5f973SBhosale, Yogeshnull 			if (tlv_len) {
5497*dea5f973SBhosale, Yogeshnull 				*module_tlv = next_tlv;
5498*dea5f973SBhosale, Yogeshnull 				*module_tlv_len = tlv_len;
5499*dea5f973SBhosale, Yogeshnull 				return IXGBE_SUCCESS;
5500*dea5f973SBhosale, Yogeshnull 			}
5501*dea5f973SBhosale, Yogeshnull 			return IXGBE_ERR_INVAL_SIZE;
5502*dea5f973SBhosale, Yogeshnull 		}
5503*dea5f973SBhosale, Yogeshnull 		/* Check next TLV, i.e. current TLV pointer + length + 2 words
5504*dea5f973SBhosale, Yogeshnull 		 * (for current TLV's type and length)
5505*dea5f973SBhosale, Yogeshnull 		 */
5506*dea5f973SBhosale, Yogeshnull 		next_tlv = next_tlv + tlv_len + 2;
5507*dea5f973SBhosale, Yogeshnull 	}
5508*dea5f973SBhosale, Yogeshnull 	/* Module does not exist */
5509*dea5f973SBhosale, Yogeshnull 	return IXGBE_ERR_DOES_NOT_EXIST;
5510*dea5f973SBhosale, Yogeshnull }
5511*dea5f973SBhosale, Yogeshnull 
5512*dea5f973SBhosale, Yogeshnull /**
5513*dea5f973SBhosale, Yogeshnull  * ixgbe_read_pba_string_E610 - Reads part number string from NVM
5514*dea5f973SBhosale, Yogeshnull  * @hw: pointer to hardware structure
5515*dea5f973SBhosale, Yogeshnull  * @pba_num: stores the part number string from the NVM
5516*dea5f973SBhosale, Yogeshnull  * @pba_num_size: part number string buffer length
5517*dea5f973SBhosale, Yogeshnull  *
5518*dea5f973SBhosale, Yogeshnull  * Reads the part number string from the NVM.
5519*dea5f973SBhosale, Yogeshnull  *
5520*dea5f973SBhosale, Yogeshnull  * Return: the exit code of the operation.
5521*dea5f973SBhosale, Yogeshnull  */
ixgbe_read_pba_string_E610(struct ixgbe_hw * hw,u8 * pba_num,u32 pba_num_size)5522*dea5f973SBhosale, Yogeshnull s32 ixgbe_read_pba_string_E610(struct ixgbe_hw *hw, u8 *pba_num,
5523*dea5f973SBhosale, Yogeshnull 			       u32 pba_num_size)
5524*dea5f973SBhosale, Yogeshnull {
5525*dea5f973SBhosale, Yogeshnull 	u16 pba_tlv, pba_tlv_len;
5526*dea5f973SBhosale, Yogeshnull 	u16 pba_word, pba_size;
5527*dea5f973SBhosale, Yogeshnull 	s32 status;
5528*dea5f973SBhosale, Yogeshnull 	u16 i;
5529*dea5f973SBhosale, Yogeshnull 
5530*dea5f973SBhosale, Yogeshnull 	status = ixgbe_get_pfa_module_tlv(hw, &pba_tlv, &pba_tlv_len,
5531*dea5f973SBhosale, Yogeshnull 					E610_SR_PBA_BLOCK_PTR);
5532*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS) {
5533*dea5f973SBhosale, Yogeshnull 		return status;
5534*dea5f973SBhosale, Yogeshnull 	}
5535*dea5f973SBhosale, Yogeshnull 
5536*dea5f973SBhosale, Yogeshnull 	/* pba_size is the next word */
5537*dea5f973SBhosale, Yogeshnull 	status = ixgbe_read_ee_aci_E610(hw, (pba_tlv + 2), &pba_size);
5538*dea5f973SBhosale, Yogeshnull 	if (status != IXGBE_SUCCESS) {
5539*dea5f973SBhosale, Yogeshnull 		return status;
5540*dea5f973SBhosale, Yogeshnull 	}
5541*dea5f973SBhosale, Yogeshnull 
5542*dea5f973SBhosale, Yogeshnull 	if (pba_tlv_len < pba_size) {
5543*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_INVAL_SIZE;
5544*dea5f973SBhosale, Yogeshnull 	}
5545*dea5f973SBhosale, Yogeshnull 
5546*dea5f973SBhosale, Yogeshnull 	/* Subtract one to get PBA word count (PBA Size word is included in
5547*dea5f973SBhosale, Yogeshnull 	 * total size)
5548*dea5f973SBhosale, Yogeshnull 	 */
5549*dea5f973SBhosale, Yogeshnull 	pba_size--;
5550*dea5f973SBhosale, Yogeshnull 	if (pba_num_size < (((u32)pba_size * 2) + 1)) {
5551*dea5f973SBhosale, Yogeshnull 		return IXGBE_ERR_PARAM;
5552*dea5f973SBhosale, Yogeshnull 	}
5553*dea5f973SBhosale, Yogeshnull 
5554*dea5f973SBhosale, Yogeshnull 	for (i = 0; i < pba_size; i++) {
5555*dea5f973SBhosale, Yogeshnull 		status = ixgbe_read_ee_aci_E610(hw, (pba_tlv + 2 + 1) + i,
5556*dea5f973SBhosale, Yogeshnull 						&pba_word);
5557*dea5f973SBhosale, Yogeshnull 		if (status != IXGBE_SUCCESS) {
5558*dea5f973SBhosale, Yogeshnull 			return status;
5559*dea5f973SBhosale, Yogeshnull 		}
5560*dea5f973SBhosale, Yogeshnull 
5561*dea5f973SBhosale, Yogeshnull 		pba_num[(i * 2)] = (pba_word >> 8) & 0xFF;
5562*dea5f973SBhosale, Yogeshnull 		pba_num[(i * 2) + 1] = pba_word & 0xFF;
5563*dea5f973SBhosale, Yogeshnull 	}
5564*dea5f973SBhosale, Yogeshnull 	pba_num[(pba_size * 2)] = '\0';
5565*dea5f973SBhosale, Yogeshnull 
5566*dea5f973SBhosale, Yogeshnull 	return status;
5567*dea5f973SBhosale, Yogeshnull }
5568