Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2001-2020 Intel Corporation
3 : : */
4 : :
5 : : #include "ixgbe_x550.h"
6 : : #include "ixgbe_x540.h"
7 : : #include "ixgbe_type.h"
8 : : #include "ixgbe_api.h"
9 : : #include "ixgbe_common.h"
10 : : #include "ixgbe_phy.h"
11 : :
12 : : STATIC s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed);
13 : : STATIC s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
14 : : STATIC void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
15 : : STATIC s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw);
16 : :
17 : : /**
18 : : * ixgbe_init_ops_X550 - Inits func ptrs and MAC type
19 : : * @hw: pointer to hardware structure
20 : : *
21 : : * Initialize the function pointers and assign the MAC type for X550.
22 : : * Does not touch the hardware.
23 : : **/
24 : 0 : s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw)
25 : : {
26 : : struct ixgbe_mac_info *mac = &hw->mac;
27 : : struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
28 : : s32 ret_val;
29 : :
30 : 0 : DEBUGFUNC("ixgbe_init_ops_X550");
31 : :
32 : 0 : ret_val = ixgbe_init_ops_X540(hw);
33 : 0 : mac->ops.dmac_config = ixgbe_dmac_config_X550;
34 : 0 : mac->ops.dmac_config_tcs = ixgbe_dmac_config_tcs_X550;
35 : 0 : mac->ops.dmac_update_tcs = ixgbe_dmac_update_tcs_X550;
36 : 0 : mac->ops.setup_eee = NULL;
37 : 0 : mac->ops.set_source_address_pruning =
38 : : ixgbe_set_source_address_pruning_X550;
39 : 0 : mac->ops.set_ethertype_anti_spoofing =
40 : : ixgbe_set_ethertype_anti_spoofing_X550;
41 : :
42 : 0 : mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
43 : 0 : eeprom->ops.init_params = ixgbe_init_eeprom_params_X550;
44 : 0 : eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
45 : 0 : eeprom->ops.read = ixgbe_read_ee_hostif_X550;
46 : 0 : eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550;
47 : 0 : eeprom->ops.write = ixgbe_write_ee_hostif_X550;
48 : 0 : eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550;
49 : 0 : eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
50 : 0 : eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
51 : :
52 : 0 : mac->ops.disable_mdd = ixgbe_disable_mdd_X550;
53 : 0 : mac->ops.enable_mdd = ixgbe_enable_mdd_X550;
54 : 0 : mac->ops.mdd_event = ixgbe_mdd_event_X550;
55 : 0 : mac->ops.restore_mdd_vf = ixgbe_restore_mdd_vf_X550;
56 : 0 : mac->ops.fw_recovery_mode = ixgbe_fw_recovery_mode_X550;
57 : 0 : mac->ops.disable_rx = ixgbe_disable_rx_x550;
58 : : /* Manageability interface */
59 : 0 : mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_x550;
60 [ # # # ]: 0 : switch (hw->device_id) {
61 : 0 : case IXGBE_DEV_ID_X550EM_X_1G_T:
62 : 0 : hw->mac.ops.led_on = NULL;
63 : 0 : hw->mac.ops.led_off = NULL;
64 : 0 : break;
65 : 0 : case IXGBE_DEV_ID_X550EM_X_10G_T:
66 : : case IXGBE_DEV_ID_X550EM_A_10G_T:
67 : 0 : hw->mac.ops.led_on = ixgbe_led_on_t_X550em;
68 : 0 : hw->mac.ops.led_off = ixgbe_led_off_t_X550em;
69 : 0 : break;
70 : : default:
71 : : break;
72 : : }
73 : 0 : return ret_val;
74 : : }
75 : :
76 : : /**
77 : : * ixgbe_read_cs4227 - Read CS4227 register
78 : : * @hw: pointer to hardware structure
79 : : * @reg: register number to write
80 : : * @value: pointer to receive value read
81 : : *
82 : : * Returns status code
83 : : **/
84 : : STATIC s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
85 : : {
86 : 0 : return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);
87 : : }
88 : :
89 : : /**
90 : : * ixgbe_write_cs4227 - Write CS4227 register
91 : : * @hw: pointer to hardware structure
92 : : * @reg: register number to write
93 : : * @value: value to write to register
94 : : *
95 : : * Returns status code
96 : : **/
97 : : STATIC s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
98 : : {
99 : 0 : return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);
100 : : }
101 : :
102 : : /**
103 : : * ixgbe_read_pe - Read register from port expander
104 : : * @hw: pointer to hardware structure
105 : : * @reg: register number to read
106 : : * @value: pointer to receive read value
107 : : *
108 : : * Returns status code
109 : : **/
110 : 0 : STATIC s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value)
111 : : {
112 : : s32 status;
113 : :
114 : 0 : status = ixgbe_read_i2c_byte_unlocked(hw, reg, IXGBE_PE, value);
115 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
116 : 0 : ERROR_REPORT2(IXGBE_ERROR_CAUTION,
117 : : "port expander access failed with %d\n", status);
118 : 0 : return status;
119 : : }
120 : :
121 : : /**
122 : : * ixgbe_write_pe - Write register to port expander
123 : : * @hw: pointer to hardware structure
124 : : * @reg: register number to write
125 : : * @value: value to write
126 : : *
127 : : * Returns status code
128 : : **/
129 : 0 : STATIC s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value)
130 : : {
131 : : s32 status;
132 : :
133 : 0 : status = ixgbe_write_i2c_byte_unlocked(hw, reg, IXGBE_PE, value);
134 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
135 : 0 : ERROR_REPORT2(IXGBE_ERROR_CAUTION,
136 : : "port expander access failed with %d\n", status);
137 : 0 : return status;
138 : : }
139 : :
140 : : /**
141 : : * ixgbe_reset_cs4227 - Reset CS4227 using port expander
142 : : * @hw: pointer to hardware structure
143 : : *
144 : : * This function assumes that the caller has acquired the proper semaphore.
145 : : * Returns error code
146 : : **/
147 : 0 : STATIC s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
148 : : {
149 : : s32 status;
150 : : u32 retry;
151 : : u16 value;
152 : : u8 reg;
153 : :
154 : : /* Trigger hard reset. */
155 : 0 : status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®);
156 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
157 : : return status;
158 : 0 : reg |= IXGBE_PE_BIT1;
159 : 0 : status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
160 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
161 : : return status;
162 : :
163 : 0 : status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®);
164 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
165 : : return status;
166 : 0 : reg &= ~IXGBE_PE_BIT1;
167 : 0 : status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg);
168 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
169 : : return status;
170 : :
171 : 0 : status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®);
172 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
173 : : return status;
174 : 0 : reg &= ~IXGBE_PE_BIT1;
175 : 0 : status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
176 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
177 : : return status;
178 : :
179 : 0 : usec_delay(IXGBE_CS4227_RESET_HOLD);
180 : :
181 : 0 : status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®);
182 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
183 : : return status;
184 : 0 : reg |= IXGBE_PE_BIT1;
185 : 0 : status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
186 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
187 : : return status;
188 : :
189 : : /* Wait for the reset to complete. */
190 : 0 : msec_delay(IXGBE_CS4227_RESET_DELAY);
191 [ # # ]: 0 : for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
192 : : status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
193 : : &value);
194 [ # # ]: 0 : if (status == IXGBE_SUCCESS &&
195 [ # # ]: 0 : value == IXGBE_CS4227_EEPROM_LOAD_OK)
196 : : break;
197 : 0 : msec_delay(IXGBE_CS4227_CHECK_DELAY);
198 : : }
199 [ # # ]: 0 : if (retry == IXGBE_CS4227_RETRIES) {
200 : 0 : ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
201 : : "CS4227 reset did not complete.");
202 : 0 : return IXGBE_ERR_PHY;
203 : : }
204 : :
205 : : status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
206 [ # # ]: 0 : if (status != IXGBE_SUCCESS ||
207 [ # # ]: 0 : !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
208 : 0 : ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
209 : : "CS4227 EEPROM did not load successfully.");
210 : 0 : return IXGBE_ERR_PHY;
211 : : }
212 : :
213 : : return IXGBE_SUCCESS;
214 : : }
215 : :
216 : : /**
217 : : * ixgbe_check_cs4227 - Check CS4227 and reset as needed
218 : : * @hw: pointer to hardware structure
219 : : **/
220 : 0 : STATIC void ixgbe_check_cs4227(struct ixgbe_hw *hw)
221 : : {
222 : : s32 status = IXGBE_SUCCESS;
223 : 0 : u32 swfw_mask = hw->phy.phy_semaphore_mask;
224 : 0 : u16 value = 0;
225 : : u8 retry;
226 : :
227 [ # # ]: 0 : for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
228 : 0 : status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
229 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
230 : 0 : ERROR_REPORT2(IXGBE_ERROR_CAUTION,
231 : : "semaphore failed with %d", status);
232 : 0 : msec_delay(IXGBE_CS4227_CHECK_DELAY);
233 : 0 : continue;
234 : : }
235 : :
236 : : /* Get status of reset flow. */
237 : : status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
238 : :
239 [ # # ]: 0 : if (status == IXGBE_SUCCESS &&
240 [ # # ]: 0 : value == IXGBE_CS4227_RESET_COMPLETE)
241 : 0 : goto out;
242 : :
243 [ # # ]: 0 : if (status != IXGBE_SUCCESS ||
244 [ # # ]: 0 : value != IXGBE_CS4227_RESET_PENDING)
245 : : break;
246 : :
247 : : /* Reset is pending. Wait and check again. */
248 : 0 : hw->mac.ops.release_swfw_sync(hw, swfw_mask);
249 : 0 : msec_delay(IXGBE_CS4227_CHECK_DELAY);
250 : : }
251 : :
252 : : /* If still pending, assume other instance failed. */
253 [ # # ]: 0 : if (retry == IXGBE_CS4227_RETRIES) {
254 : 0 : status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
255 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
256 : 0 : ERROR_REPORT2(IXGBE_ERROR_CAUTION,
257 : : "semaphore failed with %d", status);
258 : 0 : return;
259 : : }
260 : : }
261 : :
262 : : /* Reset the CS4227. */
263 : 0 : status = ixgbe_reset_cs4227(hw);
264 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
265 : 0 : ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
266 : : "CS4227 reset failed: %d", status);
267 : 0 : goto out;
268 : : }
269 : :
270 : : /* Reset takes so long, temporarily release semaphore in case the
271 : : * other driver instance is waiting for the reset indication.
272 : : */
273 : : ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
274 : : IXGBE_CS4227_RESET_PENDING);
275 : 0 : hw->mac.ops.release_swfw_sync(hw, swfw_mask);
276 : 0 : msec_delay(10);
277 : 0 : status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
278 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
279 : 0 : ERROR_REPORT2(IXGBE_ERROR_CAUTION,
280 : : "semaphore failed with %d", status);
281 : 0 : return;
282 : : }
283 : :
284 : : /* Record completion for next time. */
285 : : status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
286 : : IXGBE_CS4227_RESET_COMPLETE);
287 : :
288 : 0 : out:
289 : 0 : hw->mac.ops.release_swfw_sync(hw, swfw_mask);
290 : 0 : msec_delay(hw->eeprom.semaphore_delay);
291 : : }
292 : :
293 : : /**
294 : : * ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control
295 : : * @hw: pointer to hardware structure
296 : : **/
297 : : STATIC void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
298 : : {
299 : 0 : u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
300 : :
301 [ # # # # : 0 : if (hw->bus.lan_id) {
# # ]
302 : 0 : esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
303 : 0 : esdp |= IXGBE_ESDP_SDP1_DIR;
304 : : }
305 : 0 : esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
306 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
307 : 0 : IXGBE_WRITE_FLUSH(hw);
308 : 0 : }
309 : :
310 : : /**
311 : : * ixgbe_identify_phy_x550em - Get PHY type based on device id
312 : : * @hw: pointer to hardware structure
313 : : *
314 : : * Returns error code
315 : : */
316 : 0 : STATIC s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
317 : : {
318 : 0 : hw->mac.ops.set_lan_id(hw);
319 : :
320 : : ixgbe_read_mng_if_sel_x550em(hw);
321 : :
322 [ # # # # : 0 : switch (hw->device_id) {
# # # # #
# ]
323 : 0 : case IXGBE_DEV_ID_X550EM_A_SFP:
324 : 0 : return ixgbe_identify_sfp_module_X550em(hw);
325 : : case IXGBE_DEV_ID_X550EM_X_SFP:
326 : : /* set up for CS4227 usage */
327 : : ixgbe_setup_mux_ctl(hw);
328 : 0 : ixgbe_check_cs4227(hw);
329 : 0 : return ixgbe_identify_sfp_module_X550em(hw);
330 : 0 : case IXGBE_DEV_ID_X550EM_A_SFP_N:
331 : 0 : return ixgbe_identify_sfp_module_X550em(hw);
332 : : break;
333 : 0 : case IXGBE_DEV_ID_X550EM_X_KX4:
334 : 0 : hw->phy.type = ixgbe_phy_x550em_kx4;
335 : 0 : break;
336 : 0 : case IXGBE_DEV_ID_X550EM_X_XFI:
337 : 0 : hw->phy.type = ixgbe_phy_x550em_xfi;
338 : 0 : break;
339 : 0 : case IXGBE_DEV_ID_X550EM_X_KR:
340 : : case IXGBE_DEV_ID_X550EM_A_KR:
341 : : case IXGBE_DEV_ID_X550EM_A_KR_L:
342 : 0 : hw->phy.type = ixgbe_phy_x550em_kr;
343 : 0 : break;
344 : 0 : case IXGBE_DEV_ID_X550EM_A_10G_T:
345 : : case IXGBE_DEV_ID_X550EM_X_10G_T:
346 : 0 : return ixgbe_identify_phy_generic(hw);
347 : 0 : case IXGBE_DEV_ID_X550EM_X_1G_T:
348 : 0 : hw->phy.type = ixgbe_phy_ext_1g_t;
349 : 0 : break;
350 : 0 : case IXGBE_DEV_ID_X550EM_A_1G_T:
351 : : case IXGBE_DEV_ID_X550EM_A_1G_T_L:
352 : 0 : hw->phy.type = ixgbe_phy_fw;
353 [ # # ]: 0 : if (hw->bus.lan_id)
354 : 0 : hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
355 : : else
356 : 0 : hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
357 : : break;
358 : : default:
359 : : break;
360 : : }
361 : : return IXGBE_SUCCESS;
362 : : }
363 : :
364 : : /**
365 : : * ixgbe_fw_phy_activity - Perform an activity on a PHY
366 : : * @hw: pointer to hardware structure
367 : : * @activity: activity to perform
368 : : * @data: Pointer to 4 32-bit words of data
369 : : */
370 : 0 : s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity,
371 : : u32 (*data)[FW_PHY_ACT_DATA_COUNT])
372 : : {
373 : : union {
374 : : struct ixgbe_hic_phy_activity_req cmd;
375 : : struct ixgbe_hic_phy_activity_resp rsp;
376 : : } hic;
377 : : u16 retries = FW_PHY_ACT_RETRIES;
378 : : s32 rc;
379 : : u16 i;
380 : :
381 : : do {
382 : : memset(&hic, 0, sizeof(hic));
383 : 0 : hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD;
384 : 0 : hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN;
385 : 0 : hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
386 : 0 : hic.cmd.port_number = hw->bus.lan_id;
387 : 0 : hic.cmd.activity_id = IXGBE_CPU_TO_LE16(activity);
388 [ # # ]: 0 : for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
389 [ # # ]: 0 : hic.cmd.data[i] = IXGBE_CPU_TO_BE32((*data)[i]);
390 : :
391 : 0 : rc = ixgbe_host_interface_command(hw, (u32 *)&hic.cmd,
392 : : sizeof(hic.cmd),
393 : : IXGBE_HI_COMMAND_TIMEOUT,
394 : : true);
395 [ # # ]: 0 : if (rc != IXGBE_SUCCESS)
396 : 0 : return rc;
397 [ # # ]: 0 : if (hic.rsp.hdr.cmd_or_resp.ret_status ==
398 : : FW_CEM_RESP_STATUS_SUCCESS) {
399 [ # # ]: 0 : for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
400 [ # # ]: 0 : (*data)[i] = IXGBE_BE32_TO_CPU(hic.rsp.data[i]);
401 : : return IXGBE_SUCCESS;
402 : : }
403 : 0 : usec_delay(20);
404 : 0 : --retries;
405 [ # # ]: 0 : } while (retries > 0);
406 : :
407 : : return IXGBE_ERR_HOST_INTERFACE_COMMAND;
408 : : }
409 : :
410 : : static const struct {
411 : : u16 fw_speed;
412 : : ixgbe_link_speed phy_speed;
413 : : } ixgbe_fw_map[] = {
414 : : { FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL },
415 : : { FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL },
416 : : { FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL },
417 : : { FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL },
418 : : { FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL },
419 : : { FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL },
420 : : };
421 : :
422 : : /**
423 : : * ixgbe_get_phy_id_fw - Get the phy ID via firmware command
424 : : * @hw: pointer to hardware structure
425 : : *
426 : : * Returns error code
427 : : */
428 : 0 : static s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw)
429 : : {
430 : 0 : u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
431 : : u16 phy_speeds;
432 : : u16 phy_id_lo;
433 : : s32 rc;
434 : : u16 i;
435 : :
436 : 0 : rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info);
437 [ # # ]: 0 : if (rc)
438 : : return rc;
439 : :
440 : 0 : hw->phy.speeds_supported = 0;
441 : 0 : phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK;
442 [ # # ]: 0 : for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) {
443 [ # # ]: 0 : if (phy_speeds & ixgbe_fw_map[i].fw_speed)
444 : 0 : hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed;
445 : : }
446 [ # # ]: 0 : if (!hw->phy.autoneg_advertised)
447 : 0 : hw->phy.autoneg_advertised = hw->phy.speeds_supported;
448 : :
449 : 0 : hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK;
450 : 0 : phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK;
451 : 0 : hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK;
452 : 0 : hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK;
453 [ # # ]: 0 : if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK)
454 : 0 : return IXGBE_ERR_PHY_ADDR_INVALID;
455 : : return IXGBE_SUCCESS;
456 : : }
457 : :
458 : : /**
459 : : * ixgbe_identify_phy_fw - Get PHY type based on firmware command
460 : : * @hw: pointer to hardware structure
461 : : *
462 : : * Returns error code
463 : : */
464 : 0 : static s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw)
465 : : {
466 [ # # ]: 0 : if (hw->bus.lan_id)
467 : 0 : hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
468 : : else
469 : 0 : hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
470 : :
471 : 0 : hw->phy.type = ixgbe_phy_fw;
472 : 0 : hw->phy.ops.read_reg = NULL;
473 : 0 : hw->phy.ops.write_reg = NULL;
474 : 0 : return ixgbe_get_phy_id_fw(hw);
475 : : }
476 : :
477 : : /**
478 : : * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY
479 : : * @hw: pointer to hardware structure
480 : : *
481 : : * Returns error code
482 : : */
483 : 0 : s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw)
484 : : {
485 : 0 : u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
486 : :
487 : 0 : setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF;
488 : 0 : return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup);
489 : : }
490 : :
491 : 0 : STATIC s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
492 : : u32 device_type, u16 *phy_data)
493 : : {
494 : : UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, *phy_data);
495 : 0 : return IXGBE_NOT_IMPLEMENTED;
496 : : }
497 : :
498 : 0 : STATIC s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
499 : : u32 device_type, u16 phy_data)
500 : : {
501 : : UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, phy_data);
502 : 0 : return IXGBE_NOT_IMPLEMENTED;
503 : : }
504 : :
505 : : /**
506 : : * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
507 : : * @hw: pointer to the hardware structure
508 : : * @addr: I2C bus address to read from
509 : : * @reg: I2C device register to read from
510 : : * @val: pointer to location to receive read value
511 : : *
512 : : * Returns an error code on error.
513 : : **/
514 : 0 : STATIC s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
515 : : u16 reg, u16 *val)
516 : : {
517 : 0 : return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true);
518 : : }
519 : :
520 : : /**
521 : : * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
522 : : * @hw: pointer to the hardware structure
523 : : * @addr: I2C bus address to read from
524 : : * @reg: I2C device register to read from
525 : : * @val: pointer to location to receive read value
526 : : *
527 : : * Returns an error code on error.
528 : : **/
529 : : STATIC s32
530 : 0 : ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
531 : : u16 reg, u16 *val)
532 : : {
533 : 0 : return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false);
534 : : }
535 : :
536 : : /**
537 : : * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
538 : : * @hw: pointer to the hardware structure
539 : : * @addr: I2C bus address to write to
540 : : * @reg: I2C device register to write to
541 : : * @val: value to write
542 : : *
543 : : * Returns an error code on error.
544 : : **/
545 : 0 : STATIC s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
546 : : u8 addr, u16 reg, u16 val)
547 : : {
548 : 0 : return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
549 : : }
550 : :
551 : : /**
552 : : * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
553 : : * @hw: pointer to the hardware structure
554 : : * @addr: I2C bus address to write to
555 : : * @reg: I2C device register to write to
556 : : * @val: value to write
557 : : *
558 : : * Returns an error code on error.
559 : : **/
560 : : STATIC s32
561 : 0 : ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
562 : : u8 addr, u16 reg, u16 val)
563 : : {
564 : 0 : return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false);
565 : : }
566 : :
567 : : /**
568 : : * ixgbe_init_ops_X550EM - Inits func ptrs and MAC type
569 : : * @hw: pointer to hardware structure
570 : : *
571 : : * Initialize the function pointers and for MAC type X550EM.
572 : : * Does not touch the hardware.
573 : : **/
574 : 0 : s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw)
575 : : {
576 : : struct ixgbe_mac_info *mac = &hw->mac;
577 : : struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
578 : : struct ixgbe_phy_info *phy = &hw->phy;
579 : : s32 ret_val;
580 : :
581 : 0 : DEBUGFUNC("ixgbe_init_ops_X550EM");
582 : :
583 : : /* Similar to X550 so start there. */
584 : 0 : ret_val = ixgbe_init_ops_X550(hw);
585 : :
586 : : /* Since this function eventually calls
587 : : * ixgbe_init_ops_540 by design, we are setting
588 : : * the pointers to NULL explicitly here to overwrite
589 : : * the values being set in the x540 function.
590 : : */
591 : : /* Thermal sensor not supported in x550EM */
592 : 0 : mac->ops.get_thermal_sensor_data = NULL;
593 : 0 : mac->ops.init_thermal_sensor_thresh = NULL;
594 : 0 : mac->thermal_sensor_enabled = false;
595 : :
596 : : /* FCOE not supported in x550EM */
597 : 0 : mac->ops.get_san_mac_addr = NULL;
598 : 0 : mac->ops.set_san_mac_addr = NULL;
599 : 0 : mac->ops.get_wwn_prefix = NULL;
600 : 0 : mac->ops.get_fcoe_boot_status = NULL;
601 : :
602 : : /* IPsec not supported in x550EM */
603 : 0 : mac->ops.disable_sec_rx_path = NULL;
604 : 0 : mac->ops.enable_sec_rx_path = NULL;
605 : :
606 : : /* AUTOC register is not present in x550EM. */
607 : 0 : mac->ops.prot_autoc_read = NULL;
608 : 0 : mac->ops.prot_autoc_write = NULL;
609 : :
610 : : /* X550EM bus type is internal*/
611 : 0 : hw->bus.type = ixgbe_bus_type_internal;
612 : 0 : mac->ops.get_bus_info = ixgbe_get_bus_info_X550em;
613 : :
614 : :
615 : 0 : mac->ops.get_media_type = ixgbe_get_media_type_X550em;
616 : 0 : mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em;
617 : 0 : mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em;
618 : 0 : mac->ops.reset_hw = ixgbe_reset_hw_X550em;
619 : 0 : mac->ops.get_supported_physical_layer =
620 : : ixgbe_get_supported_physical_layer_X550em;
621 : :
622 [ # # ]: 0 : if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper)
623 : 0 : mac->ops.setup_fc = ixgbe_setup_fc_generic;
624 : : else
625 : 0 : mac->ops.setup_fc = ixgbe_setup_fc_X550em;
626 : :
627 : : /* PHY */
628 : 0 : phy->ops.init = ixgbe_init_phy_ops_X550em;
629 [ # # # ]: 0 : switch (hw->device_id) {
630 : 0 : case IXGBE_DEV_ID_X550EM_A_1G_T:
631 : : case IXGBE_DEV_ID_X550EM_A_1G_T_L:
632 : 0 : mac->ops.setup_fc = NULL;
633 : 0 : phy->ops.identify = ixgbe_identify_phy_fw;
634 : 0 : phy->ops.set_phy_power = NULL;
635 : 0 : phy->ops.get_firmware_version = NULL;
636 : 0 : break;
637 : 0 : case IXGBE_DEV_ID_X550EM_X_1G_T:
638 : 0 : mac->ops.setup_fc = NULL;
639 : 0 : phy->ops.identify = ixgbe_identify_phy_x550em;
640 : 0 : phy->ops.set_phy_power = NULL;
641 : 0 : break;
642 : 0 : default:
643 : 0 : phy->ops.identify = ixgbe_identify_phy_x550em;
644 : : }
645 : :
646 [ # # ]: 0 : if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
647 : 0 : phy->ops.set_phy_power = NULL;
648 : :
649 : :
650 : : /* EEPROM */
651 : 0 : eeprom->ops.init_params = ixgbe_init_eeprom_params_X540;
652 : 0 : eeprom->ops.read = ixgbe_read_ee_hostif_X550;
653 : 0 : eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550;
654 : 0 : eeprom->ops.write = ixgbe_write_ee_hostif_X550;
655 : 0 : eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550;
656 : 0 : eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
657 : 0 : eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
658 : 0 : eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
659 : :
660 : 0 : return ret_val;
661 : : }
662 : :
663 : : /**
664 : : * ixgbe_setup_fw_link - Setup firmware-controlled PHYs
665 : : * @hw: pointer to hardware structure
666 : : */
667 : 0 : static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw)
668 : : {
669 : 0 : u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
670 : : s32 rc;
671 : : u16 i;
672 : :
673 [ # # # # ]: 0 : if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
674 : 0 : return 0;
675 : :
676 [ # # # # ]: 0 : if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
677 : 0 : ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
678 : : "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
679 : 0 : return IXGBE_ERR_INVALID_LINK_SETTINGS;
680 : : }
681 : :
682 [ # # # # ]: 0 : switch (hw->fc.requested_mode) {
683 : 0 : case ixgbe_fc_full:
684 : 0 : setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX <<
685 : : FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
686 : 0 : break;
687 : 0 : case ixgbe_fc_rx_pause:
688 : 0 : setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX <<
689 : : FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
690 : 0 : break;
691 : 0 : case ixgbe_fc_tx_pause:
692 : 0 : setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX <<
693 : : FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
694 : 0 : break;
695 : : default:
696 : : break;
697 : : }
698 : :
699 [ # # ]: 0 : for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) {
700 [ # # ]: 0 : if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed)
701 : 0 : setup[0] |= (u32)(ixgbe_fw_map[i].fw_speed);
702 : : }
703 : 0 : setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN;
704 : :
705 [ # # ]: 0 : if (hw->phy.eee_speeds_advertised)
706 : 0 : setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE;
707 : :
708 : 0 : rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);
709 [ # # ]: 0 : if (rc)
710 : : return rc;
711 [ # # ]: 0 : if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
712 : 0 : return IXGBE_ERR_OVERTEMP;
713 : : return IXGBE_SUCCESS;
714 : : }
715 : :
716 : : /**
717 : : * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs
718 : : * @hw: pointer to hardware structure
719 : : *
720 : : * Called at init time to set up flow control.
721 : : */
722 : 0 : static s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw)
723 : : {
724 [ # # ]: 0 : if (hw->fc.requested_mode == ixgbe_fc_default)
725 : 0 : hw->fc.requested_mode = ixgbe_fc_full;
726 : :
727 : 0 : return ixgbe_setup_fw_link(hw);
728 : : }
729 : :
730 : : /**
731 : : * ixgbe_setup_eee_fw - Enable/disable EEE support
732 : : * @hw: pointer to the HW structure
733 : : * @enable_eee: boolean flag to enable EEE
734 : : *
735 : : * Enable/disable EEE based on enable_eee flag.
736 : : * This function controls EEE for firmware-based PHY implementations.
737 : : */
738 : 0 : static s32 ixgbe_setup_eee_fw(struct ixgbe_hw *hw, bool enable_eee)
739 : : {
740 [ # # ]: 0 : if (!!hw->phy.eee_speeds_advertised == enable_eee)
741 : : return IXGBE_SUCCESS;
742 [ # # ]: 0 : if (enable_eee)
743 : 0 : hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
744 : : else
745 : 0 : hw->phy.eee_speeds_advertised = 0;
746 : 0 : return hw->phy.ops.setup_link(hw);
747 : : }
748 : :
749 : : /**
750 : : * ixgbe_init_ops_X550EM_a - Inits func ptrs and MAC type
751 : : * @hw: pointer to hardware structure
752 : : *
753 : : * Initialize the function pointers and for MAC type X550EM_a.
754 : : * Does not touch the hardware.
755 : : **/
756 : 0 : s32 ixgbe_init_ops_X550EM_a(struct ixgbe_hw *hw)
757 : : {
758 : : struct ixgbe_mac_info *mac = &hw->mac;
759 : : s32 ret_val;
760 : :
761 : 0 : DEBUGFUNC("ixgbe_init_ops_X550EM_a");
762 : :
763 : : /* Start with generic X550EM init */
764 : 0 : ret_val = ixgbe_init_ops_X550EM(hw);
765 : :
766 : 0 : mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
767 : 0 : mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
768 : 0 : mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550a;
769 : 0 : mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550a;
770 : :
771 [ # # # ]: 0 : switch (mac->ops.get_media_type(hw)) {
772 : 0 : case ixgbe_media_type_fiber:
773 : 0 : mac->ops.setup_fc = NULL;
774 : 0 : mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;
775 : 0 : break;
776 : 0 : case ixgbe_media_type_backplane:
777 : 0 : mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;
778 : 0 : mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;
779 : 0 : break;
780 : : default:
781 : : break;
782 : : }
783 : :
784 [ # # ]: 0 : switch (hw->device_id) {
785 : 0 : case IXGBE_DEV_ID_X550EM_A_1G_T:
786 : : case IXGBE_DEV_ID_X550EM_A_1G_T_L:
787 : 0 : mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a;
788 : 0 : mac->ops.setup_fc = ixgbe_fc_autoneg_fw;
789 : 0 : mac->ops.setup_eee = ixgbe_setup_eee_fw;
790 : 0 : hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL |
791 : : IXGBE_LINK_SPEED_1GB_FULL;
792 : 0 : hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
793 : 0 : break;
794 : : default:
795 : : break;
796 : : }
797 : :
798 : 0 : return ret_val;
799 : : }
800 : :
801 : : /**
802 : : * ixgbe_init_ops_X550EM_x - Inits func ptrs and MAC type
803 : : * @hw: pointer to hardware structure
804 : : *
805 : : * Initialize the function pointers and for MAC type X550EM_x.
806 : : * Does not touch the hardware.
807 : : **/
808 : 0 : s32 ixgbe_init_ops_X550EM_x(struct ixgbe_hw *hw)
809 : : {
810 : : struct ixgbe_mac_info *mac = &hw->mac;
811 : : struct ixgbe_link_info *link = &hw->link;
812 : : s32 ret_val;
813 : :
814 : 0 : DEBUGFUNC("ixgbe_init_ops_X550EM_x");
815 : :
816 : : /* Start with generic X550EM init */
817 : 0 : ret_val = ixgbe_init_ops_X550EM(hw);
818 : :
819 : 0 : mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
820 : 0 : mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
821 : 0 : mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550em;
822 : 0 : mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550em;
823 : 0 : link->ops.read_link = ixgbe_read_i2c_combined_generic;
824 : 0 : link->ops.read_link_unlocked = ixgbe_read_i2c_combined_generic_unlocked;
825 : 0 : link->ops.write_link = ixgbe_write_i2c_combined_generic;
826 : 0 : link->ops.write_link_unlocked =
827 : : ixgbe_write_i2c_combined_generic_unlocked;
828 : 0 : link->addr = IXGBE_CS4227;
829 : :
830 [ # # ]: 0 : if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T) {
831 : 0 : mac->ops.setup_fc = NULL;
832 : 0 : mac->ops.setup_eee = NULL;
833 : 0 : mac->ops.init_led_link_act = NULL;
834 : : }
835 : :
836 : 0 : return ret_val;
837 : : }
838 : :
839 : : /**
840 : : * ixgbe_dmac_config_X550
841 : : * @hw: pointer to hardware structure
842 : : *
843 : : * Configure DMA coalescing. If enabling dmac, dmac is activated.
844 : : * When disabling dmac, dmac enable dmac bit is cleared.
845 : : **/
846 : 0 : s32 ixgbe_dmac_config_X550(struct ixgbe_hw *hw)
847 : : {
848 : : u32 reg, high_pri_tc;
849 : :
850 : 0 : DEBUGFUNC("ixgbe_dmac_config_X550");
851 : :
852 : : /* Disable DMA coalescing before configuring */
853 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
854 : 0 : reg &= ~IXGBE_DMACR_DMAC_EN;
855 : 0 : IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
856 : :
857 : : /* Disable DMA Coalescing if the watchdog timer is 0 */
858 [ # # ]: 0 : if (!hw->mac.dmac_config.watchdog_timer)
859 : 0 : goto out;
860 : :
861 : 0 : ixgbe_dmac_config_tcs_X550(hw);
862 : :
863 : : /* Configure DMA Coalescing Control Register */
864 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
865 : :
866 : : /* Set the watchdog timer in units of 40.96 usec */
867 : 0 : reg &= ~IXGBE_DMACR_DMACWT_MASK;
868 : 0 : reg |= (hw->mac.dmac_config.watchdog_timer * 100) / 4096;
869 : :
870 : 0 : reg &= ~IXGBE_DMACR_HIGH_PRI_TC_MASK;
871 : : /* If fcoe is enabled, set high priority traffic class */
872 [ # # ]: 0 : if (hw->mac.dmac_config.fcoe_en) {
873 : 0 : high_pri_tc = 1 << hw->mac.dmac_config.fcoe_tc;
874 : 0 : reg |= ((high_pri_tc << IXGBE_DMACR_HIGH_PRI_TC_SHIFT) &
875 : : IXGBE_DMACR_HIGH_PRI_TC_MASK);
876 : : }
877 : : reg |= IXGBE_DMACR_EN_MNG_IND;
878 : :
879 : : /* Enable DMA coalescing after configuration */
880 : 0 : reg |= IXGBE_DMACR_DMAC_EN;
881 : 0 : IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
882 : :
883 : 0 : out:
884 : 0 : return IXGBE_SUCCESS;
885 : : }
886 : :
887 : : /**
888 : : * ixgbe_dmac_config_tcs_X550
889 : : * @hw: pointer to hardware structure
890 : : *
891 : : * Configure DMA coalescing threshold per TC. The dmac enable bit must
892 : : * be cleared before configuring.
893 : : **/
894 : 0 : s32 ixgbe_dmac_config_tcs_X550(struct ixgbe_hw *hw)
895 : : {
896 : : u32 tc, reg, pb_headroom, rx_pb_size, maxframe_size_kb;
897 : :
898 : 0 : DEBUGFUNC("ixgbe_dmac_config_tcs_X550");
899 : :
900 : : /* Configure DMA coalescing enabled */
901 [ # # # ]: 0 : switch (hw->mac.dmac_config.link_speed) {
902 : : case IXGBE_LINK_SPEED_10_FULL:
903 : : case IXGBE_LINK_SPEED_100_FULL:
904 : : pb_headroom = IXGBE_DMACRXT_100M;
905 : : break;
906 : 0 : case IXGBE_LINK_SPEED_1GB_FULL:
907 : : pb_headroom = IXGBE_DMACRXT_1G;
908 : 0 : break;
909 : 0 : default:
910 : : pb_headroom = IXGBE_DMACRXT_10G;
911 : 0 : break;
912 : : }
913 : :
914 : 0 : maxframe_size_kb = ((IXGBE_READ_REG(hw, IXGBE_MAXFRS) >>
915 : : IXGBE_MHADD_MFS_SHIFT) / 1024);
916 : :
917 : : /* Set the per Rx packet buffer receive threshold */
918 [ # # ]: 0 : for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) {
919 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_DMCTH(tc));
920 : 0 : reg &= ~IXGBE_DMCTH_DMACRXT_MASK;
921 : :
922 [ # # ]: 0 : if (tc < hw->mac.dmac_config.num_tcs) {
923 : : /* Get Rx PB size */
924 : 0 : rx_pb_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(tc));
925 : 0 : rx_pb_size = (rx_pb_size & IXGBE_RXPBSIZE_MASK) >>
926 : : IXGBE_RXPBSIZE_SHIFT;
927 : :
928 : : /* Calculate receive buffer threshold in kilobytes */
929 [ # # ]: 0 : if (rx_pb_size > pb_headroom)
930 : 0 : rx_pb_size = rx_pb_size - pb_headroom;
931 : : else
932 : : rx_pb_size = 0;
933 : :
934 : : /* Minimum of MFS shall be set for DMCTH */
935 : 0 : reg |= (rx_pb_size > maxframe_size_kb) ?
936 : 0 : rx_pb_size : maxframe_size_kb;
937 : : }
938 : 0 : IXGBE_WRITE_REG(hw, IXGBE_DMCTH(tc), reg);
939 : : }
940 : 0 : return IXGBE_SUCCESS;
941 : : }
942 : :
943 : : /**
944 : : * ixgbe_dmac_update_tcs_X550
945 : : * @hw: pointer to hardware structure
946 : : *
947 : : * Disables dmac, updates per TC settings, and then enables dmac.
948 : : **/
949 : 0 : s32 ixgbe_dmac_update_tcs_X550(struct ixgbe_hw *hw)
950 : : {
951 : : u32 reg;
952 : :
953 : 0 : DEBUGFUNC("ixgbe_dmac_update_tcs_X550");
954 : :
955 : : /* Disable DMA coalescing before configuring */
956 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
957 : 0 : reg &= ~IXGBE_DMACR_DMAC_EN;
958 : 0 : IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
959 : :
960 : 0 : ixgbe_dmac_config_tcs_X550(hw);
961 : :
962 : : /* Enable DMA coalescing after configuration */
963 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_DMACR);
964 : 0 : reg |= IXGBE_DMACR_DMAC_EN;
965 : 0 : IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg);
966 : :
967 : 0 : return IXGBE_SUCCESS;
968 : : }
969 : :
970 : : /**
971 : : * ixgbe_init_eeprom_params_X550 - Initialize EEPROM params
972 : : * @hw: pointer to hardware structure
973 : : *
974 : : * Initializes the EEPROM parameters ixgbe_eeprom_info within the
975 : : * ixgbe_hw struct in order to set up EEPROM access.
976 : : **/
977 : 0 : s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
978 : : {
979 : : struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
980 : : u32 eec;
981 : : u16 eeprom_size;
982 : :
983 : 0 : DEBUGFUNC("ixgbe_init_eeprom_params_X550");
984 : :
985 [ # # ]: 0 : if (eeprom->type == ixgbe_eeprom_uninitialized) {
986 : 0 : eeprom->semaphore_delay = 10;
987 : 0 : eeprom->type = ixgbe_flash;
988 : :
989 : 0 : eec = IXGBE_READ_REG(hw, IXGBE_EEC);
990 : 0 : eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
991 : : IXGBE_EEC_SIZE_SHIFT);
992 : 0 : eeprom->word_size = 1 << (eeprom_size +
993 : : IXGBE_EEPROM_WORD_SIZE_SHIFT);
994 : :
995 : 0 : DEBUGOUT2("Eeprom params: type = %d, size = %d\n",
996 : : eeprom->type, eeprom->word_size);
997 : : }
998 : :
999 : 0 : return IXGBE_SUCCESS;
1000 : : }
1001 : :
1002 : : /**
1003 : : * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning
1004 : : * @hw: pointer to hardware structure
1005 : : * @enable: enable or disable source address pruning
1006 : : * @pool: Rx pool to set source address pruning for
1007 : : **/
1008 : 0 : void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable,
1009 : : unsigned int pool)
1010 : : {
1011 : : u64 pfflp;
1012 : :
1013 : : /* max rx pool is 63 */
1014 [ # # ]: 0 : if (pool > 63)
1015 : : return;
1016 : :
1017 : 0 : pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL);
1018 : 0 : pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32;
1019 : :
1020 [ # # ]: 0 : if (enable)
1021 : 0 : pfflp |= (1ULL << pool);
1022 : : else
1023 : 0 : pfflp &= ~(1ULL << pool);
1024 : :
1025 : 0 : IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp);
1026 : 0 : IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32));
1027 : : }
1028 : :
1029 : : /**
1030 : : * ixgbe_set_ethertype_anti_spoofing_X550 - Configure Ethertype anti-spoofing
1031 : : * @hw: pointer to hardware structure
1032 : : * @enable: enable or disable switch for Ethertype anti-spoofing
1033 : : * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing
1034 : : *
1035 : : **/
1036 : 0 : void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
1037 : : bool enable, int vf)
1038 : : {
1039 : 0 : int vf_target_reg = vf >> 3;
1040 : 0 : int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT;
1041 : : u32 pfvfspoof;
1042 : :
1043 : 0 : DEBUGFUNC("ixgbe_set_ethertype_anti_spoofing_X550");
1044 : :
1045 : 0 : pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
1046 [ # # ]: 0 : if (enable)
1047 : 0 : pfvfspoof |= (1 << vf_target_shift);
1048 : : else
1049 : 0 : pfvfspoof &= ~(1 << vf_target_shift);
1050 : :
1051 : 0 : IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
1052 : 0 : }
1053 : :
1054 : : /**
1055 : : * ixgbe_iosf_wait - Wait for IOSF command completion
1056 : : * @hw: pointer to hardware structure
1057 : : * @ctrl: pointer to location to receive final IOSF control value
1058 : : *
1059 : : * Returns failing status on timeout
1060 : : *
1061 : : * Note: ctrl can be NULL if the IOSF control register value is not needed
1062 : : **/
1063 : 0 : STATIC s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl)
1064 : : {
1065 : : u32 i, command = 0;
1066 : :
1067 : : /* Check every 10 usec to see if the address cycle completed.
1068 : : * The SB IOSF BUSY bit will clear when the operation is
1069 : : * complete
1070 : : */
1071 [ # # ]: 0 : for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
1072 : 0 : command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
1073 [ # # ]: 0 : if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0)
1074 : : break;
1075 : 0 : usec_delay(10);
1076 : : }
1077 [ # # ]: 0 : if (ctrl)
1078 : 0 : *ctrl = command;
1079 [ # # ]: 0 : if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
1080 : 0 : ERROR_REPORT1(IXGBE_ERROR_POLLING, "Wait timed out\n");
1081 : 0 : return IXGBE_ERR_PHY;
1082 : : }
1083 : :
1084 : : return IXGBE_SUCCESS;
1085 : : }
1086 : :
1087 : : /**
1088 : : * ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register
1089 : : * of the IOSF device
1090 : : * @hw: pointer to hardware structure
1091 : : * @reg_addr: 32 bit PHY register to write
1092 : : * @device_type: 3 bit device type
1093 : : * @data: Data to write to the register
1094 : : **/
1095 : 0 : s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
1096 : : u32 device_type, u32 data)
1097 : : {
1098 : : u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
1099 : : u32 command, error;
1100 : : s32 ret;
1101 : :
1102 : 0 : ret = ixgbe_acquire_swfw_semaphore(hw, gssr);
1103 [ # # ]: 0 : if (ret != IXGBE_SUCCESS)
1104 : : return ret;
1105 : :
1106 : 0 : ret = ixgbe_iosf_wait(hw, NULL);
1107 [ # # ]: 0 : if (ret != IXGBE_SUCCESS)
1108 : 0 : goto out;
1109 : :
1110 : 0 : command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
1111 : 0 : (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
1112 : :
1113 : : /* Write IOSF control register */
1114 : 0 : IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
1115 : :
1116 : : /* Write IOSF data register */
1117 : 0 : IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data);
1118 : :
1119 : 0 : ret = ixgbe_iosf_wait(hw, &command);
1120 : :
1121 [ # # ]: 0 : if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
1122 : 0 : error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
1123 : : IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
1124 : 0 : ERROR_REPORT2(IXGBE_ERROR_POLLING,
1125 : : "Failed to write, error %x\n", error);
1126 : : ret = IXGBE_ERR_PHY;
1127 : : }
1128 : :
1129 : 0 : out:
1130 : 0 : ixgbe_release_swfw_semaphore(hw, gssr);
1131 : 0 : return ret;
1132 : : }
1133 : :
1134 : : /**
1135 : : * ixgbe_read_iosf_sb_reg_x550 - Reads specified register of the IOSF device
1136 : : * @hw: pointer to hardware structure
1137 : : * @reg_addr: 32 bit PHY register to write
1138 : : * @device_type: 3 bit device type
1139 : : * @data: Pointer to read data from the register
1140 : : **/
1141 : 0 : s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
1142 : : u32 device_type, u32 *data)
1143 : : {
1144 : : u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
1145 : : u32 command, error;
1146 : : s32 ret;
1147 : :
1148 : 0 : ret = ixgbe_acquire_swfw_semaphore(hw, gssr);
1149 [ # # ]: 0 : if (ret != IXGBE_SUCCESS)
1150 : : return ret;
1151 : :
1152 : 0 : ret = ixgbe_iosf_wait(hw, NULL);
1153 [ # # ]: 0 : if (ret != IXGBE_SUCCESS)
1154 : 0 : goto out;
1155 : :
1156 : 0 : command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
1157 : 0 : (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
1158 : :
1159 : : /* Write IOSF control register */
1160 : 0 : IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
1161 : :
1162 : 0 : ret = ixgbe_iosf_wait(hw, &command);
1163 : :
1164 [ # # ]: 0 : if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
1165 : 0 : error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
1166 : : IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
1167 : 0 : ERROR_REPORT2(IXGBE_ERROR_POLLING,
1168 : : "Failed to read, error %x\n", error);
1169 : : ret = IXGBE_ERR_PHY;
1170 : : }
1171 : :
1172 [ # # ]: 0 : if (ret == IXGBE_SUCCESS)
1173 : 0 : *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
1174 : :
1175 : 0 : out:
1176 : 0 : ixgbe_release_swfw_semaphore(hw, gssr);
1177 : 0 : return ret;
1178 : : }
1179 : :
1180 : : /**
1181 : : * ixgbe_get_phy_token - Get the token for shared phy access
1182 : : * @hw: Pointer to hardware structure
1183 : : */
1184 : :
1185 : 0 : s32 ixgbe_get_phy_token(struct ixgbe_hw *hw)
1186 : : {
1187 : : struct ixgbe_hic_phy_token_req token_cmd;
1188 : : s32 status;
1189 : :
1190 : 0 : token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
1191 : 0 : token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
1192 : 0 : token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
1193 : 0 : token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
1194 : 0 : token_cmd.port_number = hw->bus.lan_id;
1195 : 0 : token_cmd.command_type = FW_PHY_TOKEN_REQ;
1196 : 0 : token_cmd.pad = 0;
1197 : 0 : status = ixgbe_host_interface_command(hw, (u32 *)&token_cmd,
1198 : : sizeof(token_cmd),
1199 : : IXGBE_HI_COMMAND_TIMEOUT,
1200 : : true);
1201 [ # # ]: 0 : if (status) {
1202 : 0 : DEBUGOUT1("Issuing host interface command failed with Status = %d\n",
1203 : : status);
1204 : 0 : return status;
1205 : : }
1206 [ # # ]: 0 : if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
1207 : : return IXGBE_SUCCESS;
1208 [ # # ]: 0 : if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) {
1209 : 0 : DEBUGOUT1("Host interface command returned 0x%08x , returning IXGBE_ERR_FW_RESP_INVALID\n",
1210 : : token_cmd.hdr.cmd_or_resp.ret_status);
1211 : 0 : return IXGBE_ERR_FW_RESP_INVALID;
1212 : : }
1213 : :
1214 : 0 : DEBUGOUT("Returning IXGBE_ERR_TOKEN_RETRY\n");
1215 : 0 : return IXGBE_ERR_TOKEN_RETRY;
1216 : : }
1217 : :
1218 : : /**
1219 : : * ixgbe_put_phy_token - Put the token for shared phy access
1220 : : * @hw: Pointer to hardware structure
1221 : : */
1222 : :
1223 : 0 : s32 ixgbe_put_phy_token(struct ixgbe_hw *hw)
1224 : : {
1225 : : struct ixgbe_hic_phy_token_req token_cmd;
1226 : : s32 status;
1227 : :
1228 : 0 : token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
1229 : 0 : token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
1230 : 0 : token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
1231 : 0 : token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
1232 : 0 : token_cmd.port_number = hw->bus.lan_id;
1233 : 0 : token_cmd.command_type = FW_PHY_TOKEN_REL;
1234 : 0 : token_cmd.pad = 0;
1235 : 0 : status = ixgbe_host_interface_command(hw, (u32 *)&token_cmd,
1236 : : sizeof(token_cmd),
1237 : : IXGBE_HI_COMMAND_TIMEOUT,
1238 : : true);
1239 [ # # ]: 0 : if (status)
1240 : : return status;
1241 [ # # ]: 0 : if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
1242 : : return IXGBE_SUCCESS;
1243 : :
1244 : 0 : DEBUGOUT("Put PHY Token host interface command failed");
1245 : 0 : return IXGBE_ERR_FW_RESP_INVALID;
1246 : : }
1247 : :
1248 : : /**
1249 : : * ixgbe_disable_mdd_X550
1250 : : * @hw: pointer to hardware structure
1251 : : *
1252 : : * Disable malicious driver detection
1253 : : **/
1254 : 0 : void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw)
1255 : : {
1256 : : u32 reg;
1257 : :
1258 : 0 : DEBUGFUNC("ixgbe_disable_mdd_X550");
1259 : :
1260 : : /* Disable MDD for TX DMA and interrupt */
1261 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
1262 : 0 : reg &= ~(IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN);
1263 : 0 : IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg);
1264 : :
1265 : : /* Disable MDD for RX and interrupt */
1266 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
1267 : 0 : reg &= ~(IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN);
1268 : 0 : IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg);
1269 : 0 : }
1270 : :
1271 : : /**
1272 : : * ixgbe_enable_mdd_X550
1273 : : * @hw: pointer to hardware structure
1274 : : *
1275 : : * Enable malicious driver detection
1276 : : **/
1277 : 0 : void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw)
1278 : : {
1279 : : u32 reg;
1280 : :
1281 : 0 : DEBUGFUNC("ixgbe_enable_mdd_X550");
1282 : :
1283 : : /* Enable MDD for TX DMA and interrupt */
1284 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
1285 : 0 : reg |= (IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN);
1286 : 0 : IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg);
1287 : :
1288 : : /* Enable MDD for RX and interrupt */
1289 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
1290 : 0 : reg |= (IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN);
1291 : 0 : IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg);
1292 : 0 : }
1293 : :
1294 : : /**
1295 : : * ixgbe_restore_mdd_vf_X550
1296 : : * @hw: pointer to hardware structure
1297 : : * @vf: vf index
1298 : : *
1299 : : * Restore VF that was disabled during malicious driver detection event
1300 : : **/
1301 : 0 : void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf)
1302 : : {
1303 : : u32 idx, reg, num_qs, start_q, bitmask;
1304 : :
1305 : 0 : DEBUGFUNC("ixgbe_restore_mdd_vf_X550");
1306 : :
1307 : : /* Map VF to queues */
1308 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_MRQC);
1309 [ # # # ]: 0 : switch (reg & IXGBE_MRQC_MRQE_MASK) {
1310 : : case IXGBE_MRQC_VMDQRT8TCEN:
1311 : : num_qs = 8; /* 16 VFs / pools */
1312 : : bitmask = 0x000000FF;
1313 : : break;
1314 : 0 : case IXGBE_MRQC_VMDQRSS32EN:
1315 : : case IXGBE_MRQC_VMDQRT4TCEN:
1316 : : num_qs = 4; /* 32 VFs / pools */
1317 : : bitmask = 0x0000000F;
1318 : 0 : break;
1319 : 0 : default: /* 64 VFs / pools */
1320 : : num_qs = 2;
1321 : : bitmask = 0x00000003;
1322 : 0 : break;
1323 : : }
1324 : 0 : start_q = vf * num_qs;
1325 : :
1326 : : /* Release vf's queues by clearing WQBR_TX and WQBR_RX (RW1C) */
1327 : 0 : idx = start_q / 32;
1328 : : reg = 0;
1329 : 0 : reg |= (bitmask << (start_q % 32));
1330 : 0 : IXGBE_WRITE_REG(hw, IXGBE_WQBR_TX(idx), reg);
1331 : 0 : IXGBE_WRITE_REG(hw, IXGBE_WQBR_RX(idx), reg);
1332 : 0 : }
1333 : :
1334 : : /**
1335 : : * ixgbe_mdd_event_X550
1336 : : * @hw: pointer to hardware structure
1337 : : * @vf_bitmap: vf bitmap of malicious vfs
1338 : : *
1339 : : * Handle malicious driver detection event.
1340 : : **/
1341 : 0 : void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap)
1342 : : {
1343 : : u32 wqbr;
1344 : : u32 i, j, reg, q, shift, vf, idx;
1345 : :
1346 : 0 : DEBUGFUNC("ixgbe_mdd_event_X550");
1347 : :
1348 : : /* figure out pool size for mapping to vf's */
1349 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_MRQC);
1350 [ # # # ]: 0 : switch (reg & IXGBE_MRQC_MRQE_MASK) {
1351 : : case IXGBE_MRQC_VMDQRT8TCEN:
1352 : : shift = 3; /* 16 VFs / pools */
1353 : : break;
1354 : 0 : case IXGBE_MRQC_VMDQRSS32EN:
1355 : : case IXGBE_MRQC_VMDQRT4TCEN:
1356 : : shift = 2; /* 32 VFs / pools */
1357 : 0 : break;
1358 : 0 : default:
1359 : : shift = 1; /* 64 VFs / pools */
1360 : 0 : break;
1361 : : }
1362 : :
1363 : : /* Read WQBR_TX and WQBR_RX and check for malicious queues */
1364 [ # # ]: 0 : for (i = 0; i < 4; i++) {
1365 : 0 : wqbr = IXGBE_READ_REG(hw, IXGBE_WQBR_TX(i));
1366 : 0 : wqbr |= IXGBE_READ_REG(hw, IXGBE_WQBR_RX(i));
1367 : :
1368 [ # # ]: 0 : if (!wqbr)
1369 : 0 : continue;
1370 : :
1371 : : /* Get malicious queue */
1372 [ # # ]: 0 : for (j = 0; j < 32 && wqbr; j++) {
1373 : :
1374 [ # # ]: 0 : if (!(wqbr & (1 << j)))
1375 : 0 : continue;
1376 : :
1377 : : /* Get queue from bitmask */
1378 : 0 : q = j + (i * 32);
1379 : :
1380 : : /* Map queue to vf */
1381 : 0 : vf = (q >> shift);
1382 : :
1383 : : /* Set vf bit in vf_bitmap */
1384 : 0 : idx = vf / 32;
1385 : 0 : vf_bitmap[idx] |= (1 << (vf % 32));
1386 : 0 : wqbr &= ~(1 << j);
1387 : : }
1388 : : }
1389 : 0 : }
1390 : :
1391 : : /**
1392 : : * ixgbe_get_media_type_X550em - Get media type
1393 : : * @hw: pointer to hardware structure
1394 : : *
1395 : : * Returns the media type (fiber, copper, backplane)
1396 : : */
1397 : 0 : enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
1398 : : {
1399 : : enum ixgbe_media_type media_type;
1400 : :
1401 : 0 : DEBUGFUNC("ixgbe_get_media_type_X550em");
1402 : :
1403 : : /* Detect if there is a copper PHY attached. */
1404 [ # # # # : 0 : switch (hw->device_id) {
# # ]
1405 : : case IXGBE_DEV_ID_X550EM_X_KR:
1406 : : case IXGBE_DEV_ID_X550EM_X_KX4:
1407 : : case IXGBE_DEV_ID_X550EM_X_XFI:
1408 : : case IXGBE_DEV_ID_X550EM_A_KR:
1409 : : case IXGBE_DEV_ID_X550EM_A_KR_L:
1410 : : media_type = ixgbe_media_type_backplane;
1411 : : break;
1412 : 0 : case IXGBE_DEV_ID_X550EM_X_SFP:
1413 : : case IXGBE_DEV_ID_X550EM_A_SFP:
1414 : : case IXGBE_DEV_ID_X550EM_A_SFP_N:
1415 : : case IXGBE_DEV_ID_X550EM_A_QSFP:
1416 : : case IXGBE_DEV_ID_X550EM_A_QSFP_N:
1417 : : media_type = ixgbe_media_type_fiber;
1418 : 0 : break;
1419 : 0 : case IXGBE_DEV_ID_X550EM_X_1G_T:
1420 : : case IXGBE_DEV_ID_X550EM_X_10G_T:
1421 : : case IXGBE_DEV_ID_X550EM_A_10G_T:
1422 : : media_type = ixgbe_media_type_copper;
1423 : 0 : break;
1424 : 0 : case IXGBE_DEV_ID_X550EM_A_SGMII:
1425 : : case IXGBE_DEV_ID_X550EM_A_SGMII_L:
1426 : : media_type = ixgbe_media_type_backplane;
1427 : 0 : hw->phy.type = ixgbe_phy_sgmii;
1428 : 0 : break;
1429 : 0 : case IXGBE_DEV_ID_X550EM_A_1G_T:
1430 : : case IXGBE_DEV_ID_X550EM_A_1G_T_L:
1431 : : media_type = ixgbe_media_type_copper;
1432 : 0 : break;
1433 : 0 : default:
1434 : : media_type = ixgbe_media_type_unknown;
1435 : 0 : break;
1436 : : }
1437 : 0 : return media_type;
1438 : : }
1439 : :
1440 : : /**
1441 : : * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported
1442 : : * @hw: pointer to hardware structure
1443 : : * @linear: true if SFP module is linear
1444 : : */
1445 : 0 : STATIC s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear)
1446 : : {
1447 : 0 : DEBUGFUNC("ixgbe_supported_sfp_modules_X550em");
1448 : :
1449 [ # # # # ]: 0 : switch (hw->phy.sfp_type) {
1450 : : case ixgbe_sfp_type_not_present:
1451 : : return IXGBE_ERR_SFP_NOT_PRESENT;
1452 : 0 : case ixgbe_sfp_type_da_cu_core0:
1453 : : case ixgbe_sfp_type_da_cu_core1:
1454 : 0 : *linear = true;
1455 : 0 : break;
1456 : 0 : case ixgbe_sfp_type_srlr_core0:
1457 : : case ixgbe_sfp_type_srlr_core1:
1458 : : case ixgbe_sfp_type_da_act_lmt_core0:
1459 : : case ixgbe_sfp_type_da_act_lmt_core1:
1460 : : case ixgbe_sfp_type_1g_sx_core0:
1461 : : case ixgbe_sfp_type_1g_sx_core1:
1462 : : case ixgbe_sfp_type_1g_lx_core0:
1463 : : case ixgbe_sfp_type_1g_lx_core1:
1464 : : case ixgbe_sfp_type_1g_lha_core0:
1465 : : case ixgbe_sfp_type_1g_lha_core1:
1466 : 0 : *linear = false;
1467 : 0 : break;
1468 : 0 : case ixgbe_sfp_type_unknown:
1469 : : case ixgbe_sfp_type_1g_cu_core0:
1470 : : case ixgbe_sfp_type_1g_cu_core1:
1471 : : default:
1472 : 0 : return IXGBE_ERR_SFP_NOT_SUPPORTED;
1473 : : }
1474 : :
1475 : : return IXGBE_SUCCESS;
1476 : : }
1477 : :
1478 : : /**
1479 : : * ixgbe_identify_sfp_module_X550em - Identifies SFP modules
1480 : : * @hw: pointer to hardware structure
1481 : : *
1482 : : * Searches for and identifies the SFP module and assigns appropriate PHY type.
1483 : : **/
1484 : 0 : s32 ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw)
1485 : : {
1486 : : s32 status;
1487 : : bool linear;
1488 : :
1489 : 0 : DEBUGFUNC("ixgbe_identify_sfp_module_X550em");
1490 : :
1491 : 0 : status = ixgbe_identify_module_generic(hw);
1492 : :
1493 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
1494 : : return status;
1495 : :
1496 : : /* Check if SFP module is supported */
1497 : 0 : status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
1498 : :
1499 : 0 : return status;
1500 : : }
1501 : :
1502 : : /**
1503 : : * ixgbe_setup_sfp_modules_X550em - Setup MAC link ops
1504 : : * @hw: pointer to hardware structure
1505 : : */
1506 : 0 : s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
1507 : : {
1508 : : s32 status;
1509 : : bool linear;
1510 : :
1511 : 0 : DEBUGFUNC("ixgbe_setup_sfp_modules_X550em");
1512 : :
1513 : : /* Check if SFP module is supported */
1514 : 0 : status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
1515 : :
1516 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
1517 : : return status;
1518 : :
1519 : 0 : ixgbe_init_mac_link_ops_X550em(hw);
1520 : 0 : hw->phy.ops.reset = NULL;
1521 : :
1522 : 0 : return IXGBE_SUCCESS;
1523 : : }
1524 : :
1525 : : /**
1526 : : * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the
1527 : : * internal PHY
1528 : : * @hw: pointer to hardware structure
1529 : : **/
1530 : 0 : STATIC s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
1531 : : {
1532 : : s32 status;
1533 : : u32 link_ctrl;
1534 : :
1535 : : /* Restart auto-negotiation. */
1536 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
1537 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1538 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl);
1539 : :
1540 [ # # ]: 0 : if (status) {
1541 : 0 : DEBUGOUT("Auto-negotiation did not complete\n");
1542 : 0 : return status;
1543 : : }
1544 : :
1545 : 0 : link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
1546 : 0 : status = hw->mac.ops.write_iosf_sb_reg(hw,
1547 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1548 : : IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl);
1549 : :
1550 [ # # ]: 0 : if (hw->mac.type == ixgbe_mac_X550EM_a) {
1551 : : u32 flx_mask_st20;
1552 : :
1553 : : /* Indicate to FW that AN restart has been asserted */
1554 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
1555 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1556 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20);
1557 : :
1558 [ # # ]: 0 : if (status) {
1559 : 0 : DEBUGOUT("Auto-negotiation did not complete\n");
1560 : 0 : return status;
1561 : : }
1562 : :
1563 : 0 : flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART;
1564 : 0 : status = hw->mac.ops.write_iosf_sb_reg(hw,
1565 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1566 : : IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20);
1567 : : }
1568 : :
1569 : : return status;
1570 : : }
1571 : :
1572 : : /**
1573 : : * ixgbe_setup_sgmii - Set up link for sgmii
1574 : : * @hw: pointer to hardware structure
1575 : : * @speed: new link speed
1576 : : * @autoneg_wait: true when waiting for completion is needed
1577 : : */
1578 : 0 : STATIC s32 ixgbe_setup_sgmii(struct ixgbe_hw *hw, ixgbe_link_speed speed,
1579 : : bool autoneg_wait)
1580 : : {
1581 : : struct ixgbe_mac_info *mac = &hw->mac;
1582 : : u32 lval, sval, flx_val;
1583 : : s32 rc;
1584 : :
1585 : 0 : rc = mac->ops.read_iosf_sb_reg(hw,
1586 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1587 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
1588 [ # # ]: 0 : if (rc)
1589 : : return rc;
1590 : :
1591 : 0 : lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
1592 : 0 : lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
1593 : 0 : lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
1594 : 0 : lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
1595 : 0 : lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
1596 : 0 : rc = mac->ops.write_iosf_sb_reg(hw,
1597 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1598 : : IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
1599 [ # # ]: 0 : if (rc)
1600 : : return rc;
1601 : :
1602 : 0 : rc = mac->ops.read_iosf_sb_reg(hw,
1603 [ # # ]: 0 : IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
1604 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
1605 [ # # ]: 0 : if (rc)
1606 : : return rc;
1607 : :
1608 : 0 : sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
1609 : 0 : sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
1610 : 0 : rc = mac->ops.write_iosf_sb_reg(hw,
1611 [ # # ]: 0 : IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
1612 : : IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
1613 [ # # ]: 0 : if (rc)
1614 : : return rc;
1615 : :
1616 : 0 : rc = mac->ops.read_iosf_sb_reg(hw,
1617 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1618 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
1619 [ # # ]: 0 : if (rc)
1620 : : return rc;
1621 : :
1622 : 0 : flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
1623 : 0 : flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
1624 : 0 : flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
1625 : 0 : flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
1626 : 0 : flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
1627 : :
1628 : 0 : rc = mac->ops.write_iosf_sb_reg(hw,
1629 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1630 : : IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
1631 [ # # ]: 0 : if (rc)
1632 : : return rc;
1633 : :
1634 : 0 : rc = ixgbe_restart_an_internal_phy_x550em(hw);
1635 [ # # ]: 0 : if (rc)
1636 : : return rc;
1637 : :
1638 : 0 : return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
1639 : : }
1640 : :
1641 : : /**
1642 : : * ixgbe_setup_sgmii_fw - Set up link for internal PHY SGMII auto-negotiation
1643 : : * @hw: pointer to hardware structure
1644 : : * @speed: new link speed
1645 : : * @autoneg_wait: true when waiting for completion is needed
1646 : : */
1647 : 0 : STATIC s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed,
1648 : : bool autoneg_wait)
1649 : : {
1650 : : struct ixgbe_mac_info *mac = &hw->mac;
1651 : : u32 lval, sval, flx_val;
1652 : : s32 rc;
1653 : :
1654 : 0 : rc = mac->ops.read_iosf_sb_reg(hw,
1655 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1656 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
1657 [ # # ]: 0 : if (rc)
1658 : : return rc;
1659 : :
1660 : 0 : lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
1661 : 0 : lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
1662 : 0 : lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
1663 : 0 : lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
1664 : 0 : lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
1665 : 0 : rc = mac->ops.write_iosf_sb_reg(hw,
1666 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1667 : : IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
1668 [ # # ]: 0 : if (rc)
1669 : : return rc;
1670 : :
1671 : 0 : rc = mac->ops.read_iosf_sb_reg(hw,
1672 [ # # ]: 0 : IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
1673 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
1674 [ # # ]: 0 : if (rc)
1675 : : return rc;
1676 : :
1677 : 0 : sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
1678 : 0 : sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
1679 : 0 : rc = mac->ops.write_iosf_sb_reg(hw,
1680 [ # # ]: 0 : IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
1681 : : IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
1682 [ # # ]: 0 : if (rc)
1683 : : return rc;
1684 : :
1685 : 0 : rc = mac->ops.write_iosf_sb_reg(hw,
1686 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
1687 : : IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
1688 [ # # ]: 0 : if (rc)
1689 : : return rc;
1690 : :
1691 : 0 : rc = mac->ops.read_iosf_sb_reg(hw,
1692 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1693 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
1694 [ # # ]: 0 : if (rc)
1695 : : return rc;
1696 : :
1697 : 0 : flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
1698 : 0 : flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
1699 : 0 : flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
1700 : 0 : flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
1701 : 0 : flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
1702 : :
1703 : 0 : rc = mac->ops.write_iosf_sb_reg(hw,
1704 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
1705 : : IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
1706 [ # # ]: 0 : if (rc)
1707 : : return rc;
1708 : :
1709 : 0 : rc = ixgbe_restart_an_internal_phy_x550em(hw);
1710 : :
1711 : 0 : return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
1712 : : }
1713 : :
1714 : : /**
1715 : : * ixgbe_init_mac_link_ops_X550em - init mac link function pointers
1716 : : * @hw: pointer to hardware structure
1717 : : */
1718 : 0 : void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
1719 : : {
1720 : : struct ixgbe_mac_info *mac = &hw->mac;
1721 : :
1722 : 0 : DEBUGFUNC("ixgbe_init_mac_link_ops_X550em");
1723 : :
1724 [ # # # # ]: 0 : switch (hw->mac.ops.get_media_type(hw)) {
1725 : 0 : case ixgbe_media_type_fiber:
1726 : : /* CS4227 does not support autoneg, so disable the laser control
1727 : : * functions for SFP+ fiber
1728 : : */
1729 : 0 : mac->ops.disable_tx_laser = NULL;
1730 : 0 : mac->ops.enable_tx_laser = NULL;
1731 : 0 : mac->ops.flap_tx_laser = NULL;
1732 : 0 : mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
1733 : 0 : mac->ops.set_rate_select_speed =
1734 : : ixgbe_set_soft_rate_select_speed;
1735 : :
1736 [ # # ]: 0 : if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) ||
1737 : : (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP))
1738 : 0 : mac->ops.setup_mac_link =
1739 : : ixgbe_setup_mac_link_sfp_x550a;
1740 : : else
1741 : 0 : mac->ops.setup_mac_link =
1742 : : ixgbe_setup_mac_link_sfp_x550em;
1743 : : break;
1744 : 0 : case ixgbe_media_type_copper:
1745 [ # # ]: 0 : if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T)
1746 : : break;
1747 [ # # ]: 0 : if (hw->mac.type == ixgbe_mac_X550EM_a) {
1748 [ # # ]: 0 : if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
1749 : : hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) {
1750 : 0 : mac->ops.setup_link = ixgbe_setup_sgmii_fw;
1751 : 0 : mac->ops.check_link =
1752 : : ixgbe_check_mac_link_generic;
1753 : : } else {
1754 : 0 : mac->ops.setup_link =
1755 : : ixgbe_setup_mac_link_t_X550em;
1756 : : }
1757 : : } else {
1758 : 0 : mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
1759 : 0 : mac->ops.check_link = ixgbe_check_link_t_X550em;
1760 : : }
1761 : : break;
1762 : 0 : case ixgbe_media_type_backplane:
1763 [ # # ]: 0 : if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
1764 : : hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)
1765 : 0 : mac->ops.setup_link = ixgbe_setup_sgmii;
1766 : : break;
1767 : : default:
1768 : : break;
1769 : : }
1770 : 0 : }
1771 : :
1772 : : /**
1773 : : * ixgbe_get_link_capabilities_X550em - Determines link capabilities
1774 : : * @hw: pointer to hardware structure
1775 : : * @speed: pointer to link speed
1776 : : * @autoneg: true when autoneg or autotry is enabled
1777 : : */
1778 : 0 : s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
1779 : : ixgbe_link_speed *speed,
1780 : : bool *autoneg)
1781 : : {
1782 : 0 : DEBUGFUNC("ixgbe_get_link_capabilities_X550em");
1783 : :
1784 : :
1785 [ # # ]: 0 : if (hw->phy.type == ixgbe_phy_fw) {
1786 : 0 : *autoneg = true;
1787 : 0 : *speed = hw->phy.speeds_supported;
1788 : 0 : return 0;
1789 : : }
1790 : :
1791 : : /* SFP */
1792 [ # # ]: 0 : if (hw->phy.media_type == ixgbe_media_type_fiber) {
1793 : :
1794 : : /* CS4227 SFP must not enable auto-negotiation */
1795 : 0 : *autoneg = false;
1796 : :
1797 : : /* Check if 1G SFP module. */
1798 : 0 : if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
1799 : : hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1
1800 [ # # # # ]: 0 : || hw->phy.sfp_type == ixgbe_sfp_type_1g_lha_core0 ||
1801 : : hw->phy.sfp_type == ixgbe_sfp_type_1g_lha_core1
1802 [ # # # # ]: 0 : || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
1803 : : hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) {
1804 : 0 : *speed = IXGBE_LINK_SPEED_1GB_FULL;
1805 : 0 : return IXGBE_SUCCESS;
1806 : : }
1807 : :
1808 : : /* Link capabilities are based on SFP */
1809 [ # # ]: 0 : if (hw->phy.multispeed_fiber)
1810 : 0 : *speed = IXGBE_LINK_SPEED_10GB_FULL |
1811 : : IXGBE_LINK_SPEED_1GB_FULL;
1812 : : else
1813 : 0 : *speed = IXGBE_LINK_SPEED_10GB_FULL;
1814 : : } else {
1815 : 0 : *autoneg = true;
1816 : :
1817 [ # # # # ]: 0 : switch (hw->phy.type) {
1818 : 0 : case ixgbe_phy_x550em_xfi:
1819 : 0 : *speed = IXGBE_LINK_SPEED_1GB_FULL |
1820 : : IXGBE_LINK_SPEED_10GB_FULL;
1821 : 0 : *autoneg = false;
1822 : 0 : break;
1823 : 0 : case ixgbe_phy_ext_1g_t:
1824 : : case ixgbe_phy_sgmii:
1825 : 0 : *speed = IXGBE_LINK_SPEED_1GB_FULL;
1826 : 0 : break;
1827 : 0 : case ixgbe_phy_x550em_kr:
1828 [ # # ]: 0 : if (hw->mac.type == ixgbe_mac_X550EM_a) {
1829 : : /* check different backplane modes */
1830 [ # # ]: 0 : if (hw->phy.nw_mng_if_sel &
1831 : : IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
1832 : 0 : *speed = IXGBE_LINK_SPEED_2_5GB_FULL;
1833 : 0 : break;
1834 [ # # ]: 0 : } else if (hw->device_id ==
1835 : : IXGBE_DEV_ID_X550EM_A_KR_L) {
1836 : 0 : *speed = IXGBE_LINK_SPEED_1GB_FULL;
1837 : 0 : break;
1838 : : }
1839 : : }
1840 : 0 : *speed = IXGBE_LINK_SPEED_10GB_FULL |
1841 : : IXGBE_LINK_SPEED_1GB_FULL;
1842 : 0 : break;
1843 : 0 : default:
1844 : 0 : *speed = IXGBE_LINK_SPEED_10GB_FULL |
1845 : : IXGBE_LINK_SPEED_1GB_FULL;
1846 : 0 : break;
1847 : : }
1848 : : }
1849 : :
1850 : : return IXGBE_SUCCESS;
1851 : : }
1852 : :
1853 : : /**
1854 : : * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause
1855 : : * @hw: pointer to hardware structure
1856 : : * @lsc: pointer to boolean flag which indicates whether external Base T
1857 : : * PHY interrupt is lsc
1858 : : *
1859 : : * Determime if external Base T PHY interrupt cause is high temperature
1860 : : * failure alarm or link status change.
1861 : : *
1862 : : * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
1863 : : * failure alarm, else return PHY access status.
1864 : : */
1865 : 0 : STATIC s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
1866 : : {
1867 : : u32 status;
1868 : : u16 reg;
1869 : :
1870 : 0 : *lsc = false;
1871 : :
1872 : : /* Vendor alarm triggered */
1873 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
1874 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
1875 : : ®);
1876 : :
1877 [ # # ]: 0 : if (status != IXGBE_SUCCESS ||
1878 [ # # ]: 0 : !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
1879 : : return status;
1880 : :
1881 : : /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
1882 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
1883 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
1884 : : ®);
1885 : :
1886 [ # # ]: 0 : if (status != IXGBE_SUCCESS ||
1887 [ # # ]: 0 : !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
1888 : : IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
1889 : : return status;
1890 : :
1891 : : /* Global alarm triggered */
1892 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
1893 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
1894 : : ®);
1895 : :
1896 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
1897 : : return status;
1898 : :
1899 : : /* If high temperature failure, then return over temp error and exit */
1900 [ # # ]: 0 : if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
1901 : : /* power down the PHY in case the PHY FW didn't already */
1902 : 0 : ixgbe_set_copper_phy_power(hw, false);
1903 : 0 : return IXGBE_ERR_OVERTEMP;
1904 [ # # ]: 0 : } else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
1905 : : /* device fault alarm triggered */
1906 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
1907 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
1908 : : ®);
1909 : :
1910 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
1911 : : return status;
1912 : :
1913 : : /* if device fault was due to high temp alarm handle and exit */
1914 [ # # ]: 0 : if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
1915 : : /* power down the PHY in case the PHY FW didn't */
1916 : 0 : ixgbe_set_copper_phy_power(hw, false);
1917 : 0 : return IXGBE_ERR_OVERTEMP;
1918 : : }
1919 : : }
1920 : :
1921 : : /* Vendor alarm 2 triggered */
1922 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
1923 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®);
1924 : :
1925 [ # # ]: 0 : if (status != IXGBE_SUCCESS ||
1926 [ # # ]: 0 : !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
1927 : : return status;
1928 : :
1929 : : /* link connect/disconnect event occurred */
1930 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
1931 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®);
1932 : :
1933 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
1934 : : return status;
1935 : :
1936 : : /* Indicate LSC */
1937 [ # # ]: 0 : if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC)
1938 : 0 : *lsc = true;
1939 : :
1940 : : return IXGBE_SUCCESS;
1941 : : }
1942 : :
1943 : : /**
1944 : : * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts
1945 : : * @hw: pointer to hardware structure
1946 : : *
1947 : : * Enable link status change and temperature failure alarm for the external
1948 : : * Base T PHY
1949 : : *
1950 : : * Returns PHY access status
1951 : : */
1952 : 0 : STATIC s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
1953 : : {
1954 : : u32 status;
1955 : : u16 reg;
1956 : : bool lsc;
1957 : :
1958 : : /* Clear interrupt flags */
1959 : 0 : status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
1960 : :
1961 : : /* Enable link status change alarm */
1962 : :
1963 : : /* Enable the LASI interrupts on X552 devices to receive notifications
1964 : : * of the link configurations of the external PHY and correspondingly
1965 : : * support the configuration of the internal iXFI link, since iXFI does
1966 : : * not support auto-negotiation. This is not required for X553 devices
1967 : : * having KR support, which performs auto-negotiations and which is used
1968 : : * as the internal link to the external PHY. Hence adding a check here
1969 : : * to avoid enabling LASI interrupts for X553 devices.
1970 : : */
1971 [ # # ]: 0 : if (hw->mac.type != ixgbe_mac_X550EM_a) {
1972 : 0 : status = hw->phy.ops.read_reg(hw,
1973 : : IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
1974 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®);
1975 : :
1976 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
1977 : : return status;
1978 : :
1979 : 0 : reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
1980 : :
1981 : 0 : status = hw->phy.ops.write_reg(hw,
1982 : : IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
1983 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg);
1984 : :
1985 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
1986 : : return status;
1987 : : }
1988 : :
1989 : : /* Enable high temperature failure and global fault alarms */
1990 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
1991 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
1992 : : ®);
1993 : :
1994 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
1995 : : return status;
1996 : :
1997 : 0 : reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN |
1998 : : IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);
1999 : :
2000 : 0 : status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
2001 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
2002 : : reg);
2003 : :
2004 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2005 : : return status;
2006 : :
2007 : : /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
2008 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
2009 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
2010 : : ®);
2011 : :
2012 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2013 : : return status;
2014 : :
2015 : 0 : reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
2016 : : IXGBE_MDIO_GLOBAL_ALARM_1_INT);
2017 : :
2018 : 0 : status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
2019 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
2020 : : reg);
2021 : :
2022 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2023 : : return status;
2024 : :
2025 : : /* Enable chip-wide vendor alarm */
2026 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
2027 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
2028 : : ®);
2029 : :
2030 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2031 : : return status;
2032 : :
2033 : 0 : reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
2034 : :
2035 : 0 : status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
2036 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
2037 : : reg);
2038 : :
2039 : 0 : return status;
2040 : : }
2041 : :
2042 : : /**
2043 : : * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed.
2044 : : * @hw: pointer to hardware structure
2045 : : * @speed: link speed
2046 : : *
2047 : : * Configures the integrated KR PHY.
2048 : : **/
2049 : 0 : STATIC s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
2050 : : ixgbe_link_speed speed)
2051 : : {
2052 : : s32 status;
2053 : : u32 reg_val;
2054 : :
2055 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
2056 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2057 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2058 [ # # ]: 0 : if (status)
2059 : : return status;
2060 : :
2061 : 0 : reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
2062 : 0 : reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
2063 : : IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
2064 : :
2065 : : /* Advertise 10G support. */
2066 [ # # ]: 0 : if (speed & IXGBE_LINK_SPEED_10GB_FULL)
2067 : 0 : reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR;
2068 : :
2069 : : /* Advertise 1G support. */
2070 [ # # ]: 0 : if (speed & IXGBE_LINK_SPEED_1GB_FULL)
2071 : 0 : reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
2072 : :
2073 : 0 : status = hw->mac.ops.write_iosf_sb_reg(hw,
2074 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2075 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2076 : :
2077 [ # # ]: 0 : if (hw->mac.type == ixgbe_mac_X550EM_a) {
2078 : : /* Set lane mode to KR auto negotiation */
2079 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
2080 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2081 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2082 : :
2083 [ # # ]: 0 : if (status)
2084 : : return status;
2085 : :
2086 : 0 : reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
2087 : 0 : reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
2088 : 0 : reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
2089 : 0 : reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
2090 : 0 : reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
2091 : :
2092 : 0 : status = hw->mac.ops.write_iosf_sb_reg(hw,
2093 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2094 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2095 : : }
2096 : :
2097 : 0 : return ixgbe_restart_an_internal_phy_x550em(hw);
2098 : : }
2099 : :
2100 : : /**
2101 : : * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs
2102 : : * @hw: pointer to hardware structure
2103 : : */
2104 : 0 : static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw)
2105 : : {
2106 : 0 : u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
2107 : : s32 rc;
2108 : :
2109 [ # # # # ]: 0 : if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
2110 : 0 : return IXGBE_SUCCESS;
2111 : :
2112 : 0 : rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store);
2113 [ # # ]: 0 : if (rc)
2114 : : return rc;
2115 : : memset(store, 0, sizeof(store));
2116 : :
2117 : 0 : rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store);
2118 [ # # ]: 0 : if (rc)
2119 : : return rc;
2120 : :
2121 : 0 : return ixgbe_setup_fw_link(hw);
2122 : : }
2123 : :
2124 : : /**
2125 : : * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp
2126 : : * @hw: pointer to hardware structure
2127 : : */
2128 : 0 : static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
2129 : : {
2130 : 0 : u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
2131 : : s32 rc;
2132 : :
2133 : 0 : rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);
2134 [ # # ]: 0 : if (rc)
2135 : : return rc;
2136 : :
2137 [ # # ]: 0 : if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {
2138 : 0 : ixgbe_shutdown_fw_phy(hw);
2139 : 0 : return IXGBE_ERR_OVERTEMP;
2140 : : }
2141 : : return IXGBE_SUCCESS;
2142 : : }
2143 : :
2144 : : /**
2145 : : * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register
2146 : : * @hw: pointer to hardware structure
2147 : : *
2148 : : * Read NW_MNG_IF_SEL register and save field values, and check for valid field
2149 : : * values.
2150 : : **/
2151 : : STATIC s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw)
2152 : : {
2153 : : /* Save NW management interface connected on board. This is used
2154 : : * to determine internal PHY mode.
2155 : : */
2156 : 0 : hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
2157 : :
2158 : : /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set
2159 : : * PHY address. This register field was has only been used for X552.
2160 : : */
2161 [ # # # # ]: 0 : if (hw->mac.type == ixgbe_mac_X550EM_a &&
2162 [ # # # # ]: 0 : hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) {
2163 : 0 : hw->phy.addr = (hw->phy.nw_mng_if_sel &
2164 : 0 : IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
2165 : : IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
2166 : : }
2167 : :
2168 : : return IXGBE_SUCCESS;
2169 : : }
2170 : :
2171 : : /**
2172 : : * ixgbe_init_phy_ops_X550em - PHY/SFP specific init
2173 : : * @hw: pointer to hardware structure
2174 : : *
2175 : : * Initialize any function pointers that were not able to be
2176 : : * set during init_shared_code because the PHY/SFP type was
2177 : : * not known. Perform the SFP init if necessary.
2178 : : */
2179 : 0 : s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
2180 : : {
2181 : : struct ixgbe_phy_info *phy = &hw->phy;
2182 : : s32 ret_val;
2183 : :
2184 : 0 : DEBUGFUNC("ixgbe_init_phy_ops_X550em");
2185 : :
2186 : 0 : hw->mac.ops.set_lan_id(hw);
2187 : : ixgbe_read_mng_if_sel_x550em(hw);
2188 : :
2189 [ # # ]: 0 : if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) {
2190 : 0 : phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
2191 : : ixgbe_setup_mux_ctl(hw);
2192 : 0 : phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em;
2193 : : }
2194 : :
2195 [ # # # # : 0 : switch (hw->device_id) {
# ]
2196 : 0 : case IXGBE_DEV_ID_X550EM_A_1G_T:
2197 : : case IXGBE_DEV_ID_X550EM_A_1G_T_L:
2198 : 0 : phy->ops.read_reg_mdi = NULL;
2199 : 0 : phy->ops.write_reg_mdi = NULL;
2200 : 0 : hw->phy.ops.read_reg = NULL;
2201 : 0 : hw->phy.ops.write_reg = NULL;
2202 : 0 : phy->ops.check_overtemp = ixgbe_check_overtemp_fw;
2203 [ # # ]: 0 : if (hw->bus.lan_id)
2204 : 0 : hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
2205 : : else
2206 : 0 : hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
2207 : :
2208 : : break;
2209 : 0 : case IXGBE_DEV_ID_X550EM_A_10G_T:
2210 : : case IXGBE_DEV_ID_X550EM_A_SFP:
2211 : 0 : hw->phy.ops.read_reg = ixgbe_read_phy_reg_x550a;
2212 : 0 : hw->phy.ops.write_reg = ixgbe_write_phy_reg_x550a;
2213 [ # # ]: 0 : if (hw->bus.lan_id)
2214 : 0 : hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
2215 : : else
2216 : 0 : hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
2217 : : break;
2218 : 0 : case IXGBE_DEV_ID_X550EM_X_SFP:
2219 : : /* set up for CS4227 usage */
2220 : 0 : hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
2221 : 0 : break;
2222 : 0 : case IXGBE_DEV_ID_X550EM_X_1G_T:
2223 : 0 : phy->ops.read_reg_mdi = NULL;
2224 : 0 : phy->ops.write_reg_mdi = NULL;
2225 : : default:
2226 : : break;
2227 : : }
2228 : :
2229 : : /* Identify the PHY or SFP module */
2230 : 0 : ret_val = phy->ops.identify(hw);
2231 : 0 : if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED ||
2232 [ # # ]: 0 : ret_val == IXGBE_ERR_PHY_ADDR_INVALID)
2233 : : return ret_val;
2234 : :
2235 : : /* Setup function pointers based on detected hardware */
2236 : 0 : ixgbe_init_mac_link_ops_X550em(hw);
2237 [ # # ]: 0 : if (phy->sfp_type != ixgbe_sfp_type_unknown)
2238 : 0 : phy->ops.reset = NULL;
2239 : :
2240 : : /* Set functions pointers based on phy type */
2241 [ # # # # : 0 : switch (hw->phy.type) {
# # # # ]
2242 : 0 : case ixgbe_phy_x550em_kx4:
2243 : 0 : phy->ops.setup_link = NULL;
2244 : 0 : phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
2245 : 0 : phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
2246 : 0 : break;
2247 : 0 : case ixgbe_phy_x550em_kr:
2248 : 0 : phy->ops.setup_link = ixgbe_setup_kr_x550em;
2249 : 0 : phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
2250 : 0 : phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
2251 : 0 : break;
2252 : 0 : case ixgbe_phy_ext_1g_t:
2253 : : /* link is managed by FW */
2254 : 0 : phy->ops.setup_link = NULL;
2255 : 0 : phy->ops.reset = NULL;
2256 : 0 : break;
2257 : 0 : case ixgbe_phy_x550em_xfi:
2258 : : /* link is managed by HW */
2259 : 0 : phy->ops.setup_link = NULL;
2260 : 0 : phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
2261 : 0 : phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
2262 : 0 : break;
2263 : 0 : case ixgbe_phy_x550em_ext_t:
2264 : : /* If internal link mode is XFI, then setup iXFI internal link,
2265 : : * else setup KR now.
2266 : : */
2267 : 0 : phy->ops.setup_internal_link =
2268 : : ixgbe_setup_internal_phy_t_x550em;
2269 : :
2270 : : /* setup SW LPLU only for first revision of X550EM_x */
2271 [ # # ]: 0 : if ((hw->mac.type == ixgbe_mac_X550EM_x) &&
2272 [ # # ]: 0 : !(IXGBE_FUSES0_REV_MASK &
2273 : 0 : IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))))
2274 : 0 : phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
2275 : :
2276 : 0 : phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
2277 : 0 : phy->ops.reset = ixgbe_reset_phy_t_X550em;
2278 : 0 : break;
2279 : 0 : case ixgbe_phy_sgmii:
2280 : 0 : phy->ops.setup_link = NULL;
2281 : 0 : break;
2282 : 0 : case ixgbe_phy_fw:
2283 : 0 : phy->ops.setup_link = ixgbe_setup_fw_link;
2284 : 0 : phy->ops.reset = ixgbe_reset_phy_fw;
2285 : 0 : break;
2286 : : default:
2287 : : break;
2288 : : }
2289 : : return ret_val;
2290 : : }
2291 : :
2292 : : /**
2293 : : * ixgbe_set_mdio_speed - Set MDIO clock speed
2294 : : * @hw: pointer to hardware structure
2295 : : */
2296 : 0 : STATIC void ixgbe_set_mdio_speed(struct ixgbe_hw *hw)
2297 : : {
2298 : : u32 hlreg0;
2299 : :
2300 [ # # # ]: 0 : switch (hw->device_id) {
2301 : 0 : case IXGBE_DEV_ID_X550EM_X_10G_T:
2302 : : case IXGBE_DEV_ID_X550EM_A_SGMII:
2303 : : case IXGBE_DEV_ID_X550EM_A_SGMII_L:
2304 : : case IXGBE_DEV_ID_X550EM_A_10G_T:
2305 : : case IXGBE_DEV_ID_X550EM_A_SFP:
2306 : : case IXGBE_DEV_ID_X550EM_A_QSFP:
2307 : : /* Config MDIO clock speed before the first MDIO PHY access */
2308 : 0 : hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
2309 : 0 : hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
2310 : 0 : IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
2311 : : break;
2312 : 0 : case IXGBE_DEV_ID_X550EM_A_1G_T:
2313 : : case IXGBE_DEV_ID_X550EM_A_1G_T_L:
2314 : : /* Select fast MDIO clock speed for these devices */
2315 : 0 : hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
2316 : 0 : hlreg0 |= IXGBE_HLREG0_MDCSPD;
2317 : 0 : IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
2318 : : break;
2319 : : default:
2320 : : break;
2321 : : }
2322 : 0 : }
2323 : :
2324 : : /**
2325 : : * ixgbe_reset_hw_X550em - Perform hardware reset
2326 : : * @hw: pointer to hardware structure
2327 : : *
2328 : : * Resets the hardware by resetting the transmit and receive units, masks
2329 : : * and clears all interrupts, perform a PHY reset, and perform a link (MAC)
2330 : : * reset.
2331 : : */
2332 : 0 : s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
2333 : : {
2334 : : ixgbe_link_speed link_speed;
2335 : : s32 status;
2336 : : u32 ctrl = 0;
2337 : : u32 i;
2338 : 0 : bool link_up = false;
2339 : 0 : u32 swfw_mask = hw->phy.phy_semaphore_mask;
2340 : :
2341 : 0 : DEBUGFUNC("ixgbe_reset_hw_X550em");
2342 : :
2343 : : /* Call adapter stop to disable Tx/Rx and clear interrupts */
2344 : 0 : status = hw->mac.ops.stop_adapter(hw);
2345 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
2346 : 0 : DEBUGOUT1("Failed to stop adapter, STATUS = %d\n", status);
2347 : 0 : return status;
2348 : : }
2349 : : /* flush pending Tx transactions */
2350 : 0 : ixgbe_clear_tx_pending(hw);
2351 : :
2352 : 0 : ixgbe_set_mdio_speed(hw);
2353 : :
2354 : : /* PHY ops must be identified and initialized prior to reset */
2355 : 0 : status = hw->phy.ops.init(hw);
2356 : :
2357 [ # # ]: 0 : if (status)
2358 : 0 : DEBUGOUT1("Failed to initialize PHY ops, STATUS = %d\n",
2359 : : status);
2360 : :
2361 : 0 : if (status == IXGBE_ERR_SFP_NOT_SUPPORTED ||
2362 [ # # ]: 0 : status == IXGBE_ERR_PHY_ADDR_INVALID) {
2363 : 0 : DEBUGOUT("Returning from reset HW due to PHY init failure\n");
2364 : 0 : return status;
2365 : : }
2366 : :
2367 : : /* start the external PHY */
2368 [ # # ]: 0 : if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
2369 : 0 : status = ixgbe_init_ext_t_x550em(hw);
2370 [ # # ]: 0 : if (status) {
2371 : 0 : DEBUGOUT1("Failed to start the external PHY, STATUS = %d\n",
2372 : : status);
2373 : 0 : return status;
2374 : : }
2375 : : }
2376 : :
2377 : : /* Setup SFP module if there is one present. */
2378 [ # # ]: 0 : if (hw->phy.sfp_setup_needed) {
2379 : 0 : status = hw->mac.ops.setup_sfp(hw);
2380 : 0 : hw->phy.sfp_setup_needed = false;
2381 : : }
2382 : :
2383 [ # # ]: 0 : if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
2384 : : return status;
2385 : :
2386 : : /* Reset PHY */
2387 [ # # # # ]: 0 : if (!hw->phy.reset_disable && hw->phy.ops.reset) {
2388 [ # # ]: 0 : if (hw->phy.ops.reset(hw) == IXGBE_ERR_OVERTEMP)
2389 : : return IXGBE_ERR_OVERTEMP;
2390 : : }
2391 : :
2392 : 0 : mac_reset_top:
2393 : : /* Issue global reset to the MAC. Needs to be SW reset if link is up.
2394 : : * If link reset is used when link is up, it might reset the PHY when
2395 : : * mng is using it. If link is down or the flag to force full link
2396 : : * reset is set, then perform link reset.
2397 : : */
2398 : : ctrl = IXGBE_CTRL_LNK_RST;
2399 [ # # ]: 0 : if (!hw->force_full_reset) {
2400 : 0 : hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
2401 [ # # ]: 0 : if (link_up)
2402 : : ctrl = IXGBE_CTRL_RST;
2403 : : }
2404 : :
2405 : 0 : status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
2406 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
2407 : 0 : ERROR_REPORT2(IXGBE_ERROR_CAUTION,
2408 : : "semaphore failed with %d", status);
2409 : 0 : return IXGBE_ERR_SWFW_SYNC;
2410 : : }
2411 : 0 : ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
2412 : 0 : IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
2413 : 0 : IXGBE_WRITE_FLUSH(hw);
2414 : 0 : hw->mac.ops.release_swfw_sync(hw, swfw_mask);
2415 : :
2416 : : /* Poll for reset bit to self-clear meaning reset is complete */
2417 [ # # ]: 0 : for (i = 0; i < 10; i++) {
2418 : 0 : usec_delay(1);
2419 : 0 : ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
2420 [ # # ]: 0 : if (!(ctrl & IXGBE_CTRL_RST_MASK))
2421 : : break;
2422 : : }
2423 : :
2424 [ # # ]: 0 : if (ctrl & IXGBE_CTRL_RST_MASK) {
2425 : : status = IXGBE_ERR_RESET_FAILED;
2426 : 0 : DEBUGOUT("Reset polling failed to complete.\n");
2427 : : }
2428 : :
2429 : 0 : msec_delay(50);
2430 : :
2431 : : /* Double resets are required for recovery from certain error
2432 : : * conditions. Between resets, it is necessary to stall to
2433 : : * allow time for any pending HW events to complete.
2434 : : */
2435 [ # # ]: 0 : if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
2436 : 0 : hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
2437 : 0 : goto mac_reset_top;
2438 : : }
2439 : :
2440 : : /* Store the permanent mac address */
2441 : 0 : hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
2442 : :
2443 : : /* Store MAC address from RAR0, clear receive address registers, and
2444 : : * clear the multicast table. Also reset num_rar_entries to 128,
2445 : : * since we modify this value when programming the SAN MAC address.
2446 : : */
2447 : 0 : hw->mac.num_rar_entries = 128;
2448 : 0 : hw->mac.ops.init_rx_addrs(hw);
2449 : :
2450 : 0 : ixgbe_set_mdio_speed(hw);
2451 : :
2452 [ # # ]: 0 : if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
2453 : : ixgbe_setup_mux_ctl(hw);
2454 : :
2455 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2456 : 0 : DEBUGOUT1("Reset HW failed, STATUS = %d\n", status);
2457 : :
2458 : : return status;
2459 : : }
2460 : :
2461 : : /**
2462 : : * ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY.
2463 : : * @hw: pointer to hardware structure
2464 : : */
2465 : 0 : s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
2466 : : {
2467 : : u32 status;
2468 : : u16 reg;
2469 : :
2470 : 0 : status = hw->phy.ops.read_reg(hw,
2471 : : IXGBE_MDIO_TX_VENDOR_ALARMS_3,
2472 : : IXGBE_MDIO_PMA_PMD_DEV_TYPE,
2473 : : ®);
2474 : :
2475 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2476 : : return status;
2477 : :
2478 : : /* If PHY FW reset completed bit is set then this is the first
2479 : : * SW instance after a power on so the PHY FW must be un-stalled.
2480 : : */
2481 [ # # ]: 0 : if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
2482 : 0 : status = hw->phy.ops.read_reg(hw,
2483 : : IXGBE_MDIO_GLOBAL_RES_PR_10,
2484 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
2485 : : ®);
2486 : :
2487 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2488 : : return status;
2489 : :
2490 : 0 : reg &= ~IXGBE_MDIO_POWER_UP_STALL;
2491 : :
2492 : 0 : status = hw->phy.ops.write_reg(hw,
2493 : : IXGBE_MDIO_GLOBAL_RES_PR_10,
2494 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
2495 : : reg);
2496 : :
2497 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2498 : 0 : return status;
2499 : : }
2500 : :
2501 : : return status;
2502 : : }
2503 : :
2504 : : /**
2505 : : * ixgbe_setup_kr_x550em - Configure the KR PHY.
2506 : : * @hw: pointer to hardware structure
2507 : : **/
2508 : 0 : s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
2509 : : {
2510 : : /* leave link alone for 2.5G */
2511 [ # # ]: 0 : if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
2512 : : return IXGBE_SUCCESS;
2513 : :
2514 [ # # ]: 0 : if (ixgbe_check_reset_blocked(hw))
2515 : : return 0;
2516 : :
2517 : 0 : return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised);
2518 : : }
2519 : :
2520 : : /**
2521 : : * ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP
2522 : : * @hw: pointer to hardware structure
2523 : : * @speed: new link speed
2524 : : * @autoneg_wait_to_complete: unused
2525 : : *
2526 : : * Configure the external PHY and the integrated KR PHY for SFP support.
2527 : : **/
2528 : 0 : s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
2529 : : ixgbe_link_speed speed,
2530 : : bool autoneg_wait_to_complete)
2531 : : {
2532 : : s32 ret_val;
2533 : : u16 reg_slice, reg_val;
2534 : 0 : bool setup_linear = false;
2535 : : UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
2536 : :
2537 : : /* Check if SFP module is supported and linear */
2538 : 0 : ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
2539 : :
2540 : : /* If no SFP module present, then return success. Return success since
2541 : : * there is no reason to configure CS4227 and SFP not present error is
2542 : : * not excepted in the setup MAC link flow.
2543 : : */
2544 [ # # ]: 0 : if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
2545 : : return IXGBE_SUCCESS;
2546 : :
2547 [ # # ]: 0 : if (ret_val != IXGBE_SUCCESS)
2548 : : return ret_val;
2549 : :
2550 : : /* Configure internal PHY for KR/KX. */
2551 : 0 : ixgbe_setup_kr_speed_x550em(hw, speed);
2552 : :
2553 : : /* Configure CS4227 LINE side to proper mode. */
2554 : 0 : reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
2555 : 0 : (hw->bus.lan_id << 12);
2556 [ # # ]: 0 : if (setup_linear)
2557 : : reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
2558 : : else
2559 : : reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
2560 : 0 : ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice,
2561 : : reg_val);
2562 : 0 : return ret_val;
2563 : : }
2564 : :
2565 : : /**
2566 : : * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode
2567 : : * @hw: pointer to hardware structure
2568 : : * @speed: the link speed to force
2569 : : *
2570 : : * Configures the integrated PHY for native SFI mode. Used to connect the
2571 : : * internal PHY directly to an SFP cage, without autonegotiation.
2572 : : **/
2573 : 0 : STATIC s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
2574 : : {
2575 : : struct ixgbe_mac_info *mac = &hw->mac;
2576 : : s32 status;
2577 : : u32 reg_val;
2578 : :
2579 : : /* Disable all AN and force speed to 10G Serial. */
2580 : 0 : status = mac->ops.read_iosf_sb_reg(hw,
2581 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2582 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2583 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2584 : : return status;
2585 : :
2586 : 0 : reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
2587 : 0 : reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
2588 : 0 : reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
2589 : 0 : reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
2590 : :
2591 : : /* Select forced link speed for internal PHY. */
2592 [ # # # ]: 0 : switch (*speed) {
2593 : 0 : case IXGBE_LINK_SPEED_10GB_FULL:
2594 : 0 : reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G;
2595 : 0 : break;
2596 : 0 : case IXGBE_LINK_SPEED_1GB_FULL:
2597 : 0 : reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
2598 : 0 : break;
2599 : : default:
2600 : : /* Other link speeds are not supported by internal PHY. */
2601 : : return IXGBE_ERR_LINK_SETUP;
2602 : : }
2603 : :
2604 : 0 : status = mac->ops.write_iosf_sb_reg(hw,
2605 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2606 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2607 : :
2608 : : /* Toggle port SW reset by AN reset. */
2609 : 0 : status = ixgbe_restart_an_internal_phy_x550em(hw);
2610 : :
2611 : 0 : return status;
2612 : : }
2613 : :
2614 : : /**
2615 : : * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP
2616 : : * @hw: pointer to hardware structure
2617 : : * @speed: new link speed
2618 : : * @autoneg_wait_to_complete: unused
2619 : : *
2620 : : * Configure the integrated PHY for SFP support.
2621 : : **/
2622 : 0 : s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
2623 : : ixgbe_link_speed speed,
2624 : : bool autoneg_wait_to_complete)
2625 : : {
2626 : : s32 ret_val;
2627 : : u16 reg_phy_ext;
2628 : 0 : bool setup_linear = false;
2629 : : u32 reg_slice, reg_phy_int, slice_offset;
2630 : :
2631 : : UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
2632 : :
2633 : : /* Check if SFP module is supported and linear */
2634 : 0 : ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
2635 : :
2636 : : /* If no SFP module present, then return success. Return success since
2637 : : * SFP not present error is not excepted in the setup MAC link flow.
2638 : : */
2639 [ # # ]: 0 : if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
2640 : : return IXGBE_SUCCESS;
2641 : :
2642 [ # # ]: 0 : if (ret_val != IXGBE_SUCCESS)
2643 : : return ret_val;
2644 : :
2645 [ # # ]: 0 : if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) {
2646 : : /* Configure internal PHY for native SFI based on module type */
2647 : 0 : ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
2648 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2649 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int);
2650 : :
2651 [ # # ]: 0 : if (ret_val != IXGBE_SUCCESS)
2652 : : return ret_val;
2653 : :
2654 : 0 : reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA;
2655 [ # # ]: 0 : if (!setup_linear)
2656 : 0 : reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR;
2657 : :
2658 : 0 : ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
2659 [ # # ]: 0 : IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
2660 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
2661 : :
2662 [ # # ]: 0 : if (ret_val != IXGBE_SUCCESS)
2663 : : return ret_val;
2664 : :
2665 : : /* Setup SFI internal link. */
2666 : 0 : ret_val = ixgbe_setup_sfi_x550a(hw, &speed);
2667 : : } else {
2668 : : /* Configure internal PHY for KR/KX. */
2669 : 0 : ixgbe_setup_kr_speed_x550em(hw, speed);
2670 : :
2671 [ # # ]: 0 : if (hw->phy.addr == 0x0 || hw->phy.addr == 0xFFFF) {
2672 : : /* Find Address */
2673 : 0 : DEBUGOUT("Invalid NW_MNG_IF_SEL.MDIO_PHY_ADD value\n");
2674 : 0 : return IXGBE_ERR_PHY_ADDR_INVALID;
2675 : : }
2676 : :
2677 : : /* Get external PHY SKU id */
2678 : 0 : ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU,
2679 : : IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext);
2680 : :
2681 [ # # ]: 0 : if (ret_val != IXGBE_SUCCESS)
2682 : : return ret_val;
2683 : :
2684 : : /* When configuring quad port CS4223, the MAC instance is part
2685 : : * of the slice offset.
2686 : : */
2687 [ # # ]: 0 : if (reg_phy_ext == IXGBE_CS4223_SKU_ID)
2688 : 0 : slice_offset = (hw->bus.lan_id +
2689 : 0 : (hw->bus.instance_id << 1)) << 12;
2690 : : else
2691 : 0 : slice_offset = hw->bus.lan_id << 12;
2692 : :
2693 : : /* Configure CS4227/CS4223 LINE side to proper mode. */
2694 : 0 : reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
2695 : :
2696 : 0 : ret_val = hw->phy.ops.read_reg(hw, reg_slice,
2697 : : IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext);
2698 : :
2699 [ # # ]: 0 : if (ret_val != IXGBE_SUCCESS)
2700 : : return ret_val;
2701 : :
2702 : 0 : reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) |
2703 : : (IXGBE_CS4227_EDC_MODE_SR << 1));
2704 : :
2705 [ # # ]: 0 : if (setup_linear)
2706 : 0 : reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
2707 : : else
2708 : 0 : reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
2709 : 0 : ret_val = hw->phy.ops.write_reg(hw, reg_slice,
2710 : : IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
2711 : :
2712 : : /* Flush previous write with a read */
2713 : 0 : ret_val = hw->phy.ops.read_reg(hw, reg_slice,
2714 : : IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext);
2715 : : }
2716 : : return ret_val;
2717 : : }
2718 : :
2719 : : /**
2720 : : * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration
2721 : : * @hw: pointer to hardware structure
2722 : : *
2723 : : * iXfI configuration needed for ixgbe_mac_X550EM_x devices.
2724 : : **/
2725 : 0 : STATIC s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)
2726 : : {
2727 : : struct ixgbe_mac_info *mac = &hw->mac;
2728 : : s32 status;
2729 : : u32 reg_val;
2730 : :
2731 : : /* Disable training protocol FSM. */
2732 : 0 : status = mac->ops.read_iosf_sb_reg(hw,
2733 [ # # ]: 0 : IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
2734 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2735 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2736 : : return status;
2737 : 0 : reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL;
2738 : 0 : status = mac->ops.write_iosf_sb_reg(hw,
2739 [ # # ]: 0 : IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
2740 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2741 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2742 : : return status;
2743 : :
2744 : : /* Disable Flex from training TXFFE. */
2745 : 0 : status = mac->ops.read_iosf_sb_reg(hw,
2746 [ # # ]: 0 : IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
2747 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2748 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2749 : : return status;
2750 : 0 : reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
2751 : 0 : reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
2752 : 0 : reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
2753 : 0 : status = mac->ops.write_iosf_sb_reg(hw,
2754 [ # # ]: 0 : IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
2755 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2756 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2757 : : return status;
2758 : 0 : status = mac->ops.read_iosf_sb_reg(hw,
2759 [ # # ]: 0 : IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
2760 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2761 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2762 : : return status;
2763 : 0 : reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
2764 : 0 : reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
2765 : 0 : reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
2766 : 0 : status = mac->ops.write_iosf_sb_reg(hw,
2767 [ # # ]: 0 : IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
2768 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2769 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2770 : : return status;
2771 : :
2772 : : /* Enable override for coefficients. */
2773 : 0 : status = mac->ops.read_iosf_sb_reg(hw,
2774 [ # # ]: 0 : IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
2775 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2776 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2777 : : return status;
2778 : 0 : reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN;
2779 : 0 : reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN;
2780 : 0 : reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN;
2781 : 0 : reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN;
2782 : 0 : status = mac->ops.write_iosf_sb_reg(hw,
2783 [ # # ]: 0 : IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
2784 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2785 : 0 : return status;
2786 : : }
2787 : :
2788 : : /**
2789 : : * ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
2790 : : * @hw: pointer to hardware structure
2791 : : * @speed: the link speed to force
2792 : : *
2793 : : * Configures the integrated KR PHY to use iXFI mode. Used to connect an
2794 : : * internal and external PHY at a specific speed, without autonegotiation.
2795 : : **/
2796 : 0 : STATIC s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
2797 : : {
2798 : : struct ixgbe_mac_info *mac = &hw->mac;
2799 : : s32 status;
2800 : : u32 reg_val;
2801 : :
2802 : : /* iXFI is only supported with X552 */
2803 [ # # ]: 0 : if (mac->type != ixgbe_mac_X550EM_x)
2804 : : return IXGBE_ERR_LINK_SETUP;
2805 : :
2806 : : /* Disable AN and force speed to 10G Serial. */
2807 : 0 : status = mac->ops.read_iosf_sb_reg(hw,
2808 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2809 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2810 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2811 : : return status;
2812 : :
2813 : 0 : reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
2814 : 0 : reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
2815 : :
2816 : : /* Select forced link speed for internal PHY. */
2817 [ # # # ]: 0 : switch (*speed) {
2818 : 0 : case IXGBE_LINK_SPEED_10GB_FULL:
2819 : 0 : reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
2820 : 0 : break;
2821 : 0 : case IXGBE_LINK_SPEED_1GB_FULL:
2822 : 0 : reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
2823 : 0 : break;
2824 : : default:
2825 : : /* Other link speeds are not supported by internal KR PHY. */
2826 : : return IXGBE_ERR_LINK_SETUP;
2827 : : }
2828 : :
2829 : 0 : status = mac->ops.write_iosf_sb_reg(hw,
2830 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2831 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2832 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2833 : : return status;
2834 : :
2835 : : /* Additional configuration needed for x550em_x */
2836 [ # # ]: 0 : if (hw->mac.type == ixgbe_mac_X550EM_x) {
2837 : 0 : status = ixgbe_setup_ixfi_x550em_x(hw);
2838 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2839 : : return status;
2840 : : }
2841 : :
2842 : : /* Toggle port SW reset by AN reset. */
2843 : 0 : status = ixgbe_restart_an_internal_phy_x550em(hw);
2844 : :
2845 : 0 : return status;
2846 : : }
2847 : :
2848 : : /**
2849 : : * ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status
2850 : : * @hw: address of hardware structure
2851 : : * @link_up: address of boolean to indicate link status
2852 : : *
2853 : : * Returns error code if unable to get link status.
2854 : : */
2855 : 0 : STATIC s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
2856 : : {
2857 : : u32 ret;
2858 : : u16 autoneg_status;
2859 : :
2860 : 0 : *link_up = false;
2861 : :
2862 : : /* read this twice back to back to indicate current status */
2863 : 0 : ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
2864 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
2865 : : &autoneg_status);
2866 [ # # ]: 0 : if (ret != IXGBE_SUCCESS)
2867 : : return ret;
2868 : :
2869 : 0 : ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
2870 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
2871 : : &autoneg_status);
2872 [ # # ]: 0 : if (ret != IXGBE_SUCCESS)
2873 : : return ret;
2874 : :
2875 : 0 : *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS);
2876 : :
2877 : 0 : return IXGBE_SUCCESS;
2878 : : }
2879 : :
2880 : : /**
2881 : : * ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link
2882 : : * @hw: point to hardware structure
2883 : : *
2884 : : * Configures the link between the integrated KR PHY and the external X557 PHY
2885 : : * The driver will call this function when it gets a link status change
2886 : : * interrupt from the X557 PHY. This function configures the link speed
2887 : : * between the PHYs to match the link speed of the BASE-T link.
2888 : : *
2889 : : * A return of a non-zero value indicates an error, and the base driver should
2890 : : * not report link up.
2891 : : */
2892 : 0 : s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
2893 : : {
2894 : : ixgbe_link_speed force_speed;
2895 : : bool link_up;
2896 : : u32 status;
2897 : : u16 speed;
2898 : :
2899 [ # # ]: 0 : if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
2900 : : return IXGBE_ERR_CONFIG;
2901 : :
2902 [ # # ]: 0 : if (hw->mac.type == ixgbe_mac_X550EM_x &&
2903 [ # # ]: 0 : !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
2904 : : /* If link is down, there is no setup necessary so return */
2905 : 0 : status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
2906 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2907 : : return status;
2908 : :
2909 [ # # ]: 0 : if (!link_up)
2910 : : return IXGBE_SUCCESS;
2911 : :
2912 : 0 : status = hw->phy.ops.read_reg(hw,
2913 : : IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
2914 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
2915 : : &speed);
2916 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2917 : : return status;
2918 : :
2919 : : /* If link is still down - no setup is required so return */
2920 : 0 : status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
2921 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2922 : : return status;
2923 [ # # ]: 0 : if (!link_up)
2924 : : return IXGBE_SUCCESS;
2925 : :
2926 : : /* clear everything but the speed and duplex bits */
2927 : 0 : speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
2928 : :
2929 [ # # # ]: 0 : switch (speed) {
2930 : 0 : case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
2931 : 0 : force_speed = IXGBE_LINK_SPEED_10GB_FULL;
2932 : 0 : break;
2933 : 0 : case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
2934 : 0 : force_speed = IXGBE_LINK_SPEED_1GB_FULL;
2935 : 0 : break;
2936 : : default:
2937 : : /* Internal PHY does not support anything else */
2938 : : return IXGBE_ERR_INVALID_LINK_SETTINGS;
2939 : : }
2940 : :
2941 : 0 : return ixgbe_setup_ixfi_x550em(hw, &force_speed);
2942 : : } else {
2943 : 0 : speed = IXGBE_LINK_SPEED_10GB_FULL |
2944 : : IXGBE_LINK_SPEED_1GB_FULL;
2945 : 0 : return ixgbe_setup_kr_speed_x550em(hw, speed);
2946 : : }
2947 : : }
2948 : :
2949 : : /**
2950 : : * ixgbe_setup_phy_loopback_x550em - Configure the KR PHY for loopback.
2951 : : * @hw: pointer to hardware structure
2952 : : *
2953 : : * Configures the integrated KR PHY to use internal loopback mode.
2954 : : **/
2955 : 0 : s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw)
2956 : : {
2957 : : s32 status;
2958 : : u32 reg_val;
2959 : :
2960 : : /* Disable AN and force speed to 10G Serial. */
2961 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
2962 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2963 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2964 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2965 : : return status;
2966 : 0 : reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
2967 : 0 : reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
2968 : 0 : reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
2969 : 0 : status = hw->mac.ops.write_iosf_sb_reg(hw,
2970 [ # # ]: 0 : IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
2971 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2972 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2973 : : return status;
2974 : :
2975 : : /* Set near-end loopback clocks. */
2976 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
2977 [ # # ]: 0 : IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
2978 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2979 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2980 : : return status;
2981 : 0 : reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B;
2982 : 0 : reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS;
2983 : 0 : status = hw->mac.ops.write_iosf_sb_reg(hw,
2984 [ # # ]: 0 : IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
2985 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2986 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2987 : : return status;
2988 : :
2989 : : /* Set loopback enable. */
2990 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
2991 [ # # ]: 0 : IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
2992 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
2993 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
2994 : : return status;
2995 : 0 : reg_val |= IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK;
2996 : 0 : status = hw->mac.ops.write_iosf_sb_reg(hw,
2997 [ # # ]: 0 : IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
2998 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
2999 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3000 : : return status;
3001 : :
3002 : : /* Training bypass. */
3003 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
3004 [ # # ]: 0 : IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
3005 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
3006 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3007 : : return status;
3008 : 0 : reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS;
3009 : 0 : status = hw->mac.ops.write_iosf_sb_reg(hw,
3010 [ # # ]: 0 : IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
3011 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
3012 : :
3013 : 0 : return status;
3014 : : }
3015 : :
3016 : : /**
3017 : : * ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command
3018 : : * assuming that the semaphore is already obtained.
3019 : : * @hw: pointer to hardware structure
3020 : : * @offset: offset of word in the EEPROM to read
3021 : : * @data: word read from the EEPROM
3022 : : *
3023 : : * Reads a 16 bit word from the EEPROM using the hostif.
3024 : : **/
3025 : 0 : s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data)
3026 : : {
3027 : : const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
3028 : : struct ixgbe_hic_read_shadow_ram buffer;
3029 : : s32 status;
3030 : :
3031 : 0 : DEBUGFUNC("ixgbe_read_ee_hostif_X550");
3032 : 0 : buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
3033 : 0 : buffer.hdr.req.buf_lenh = 0;
3034 : 0 : buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
3035 : 0 : buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
3036 : :
3037 : : /* convert offset from words to bytes */
3038 [ # # ]: 0 : buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
3039 : : /* one word */
3040 : 0 : buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
3041 : 0 : buffer.pad2 = 0;
3042 : 0 : buffer.data = 0;
3043 : 0 : buffer.pad3 = 0;
3044 : :
3045 : 0 : status = hw->mac.ops.acquire_swfw_sync(hw, mask);
3046 [ # # ]: 0 : if (status)
3047 : : return status;
3048 : :
3049 : 0 : status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
3050 : : IXGBE_HI_COMMAND_TIMEOUT);
3051 [ # # ]: 0 : if (!status) {
3052 : 0 : *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
3053 : : FW_NVM_DATA_OFFSET);
3054 : : }
3055 : :
3056 : 0 : hw->mac.ops.release_swfw_sync(hw, mask);
3057 : 0 : return status;
3058 : : }
3059 : :
3060 : : /**
3061 : : * ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif
3062 : : * @hw: pointer to hardware structure
3063 : : * @offset: offset of word in the EEPROM to read
3064 : : * @words: number of words
3065 : : * @data: word(s) read from the EEPROM
3066 : : *
3067 : : * Reads a 16 bit word(s) from the EEPROM using the hostif.
3068 : : **/
3069 : 0 : s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
3070 : : u16 offset, u16 words, u16 *data)
3071 : : {
3072 : : const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
3073 : : struct ixgbe_hic_read_shadow_ram buffer;
3074 : : u32 current_word = 0;
3075 : : u16 words_to_read;
3076 : : s32 status;
3077 : : u32 i;
3078 : :
3079 : 0 : DEBUGFUNC("ixgbe_read_ee_hostif_buffer_X550");
3080 : :
3081 : : /* Take semaphore for the entire operation. */
3082 : 0 : status = hw->mac.ops.acquire_swfw_sync(hw, mask);
3083 [ # # ]: 0 : if (status) {
3084 : 0 : DEBUGOUT("EEPROM read buffer - semaphore failed\n");
3085 : 0 : return status;
3086 : : }
3087 : :
3088 [ # # ]: 0 : while (words) {
3089 : : if (words > FW_MAX_READ_BUFFER_SIZE / 2)
3090 : : words_to_read = FW_MAX_READ_BUFFER_SIZE / 2;
3091 : : else
3092 : : words_to_read = words;
3093 : :
3094 : 0 : buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
3095 : 0 : buffer.hdr.req.buf_lenh = 0;
3096 : 0 : buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
3097 : 0 : buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
3098 : :
3099 : : /* convert offset from words to bytes */
3100 [ # # ]: 0 : buffer.address = IXGBE_CPU_TO_BE32((offset + current_word) * 2);
3101 [ # # ]: 0 : buffer.length = IXGBE_CPU_TO_BE16(words_to_read * 2);
3102 : 0 : buffer.pad2 = 0;
3103 : 0 : buffer.data = 0;
3104 : 0 : buffer.pad3 = 0;
3105 : :
3106 : 0 : status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
3107 : : IXGBE_HI_COMMAND_TIMEOUT);
3108 : :
3109 [ # # ]: 0 : if (status) {
3110 : 0 : DEBUGOUT("Host interface command failed\n");
3111 : 0 : goto out;
3112 : : }
3113 : :
3114 [ # # ]: 0 : for (i = 0; i < words_to_read; i++) {
3115 : 0 : u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) +
3116 : : 2 * i;
3117 : 0 : u32 value = IXGBE_READ_REG(hw, reg);
3118 : :
3119 : 0 : data[current_word] = (u16)(value & 0xffff);
3120 : 0 : current_word++;
3121 : 0 : i++;
3122 [ # # ]: 0 : if (i < words_to_read) {
3123 : 0 : value >>= 16;
3124 : 0 : data[current_word] = (u16)(value & 0xffff);
3125 : 0 : current_word++;
3126 : : }
3127 : : }
3128 : 0 : words -= words_to_read;
3129 : : }
3130 : :
3131 : 0 : out:
3132 : 0 : hw->mac.ops.release_swfw_sync(hw, mask);
3133 : 0 : return status;
3134 : : }
3135 : :
3136 : : /**
3137 : : * ixgbe_write_ee_hostif_data_X550 - Write EEPROM word using hostif
3138 : : * @hw: pointer to hardware structure
3139 : : * @offset: offset of word in the EEPROM to write
3140 : : * @data: word write to the EEPROM
3141 : : *
3142 : : * Write a 16 bit word to the EEPROM using the hostif.
3143 : : **/
3144 : 0 : s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
3145 : : u16 data)
3146 : : {
3147 : : s32 status;
3148 : : struct ixgbe_hic_write_shadow_ram buffer;
3149 : :
3150 : 0 : DEBUGFUNC("ixgbe_write_ee_hostif_data_X550");
3151 : :
3152 : 0 : buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
3153 : 0 : buffer.hdr.req.buf_lenh = 0;
3154 : 0 : buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
3155 : 0 : buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
3156 : :
3157 : : /* one word */
3158 : 0 : buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
3159 : 0 : buffer.data = data;
3160 [ # # ]: 0 : buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
3161 : :
3162 : 0 : status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
3163 : : sizeof(buffer),
3164 : : IXGBE_HI_COMMAND_TIMEOUT, true);
3165 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
3166 : 0 : DEBUGOUT2("for offset %04x failed with status %d\n",
3167 : : offset, status);
3168 : 0 : return status;
3169 : : }
3170 : :
3171 [ # # ]: 0 : if (buffer.hdr.rsp.buf_lenh_status != FW_CEM_RESP_STATUS_SUCCESS) {
3172 : 0 : DEBUGOUT2("for offset %04x host interface return status %02x\n",
3173 : : offset, buffer.hdr.rsp.buf_lenh_status);
3174 : 0 : return IXGBE_ERR_HOST_INTERFACE_COMMAND;
3175 : : }
3176 : :
3177 : : return status;
3178 : : }
3179 : :
3180 : : /**
3181 : : * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
3182 : : * @hw: pointer to hardware structure
3183 : : * @offset: offset of word in the EEPROM to write
3184 : : * @data: word write to the EEPROM
3185 : : *
3186 : : * Write a 16 bit word to the EEPROM using the hostif.
3187 : : **/
3188 : 0 : s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset,
3189 : : u16 data)
3190 : : {
3191 : : s32 status = IXGBE_SUCCESS;
3192 : :
3193 : 0 : DEBUGFUNC("ixgbe_write_ee_hostif_X550");
3194 : :
3195 [ # # ]: 0 : if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
3196 : : IXGBE_SUCCESS) {
3197 : 0 : status = ixgbe_write_ee_hostif_data_X550(hw, offset, data);
3198 : 0 : hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
3199 : : } else {
3200 : 0 : DEBUGOUT("write ee hostif failed to get semaphore");
3201 : : status = IXGBE_ERR_SWFW_SYNC;
3202 : : }
3203 : :
3204 : 0 : return status;
3205 : : }
3206 : :
3207 : : /**
3208 : : * ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif
3209 : : * @hw: pointer to hardware structure
3210 : : * @offset: offset of word in the EEPROM to write
3211 : : * @words: number of words
3212 : : * @data: word(s) write to the EEPROM
3213 : : *
3214 : : * Write a 16 bit word(s) to the EEPROM using the hostif.
3215 : : **/
3216 : 0 : s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
3217 : : u16 offset, u16 words, u16 *data)
3218 : : {
3219 : : s32 status = IXGBE_SUCCESS;
3220 : : u32 i = 0;
3221 : :
3222 : 0 : DEBUGFUNC("ixgbe_write_ee_hostif_buffer_X550");
3223 : :
3224 : : /* Take semaphore for the entire operation. */
3225 : 0 : status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
3226 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
3227 : 0 : DEBUGOUT("EEPROM write buffer - semaphore failed\n");
3228 : 0 : goto out;
3229 : : }
3230 : :
3231 [ # # ]: 0 : for (i = 0; i < words; i++) {
3232 : 0 : status = ixgbe_write_ee_hostif_data_X550(hw, offset + i,
3233 : 0 : data[i]);
3234 : :
3235 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
3236 : 0 : DEBUGOUT("Eeprom buffered write failed\n");
3237 : 0 : break;
3238 : : }
3239 : : }
3240 : :
3241 : 0 : hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
3242 : 0 : out:
3243 : :
3244 : 0 : return status;
3245 : : }
3246 : :
3247 : : /**
3248 : : * ixgbe_checksum_ptr_x550 - Checksum one pointer region
3249 : : * @hw: pointer to hardware structure
3250 : : * @ptr: pointer offset in eeprom
3251 : : * @size: size of section pointed by ptr, if 0 first word will be used as size
3252 : : * @csum: address of checksum to update
3253 : : * @buffer: pointer to buffer containing calculated checksum
3254 : : * @buffer_size: size of buffer
3255 : : *
3256 : : * Returns error status for any failure
3257 : : */
3258 : 0 : STATIC s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
3259 : : u16 size, u16 *csum, u16 *buffer,
3260 : : u32 buffer_size)
3261 : : {
3262 : : u16 buf[256];
3263 : : s32 status;
3264 : : u16 length, bufsz, i, start;
3265 : : u16 *local_buffer;
3266 : :
3267 : : bufsz = sizeof(buf) / sizeof(buf[0]);
3268 : :
3269 : : /* Read a chunk at the pointer location */
3270 [ # # ]: 0 : if (!buffer) {
3271 : 0 : status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf);
3272 [ # # ]: 0 : if (status) {
3273 : 0 : DEBUGOUT("Failed to read EEPROM image\n");
3274 : 0 : return status;
3275 : : }
3276 : : local_buffer = buf;
3277 : : } else {
3278 [ # # ]: 0 : if (buffer_size < ptr)
3279 : : return IXGBE_ERR_PARAM;
3280 : 0 : local_buffer = &buffer[ptr];
3281 : : }
3282 : :
3283 [ # # ]: 0 : if (size) {
3284 : : start = 0;
3285 : : length = size;
3286 : : } else {
3287 : : start = 1;
3288 : 0 : length = local_buffer[0];
3289 : :
3290 : : /* Skip pointer section if length is invalid. */
3291 [ # # ]: 0 : if (length == 0xFFFF || length == 0 ||
3292 [ # # ]: 0 : (ptr + length) >= hw->eeprom.word_size)
3293 : : return IXGBE_SUCCESS;
3294 : : }
3295 : :
3296 [ # # # # ]: 0 : if (buffer && ((u32)start + (u32)length > buffer_size))
3297 : : return IXGBE_ERR_PARAM;
3298 : :
3299 [ # # ]: 0 : for (i = start; length; i++, length--) {
3300 [ # # ]: 0 : if (i == bufsz && !buffer) {
3301 : 0 : ptr += bufsz;
3302 : : i = 0;
3303 : : if (length < bufsz)
3304 : : bufsz = length;
3305 : :
3306 : : /* Read a chunk at the pointer location */
3307 : 0 : status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr,
3308 : : bufsz, buf);
3309 [ # # ]: 0 : if (status) {
3310 : 0 : DEBUGOUT("Failed to read EEPROM image\n");
3311 : 0 : return status;
3312 : : }
3313 : : }
3314 : 0 : *csum += local_buffer[i];
3315 : : }
3316 : : return IXGBE_SUCCESS;
3317 : : }
3318 : :
3319 : : /**
3320 : : * ixgbe_calc_checksum_X550 - Calculates and returns the checksum
3321 : : * @hw: pointer to hardware structure
3322 : : * @buffer: pointer to buffer containing calculated checksum
3323 : : * @buffer_size: size of buffer
3324 : : *
3325 : : * Returns a negative error code on error, or the 16-bit checksum
3326 : : **/
3327 : 0 : s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, u32 buffer_size)
3328 : : {
3329 : : u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1];
3330 : : u16 *local_buffer;
3331 : : s32 status;
3332 : 0 : u16 checksum = 0;
3333 : : u16 pointer, i, size;
3334 : :
3335 : 0 : DEBUGFUNC("ixgbe_calc_eeprom_checksum_X550");
3336 : :
3337 : 0 : hw->eeprom.ops.init_params(hw);
3338 : :
3339 [ # # ]: 0 : if (!buffer) {
3340 : : /* Read pointer area */
3341 : 0 : status = ixgbe_read_ee_hostif_buffer_X550(hw, 0,
3342 : : IXGBE_EEPROM_LAST_WORD + 1,
3343 : : eeprom_ptrs);
3344 [ # # ]: 0 : if (status) {
3345 : 0 : DEBUGOUT("Failed to read EEPROM image\n");
3346 : 0 : return status;
3347 : : }
3348 : : local_buffer = eeprom_ptrs;
3349 : : } else {
3350 [ # # ]: 0 : if (buffer_size < IXGBE_EEPROM_LAST_WORD)
3351 : : return IXGBE_ERR_PARAM;
3352 : : local_buffer = buffer;
3353 : : }
3354 : :
3355 : : /*
3356 : : * For X550 hardware include 0x0-0x41 in the checksum, skip the
3357 : : * checksum word itself
3358 : : */
3359 [ # # ]: 0 : for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++)
3360 [ # # ]: 0 : if (i != IXGBE_EEPROM_CHECKSUM)
3361 : 0 : checksum += local_buffer[i];
3362 : :
3363 : : /*
3364 : : * Include all data from pointers 0x3, 0x6-0xE. This excludes the
3365 : : * FW, PHY module, and PCIe Expansion/Option ROM pointers.
3366 : : */
3367 [ # # ]: 0 : for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) {
3368 [ # # ]: 0 : if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
3369 : 0 : continue;
3370 : :
3371 : 0 : pointer = local_buffer[i];
3372 : :
3373 : : /* Skip pointer section if the pointer is invalid. */
3374 [ # # ]: 0 : if (pointer == 0xFFFF || pointer == 0 ||
3375 [ # # ]: 0 : pointer >= hw->eeprom.word_size)
3376 : 0 : continue;
3377 : :
3378 [ # # # ]: 0 : switch (i) {
3379 : : case IXGBE_PCIE_GENERAL_PTR:
3380 : : size = IXGBE_IXGBE_PCIE_GENERAL_SIZE;
3381 : : break;
3382 : 0 : case IXGBE_PCIE_CONFIG0_PTR:
3383 : : case IXGBE_PCIE_CONFIG1_PTR:
3384 : : size = IXGBE_PCIE_CONFIG_SIZE;
3385 : 0 : break;
3386 : 0 : default:
3387 : : size = 0;
3388 : 0 : break;
3389 : : }
3390 : :
3391 : 0 : status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum,
3392 : : buffer, buffer_size);
3393 [ # # ]: 0 : if (status)
3394 : 0 : return status;
3395 : : }
3396 : :
3397 : 0 : checksum = (u16)IXGBE_EEPROM_SUM - checksum;
3398 : :
3399 : 0 : return (s32)checksum;
3400 : : }
3401 : :
3402 : : /**
3403 : : * ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum
3404 : : * @hw: pointer to hardware structure
3405 : : *
3406 : : * Returns a negative error code on error, or the 16-bit checksum
3407 : : **/
3408 : 0 : s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
3409 : : {
3410 : 0 : return ixgbe_calc_checksum_X550(hw, NULL, 0);
3411 : : }
3412 : :
3413 : : /**
3414 : : * ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum
3415 : : * @hw: pointer to hardware structure
3416 : : * @checksum_val: calculated checksum
3417 : : *
3418 : : * Performs checksum calculation and validates the EEPROM checksum. If the
3419 : : * caller does not need checksum_val, the value can be NULL.
3420 : : **/
3421 : 0 : s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, u16 *checksum_val)
3422 : : {
3423 : : s32 status;
3424 : : u16 checksum;
3425 : 0 : u16 read_checksum = 0;
3426 : :
3427 : 0 : DEBUGFUNC("ixgbe_validate_eeprom_checksum_X550");
3428 : :
3429 : : /* Read the first word from the EEPROM. If this times out or fails, do
3430 : : * not continue or we could be in for a very long wait while every
3431 : : * EEPROM read fails
3432 : : */
3433 : 0 : status = hw->eeprom.ops.read(hw, 0, &checksum);
3434 [ # # ]: 0 : if (status) {
3435 : 0 : DEBUGOUT("EEPROM read failed\n");
3436 : 0 : return status;
3437 : : }
3438 : :
3439 : 0 : status = hw->eeprom.ops.calc_checksum(hw);
3440 [ # # ]: 0 : if (status < 0)
3441 : : return status;
3442 : :
3443 : 0 : checksum = (u16)(status & 0xffff);
3444 : :
3445 : 0 : status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
3446 : : &read_checksum);
3447 [ # # ]: 0 : if (status)
3448 : : return status;
3449 : :
3450 : : /* Verify read checksum from EEPROM is the same as
3451 : : * calculated checksum
3452 : : */
3453 [ # # ]: 0 : if (read_checksum != checksum) {
3454 : : status = IXGBE_ERR_EEPROM_CHECKSUM;
3455 : 0 : ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
3456 : : "Invalid EEPROM checksum");
3457 : : }
3458 : :
3459 : : /* If the user cares, return the calculated checksum */
3460 [ # # ]: 0 : if (checksum_val)
3461 : 0 : *checksum_val = checksum;
3462 : :
3463 : : return status;
3464 : : }
3465 : :
3466 : : /**
3467 : : * ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash
3468 : : * @hw: pointer to hardware structure
3469 : : *
3470 : : * After writing EEPROM to shadow RAM using EEWR register, software calculates
3471 : : * checksum and updates the EEPROM and instructs the hardware to update
3472 : : * the flash.
3473 : : **/
3474 : 0 : s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw)
3475 : : {
3476 : : s32 status;
3477 : 0 : u16 checksum = 0;
3478 : :
3479 : 0 : DEBUGFUNC("ixgbe_update_eeprom_checksum_X550");
3480 : :
3481 : : /* Read the first word from the EEPROM. If this times out or fails, do
3482 : : * not continue or we could be in for a very long wait while every
3483 : : * EEPROM read fails
3484 : : */
3485 : 0 : status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum);
3486 [ # # ]: 0 : if (status) {
3487 : 0 : DEBUGOUT("EEPROM read failed\n");
3488 : 0 : return status;
3489 : : }
3490 : :
3491 : 0 : status = ixgbe_calc_eeprom_checksum_X550(hw);
3492 [ # # ]: 0 : if (status < 0)
3493 : : return status;
3494 : :
3495 : 0 : checksum = (u16)(status & 0xffff);
3496 : :
3497 : 0 : status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
3498 : : checksum);
3499 [ # # ]: 0 : if (status)
3500 : : return status;
3501 : :
3502 : 0 : status = ixgbe_update_flash_X550(hw);
3503 : :
3504 : 0 : return status;
3505 : : }
3506 : :
3507 : : /**
3508 : : * ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device
3509 : : * @hw: pointer to hardware structure
3510 : : *
3511 : : * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash.
3512 : : **/
3513 : 0 : s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw)
3514 : : {
3515 : : s32 status = IXGBE_SUCCESS;
3516 : : union ixgbe_hic_hdr2 buffer;
3517 : :
3518 : 0 : DEBUGFUNC("ixgbe_update_flash_X550");
3519 : :
3520 : 0 : buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD;
3521 : 0 : buffer.req.buf_lenh = 0;
3522 : 0 : buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN;
3523 : 0 : buffer.req.checksum = FW_DEFAULT_CHECKSUM;
3524 : :
3525 : 0 : status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
3526 : : sizeof(buffer),
3527 : : IXGBE_HI_COMMAND_TIMEOUT, false);
3528 : :
3529 : 0 : return status;
3530 : : }
3531 : :
3532 : : /**
3533 : : * ixgbe_get_supported_physical_layer_X550em - Returns physical layer type
3534 : : * @hw: pointer to hardware structure
3535 : : *
3536 : : * Determines physical layer capabilities of the current configuration.
3537 : : **/
3538 : 0 : u64 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
3539 : : {
3540 : : u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
3541 : 0 : u16 ext_ability = 0;
3542 : :
3543 : 0 : DEBUGFUNC("ixgbe_get_supported_physical_layer_X550em");
3544 : :
3545 : 0 : hw->phy.ops.identify(hw);
3546 : :
3547 [ # # # # : 0 : switch (hw->phy.type) {
# # # # ]
3548 : 0 : case ixgbe_phy_x550em_kr:
3549 [ # # ]: 0 : if (hw->mac.type == ixgbe_mac_X550EM_a) {
3550 [ # # ]: 0 : if (hw->phy.nw_mng_if_sel &
3551 : : IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
3552 : : physical_layer =
3553 : : IXGBE_PHYSICAL_LAYER_2500BASE_KX;
3554 : : break;
3555 [ # # ]: 0 : } else if (hw->device_id ==
3556 : : IXGBE_DEV_ID_X550EM_A_KR_L) {
3557 : : physical_layer =
3558 : : IXGBE_PHYSICAL_LAYER_1000BASE_KX;
3559 : : break;
3560 : : }
3561 : : }
3562 : : physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR |
3563 : : IXGBE_PHYSICAL_LAYER_1000BASE_KX;
3564 : 0 : break;
3565 : 0 : case ixgbe_phy_x550em_xfi:
3566 : : physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR |
3567 : : IXGBE_PHYSICAL_LAYER_1000BASE_KX;
3568 : 0 : break;
3569 : 0 : case ixgbe_phy_x550em_kx4:
3570 : : physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
3571 : : IXGBE_PHYSICAL_LAYER_1000BASE_KX;
3572 : 0 : break;
3573 : 0 : case ixgbe_phy_x550em_ext_t:
3574 : 0 : hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
3575 : : IXGBE_MDIO_PMA_PMD_DEV_TYPE,
3576 : : &ext_ability);
3577 [ # # ]: 0 : if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
3578 : : physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
3579 [ # # ]: 0 : if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
3580 : 0 : physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
3581 : : break;
3582 : 0 : case ixgbe_phy_fw:
3583 [ # # ]: 0 : if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_1GB_FULL)
3584 : : physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
3585 [ # # ]: 0 : if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_100_FULL)
3586 : 0 : physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
3587 [ # # ]: 0 : if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_10_FULL)
3588 : 0 : physical_layer |= IXGBE_PHYSICAL_LAYER_10BASE_T;
3589 : : break;
3590 : 0 : case ixgbe_phy_sgmii:
3591 : : physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
3592 : 0 : break;
3593 : 0 : case ixgbe_phy_ext_1g_t:
3594 : : physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
3595 : 0 : break;
3596 : : default:
3597 : : break;
3598 : : }
3599 : :
3600 [ # # ]: 0 : if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber)
3601 : 0 : physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw);
3602 : :
3603 : 0 : return physical_layer;
3604 : : }
3605 : :
3606 : : /**
3607 : : * ixgbe_get_bus_info_X550em - Set PCI bus info
3608 : : * @hw: pointer to hardware structure
3609 : : *
3610 : : * Sets bus link width and speed to unknown because X550em is
3611 : : * not a PCI device.
3612 : : **/
3613 : 0 : s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
3614 : : {
3615 : :
3616 : 0 : DEBUGFUNC("ixgbe_get_bus_info_x550em");
3617 : :
3618 : 0 : hw->bus.width = ixgbe_bus_width_unknown;
3619 : 0 : hw->bus.speed = ixgbe_bus_speed_unknown;
3620 : :
3621 : 0 : hw->mac.ops.set_lan_id(hw);
3622 : :
3623 : 0 : return IXGBE_SUCCESS;
3624 : : }
3625 : :
3626 : : /**
3627 : : * ixgbe_disable_rx_x550 - Disable RX unit
3628 : : * @hw: pointer to hardware structure
3629 : : *
3630 : : * Enables the Rx DMA unit for x550
3631 : : **/
3632 : 0 : void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
3633 : : {
3634 : : u32 rxctrl, pfdtxgswc;
3635 : : s32 status;
3636 : : struct ixgbe_hic_disable_rxen fw_cmd;
3637 : :
3638 : 0 : DEBUGFUNC("ixgbe_enable_rx_dma_x550");
3639 : :
3640 : 0 : rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
3641 [ # # ]: 0 : if (rxctrl & IXGBE_RXCTRL_RXEN) {
3642 : 0 : pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
3643 [ # # ]: 0 : if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
3644 : 0 : pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
3645 : 0 : IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
3646 : 0 : hw->mac.set_lben = true;
3647 : : } else {
3648 : 0 : hw->mac.set_lben = false;
3649 : : }
3650 : :
3651 : 0 : fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD;
3652 : 0 : fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN;
3653 : 0 : fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
3654 : 0 : fw_cmd.port_number = (u8)hw->bus.lan_id;
3655 : :
3656 : 0 : status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
3657 : : sizeof(struct ixgbe_hic_disable_rxen),
3658 : : IXGBE_HI_COMMAND_TIMEOUT, true);
3659 : :
3660 : : /* If we fail - disable RX using register write */
3661 [ # # ]: 0 : if (status) {
3662 : 0 : rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
3663 [ # # ]: 0 : if (rxctrl & IXGBE_RXCTRL_RXEN) {
3664 : 0 : rxctrl &= ~IXGBE_RXCTRL_RXEN;
3665 : 0 : IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
3666 : : }
3667 : : }
3668 : : }
3669 : 0 : }
3670 : :
3671 : : /**
3672 : : * ixgbe_enter_lplu_t_x550em - Transition to low power states
3673 : : * @hw: pointer to hardware structure
3674 : : *
3675 : : * Configures Low Power Link Up on transition to low power states
3676 : : * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting the
3677 : : * X557 PHY immediately prior to entering LPLU.
3678 : : **/
3679 : 0 : s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
3680 : : {
3681 : : u16 an_10g_cntl_reg, autoneg_reg, speed;
3682 : : s32 status;
3683 : : ixgbe_link_speed lcd_speed;
3684 : : u32 save_autoneg;
3685 : : bool link_up;
3686 : :
3687 : : /* SW LPLU not required on later HW revisions. */
3688 [ # # ]: 0 : if ((hw->mac.type == ixgbe_mac_X550EM_x) &&
3689 [ # # ]: 0 : (IXGBE_FUSES0_REV_MASK &
3690 : 0 : IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))))
3691 : : return IXGBE_SUCCESS;
3692 : :
3693 : : /* If blocked by MNG FW, then don't restart AN */
3694 [ # # ]: 0 : if (ixgbe_check_reset_blocked(hw))
3695 : : return IXGBE_SUCCESS;
3696 : :
3697 : 0 : status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
3698 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3699 : : return status;
3700 : :
3701 : 0 : status = ixgbe_read_eeprom(hw, NVM_INIT_CTRL_3, &hw->eeprom.ctrl_word_3);
3702 : :
3703 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3704 : : return status;
3705 : :
3706 : : /* If link is down, LPLU disabled in NVM, WoL disabled, or manageability
3707 : : * disabled, then force link down by entering low power mode.
3708 : : */
3709 [ # # # # ]: 0 : if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
3710 [ # # # # ]: 0 : !(hw->wol_enabled || ixgbe_mng_present(hw)))
3711 : 0 : return ixgbe_set_copper_phy_power(hw, FALSE);
3712 : :
3713 : : /* Determine LCD */
3714 : 0 : status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed);
3715 : :
3716 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3717 : : return status;
3718 : :
3719 : : /* If no valid LCD link speed, then force link down and exit. */
3720 [ # # ]: 0 : if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN)
3721 : 0 : return ixgbe_set_copper_phy_power(hw, FALSE);
3722 : :
3723 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
3724 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
3725 : : &speed);
3726 : :
3727 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3728 : : return status;
3729 : :
3730 : : /* If no link now, speed is invalid so take link down */
3731 : 0 : status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
3732 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3733 : 0 : return ixgbe_set_copper_phy_power(hw, false);
3734 : :
3735 : : /* clear everything but the speed bits */
3736 : 0 : speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK;
3737 : :
3738 : : /* If current speed is already LCD, then exit. */
3739 [ # # ]: 0 : if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) &&
3740 [ # # # # ]: 0 : (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) ||
3741 : 0 : ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) &&
3742 [ # # ]: 0 : (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL)))
3743 : : return status;
3744 : :
3745 : : /* Clear AN completed indication */
3746 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
3747 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
3748 : : &autoneg_reg);
3749 : :
3750 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3751 : : return status;
3752 : :
3753 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
3754 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
3755 : : &an_10g_cntl_reg);
3756 : :
3757 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3758 : : return status;
3759 : :
3760 : 0 : status = hw->phy.ops.read_reg(hw,
3761 : : IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
3762 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
3763 : : &autoneg_reg);
3764 : :
3765 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3766 : : return status;
3767 : :
3768 : 0 : save_autoneg = hw->phy.autoneg_advertised;
3769 : :
3770 : : /* Setup link at least common link speed */
3771 : 0 : status = hw->mac.ops.setup_link(hw, lcd_speed, false);
3772 : :
3773 : : /* restore autoneg from before setting lplu speed */
3774 : 0 : hw->phy.autoneg_advertised = save_autoneg;
3775 : :
3776 : 0 : return status;
3777 : : }
3778 : :
3779 : : /**
3780 : : * ixgbe_get_lcd_t_x550em - Determine lowest common denominator
3781 : : * @hw: pointer to hardware structure
3782 : : * @lcd_speed: pointer to lowest common link speed
3783 : : *
3784 : : * Determine lowest common link speed with link partner.
3785 : : **/
3786 : 0 : s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed)
3787 : : {
3788 : : u16 an_lp_status;
3789 : : s32 status;
3790 : 0 : u16 word = hw->eeprom.ctrl_word_3;
3791 : :
3792 : 0 : *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
3793 : :
3794 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
3795 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
3796 : : &an_lp_status);
3797 : :
3798 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
3799 : : return status;
3800 : :
3801 : : /* If link partner advertised 1G, return 1G */
3802 [ # # ]: 0 : if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) {
3803 : 0 : *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL;
3804 : 0 : return status;
3805 : : }
3806 : :
3807 : : /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */
3808 [ # # # # : 0 : if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) ||
# # ]
3809 : : (word & NVM_INIT_CTRL_3_D10GMP_PORT0))
3810 : : return status;
3811 : :
3812 : : /* Link partner not capable of lower speeds, return 10G */
3813 : 0 : *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL;
3814 : 0 : return status;
3815 : : }
3816 : :
3817 : : /**
3818 : : * ixgbe_setup_fc_X550em - Set up flow control
3819 : : * @hw: pointer to hardware structure
3820 : : *
3821 : : * Called at init time to set up flow control.
3822 : : **/
3823 : 0 : s32 ixgbe_setup_fc_X550em(struct ixgbe_hw *hw)
3824 : : {
3825 : : s32 ret_val = IXGBE_SUCCESS;
3826 : : u32 pause, asm_dir, reg_val;
3827 : :
3828 : 0 : DEBUGFUNC("ixgbe_setup_fc_X550em");
3829 : :
3830 : : /* Validate the requested mode */
3831 [ # # # # ]: 0 : if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
3832 : 0 : ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
3833 : : "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
3834 : : ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
3835 : 0 : goto out;
3836 : : }
3837 : :
3838 : : /* 10gig parts do not have a word in the EEPROM to determine the
3839 : : * default flow control setting, so we explicitly set it to full.
3840 : : */
3841 [ # # ]: 0 : if (hw->fc.requested_mode == ixgbe_fc_default)
3842 : 0 : hw->fc.requested_mode = ixgbe_fc_full;
3843 : :
3844 : : /* Determine PAUSE and ASM_DIR bits. */
3845 [ # # ]: 0 : switch (hw->fc.requested_mode) {
3846 : : case ixgbe_fc_none:
3847 : : pause = 0;
3848 : : asm_dir = 0;
3849 : : break;
3850 : : case ixgbe_fc_tx_pause:
3851 : : pause = 0;
3852 : : asm_dir = 1;
3853 : : break;
3854 : : case ixgbe_fc_rx_pause:
3855 : : /* Rx Flow control is enabled and Tx Flow control is
3856 : : * disabled by software override. Since there really
3857 : : * isn't a way to advertise that we are capable of RX
3858 : : * Pause ONLY, we will advertise that we support both
3859 : : * symmetric and asymmetric Rx PAUSE, as such we fall
3860 : : * through to the fc_full statement. Later, we will
3861 : : * disable the adapter's ability to send PAUSE frames.
3862 : : */
3863 : : case ixgbe_fc_full:
3864 : : pause = 1;
3865 : : asm_dir = 1;
3866 : : break;
3867 : 0 : default:
3868 : 0 : ERROR_REPORT1(IXGBE_ERROR_ARGUMENT,
3869 : : "Flow control param set incorrectly\n");
3870 : : ret_val = IXGBE_ERR_CONFIG;
3871 : 0 : goto out;
3872 : : }
3873 : :
3874 [ # # # ]: 0 : switch (hw->device_id) {
3875 : 0 : case IXGBE_DEV_ID_X550EM_X_KR:
3876 : : case IXGBE_DEV_ID_X550EM_A_KR:
3877 : : case IXGBE_DEV_ID_X550EM_A_KR_L:
3878 : 0 : ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
3879 [ # # ]: 0 : IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
3880 : : IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val);
3881 [ # # ]: 0 : if (ret_val != IXGBE_SUCCESS)
3882 : 0 : goto out;
3883 : 0 : reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
3884 : : IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
3885 [ # # ]: 0 : if (pause)
3886 : 0 : reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
3887 [ # # ]: 0 : if (asm_dir)
3888 : 0 : reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
3889 : 0 : ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
3890 [ # # ]: 0 : IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
3891 : : IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
3892 : :
3893 : : /* This device does not fully support AN. */
3894 : 0 : hw->fc.disable_fc_autoneg = true;
3895 : 0 : break;
3896 : 0 : case IXGBE_DEV_ID_X550EM_X_XFI:
3897 : 0 : hw->fc.disable_fc_autoneg = true;
3898 : 0 : break;
3899 : : default:
3900 : : break;
3901 : : }
3902 : :
3903 : 0 : out:
3904 : 0 : return ret_val;
3905 : : }
3906 : :
3907 : : /**
3908 : : * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37
3909 : : * @hw: pointer to hardware structure
3910 : : *
3911 : : * Enable flow control according to IEEE clause 37.
3912 : : **/
3913 : 0 : void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
3914 : : {
3915 : : u32 link_s1, lp_an_page_low, an_cntl_1;
3916 : : s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
3917 : : ixgbe_link_speed speed;
3918 : : bool link_up;
3919 : :
3920 : : /* AN should have completed when the cable was plugged in.
3921 : : * Look for reasons to bail out. Bail out if:
3922 : : * - FC autoneg is disabled, or if
3923 : : * - link is not up.
3924 : : */
3925 [ # # ]: 0 : if (hw->fc.disable_fc_autoneg) {
3926 : 0 : ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
3927 : : "Flow control autoneg is disabled");
3928 : 0 : goto out;
3929 : : }
3930 : :
3931 : 0 : hw->mac.ops.check_link(hw, &speed, &link_up, false);
3932 [ # # ]: 0 : if (!link_up) {
3933 : 0 : ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down");
3934 : 0 : goto out;
3935 : : }
3936 : :
3937 : : /* Check at auto-negotiation has completed */
3938 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
3939 [ # # ]: 0 : IXGBE_KRM_LINK_S1(hw->bus.lan_id),
3940 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1);
3941 : :
3942 [ # # ]: 0 : if (status != IXGBE_SUCCESS ||
3943 [ # # ]: 0 : (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
3944 : 0 : DEBUGOUT("Auto-Negotiation did not complete\n");
3945 : : status = IXGBE_ERR_FC_NOT_NEGOTIATED;
3946 : 0 : goto out;
3947 : : }
3948 : :
3949 : : /* Read the 10g AN autoc and LP ability registers and resolve
3950 : : * local flow control settings accordingly
3951 : : */
3952 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
3953 [ # # ]: 0 : IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
3954 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1);
3955 : :
3956 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
3957 : 0 : DEBUGOUT("Auto-Negotiation did not complete\n");
3958 : 0 : goto out;
3959 : : }
3960 : :
3961 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
3962 [ # # ]: 0 : IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id),
3963 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low);
3964 : :
3965 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
3966 : 0 : DEBUGOUT("Auto-Negotiation did not complete\n");
3967 : 0 : goto out;
3968 : : }
3969 : :
3970 : 0 : status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low,
3971 : : IXGBE_KRM_AN_CNTL_1_SYM_PAUSE,
3972 : : IXGBE_KRM_AN_CNTL_1_ASM_PAUSE,
3973 : : IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE,
3974 : : IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE);
3975 : :
3976 : 0 : out:
3977 [ # # ]: 0 : if (status == IXGBE_SUCCESS) {
3978 : 0 : hw->fc.fc_was_autonegged = true;
3979 : : } else {
3980 : 0 : hw->fc.fc_was_autonegged = false;
3981 : 0 : hw->fc.current_mode = hw->fc.requested_mode;
3982 : : }
3983 : 0 : }
3984 : :
3985 : : /**
3986 : : * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings
3987 : : * @hw: pointer to hardware structure
3988 : : *
3989 : : **/
3990 : 0 : void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw)
3991 : : {
3992 : 0 : hw->fc.fc_was_autonegged = false;
3993 : 0 : hw->fc.current_mode = hw->fc.requested_mode;
3994 : 0 : }
3995 : :
3996 : : /**
3997 : : * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37
3998 : : * @hw: pointer to hardware structure
3999 : : *
4000 : : * Enable flow control according to IEEE clause 37.
4001 : : **/
4002 : 0 : void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)
4003 : : {
4004 : : s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
4005 : 0 : u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
4006 : : ixgbe_link_speed speed;
4007 : : bool link_up;
4008 : :
4009 : : /* AN should have completed when the cable was plugged in.
4010 : : * Look for reasons to bail out. Bail out if:
4011 : : * - FC autoneg is disabled, or if
4012 : : * - link is not up.
4013 : : */
4014 [ # # ]: 0 : if (hw->fc.disable_fc_autoneg) {
4015 : 0 : ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
4016 : : "Flow control autoneg is disabled");
4017 : 0 : goto out;
4018 : : }
4019 : :
4020 : 0 : hw->mac.ops.check_link(hw, &speed, &link_up, false);
4021 [ # # ]: 0 : if (!link_up) {
4022 : 0 : ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down");
4023 : 0 : goto out;
4024 : : }
4025 : :
4026 : : /* Check if auto-negotiation has completed */
4027 : 0 : status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info);
4028 [ # # ]: 0 : if (status != IXGBE_SUCCESS ||
4029 [ # # ]: 0 : !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) {
4030 : 0 : DEBUGOUT("Auto-Negotiation did not complete\n");
4031 : : status = IXGBE_ERR_FC_NOT_NEGOTIATED;
4032 : 0 : goto out;
4033 : : }
4034 : :
4035 : : /* Negotiate the flow control */
4036 : 0 : status = ixgbe_negotiate_fc(hw, info[0], info[0],
4037 : : FW_PHY_ACT_GET_LINK_INFO_FC_RX,
4038 : : FW_PHY_ACT_GET_LINK_INFO_FC_TX,
4039 : : FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX,
4040 : : FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX);
4041 : :
4042 : : out:
4043 [ # # ]: 0 : if (status == IXGBE_SUCCESS) {
4044 : 0 : hw->fc.fc_was_autonegged = true;
4045 : : } else {
4046 : 0 : hw->fc.fc_was_autonegged = false;
4047 : 0 : hw->fc.current_mode = hw->fc.requested_mode;
4048 : : }
4049 : 0 : }
4050 : :
4051 : : /**
4052 : : * ixgbe_setup_fc_backplane_x550em_a - Set up flow control
4053 : : * @hw: pointer to hardware structure
4054 : : *
4055 : : * Called at init time to set up flow control.
4056 : : **/
4057 : 0 : s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw)
4058 : : {
4059 : : s32 status = IXGBE_SUCCESS;
4060 : 0 : u32 an_cntl = 0;
4061 : :
4062 : 0 : DEBUGFUNC("ixgbe_setup_fc_backplane_x550em_a");
4063 : :
4064 : : /* Validate the requested mode */
4065 [ # # # # ]: 0 : if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
4066 : 0 : ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
4067 : : "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
4068 : 0 : return IXGBE_ERR_INVALID_LINK_SETTINGS;
4069 : : }
4070 : :
4071 [ # # ]: 0 : if (hw->fc.requested_mode == ixgbe_fc_default)
4072 : 0 : hw->fc.requested_mode = ixgbe_fc_full;
4073 : :
4074 : : /* Set up the 1G and 10G flow control advertisement registers so the
4075 : : * HW will be able to do FC autoneg once the cable is plugged in. If
4076 : : * we link at 10G, the 1G advertisement is harmless and vice versa.
4077 : : */
4078 : 0 : status = hw->mac.ops.read_iosf_sb_reg(hw,
4079 [ # # ]: 0 : IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
4080 : : IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl);
4081 : :
4082 [ # # ]: 0 : if (status != IXGBE_SUCCESS) {
4083 : 0 : DEBUGOUT("Auto-Negotiation did not complete\n");
4084 : 0 : return status;
4085 : : }
4086 : :
4087 : : /* The possible values of fc.requested_mode are:
4088 : : * 0: Flow control is completely disabled
4089 : : * 1: Rx flow control is enabled (we can receive pause frames,
4090 : : * but not send pause frames).
4091 : : * 2: Tx flow control is enabled (we can send pause frames but
4092 : : * we do not support receiving pause frames).
4093 : : * 3: Both Rx and Tx flow control (symmetric) are enabled.
4094 : : * other: Invalid.
4095 : : */
4096 [ # # # # ]: 0 : switch (hw->fc.requested_mode) {
4097 : 0 : case ixgbe_fc_none:
4098 : : /* Flow control completely disabled by software override. */
4099 : 0 : an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
4100 : : IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
4101 : 0 : break;
4102 : 0 : case ixgbe_fc_tx_pause:
4103 : : /* Tx Flow control is enabled, and Rx Flow control is
4104 : : * disabled by software override.
4105 : : */
4106 : 0 : an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
4107 : 0 : an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
4108 : 0 : break;
4109 : 0 : case ixgbe_fc_rx_pause:
4110 : : /* Rx Flow control is enabled and Tx Flow control is
4111 : : * disabled by software override. Since there really
4112 : : * isn't a way to advertise that we are capable of RX
4113 : : * Pause ONLY, we will advertise that we support both
4114 : : * symmetric and asymmetric Rx PAUSE, as such we fall
4115 : : * through to the fc_full statement. Later, we will
4116 : : * disable the adapter's ability to send PAUSE frames.
4117 : : */
4118 : : case ixgbe_fc_full:
4119 : : /* Flow control (both Rx and Tx) is enabled by SW override. */
4120 : 0 : an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
4121 : : IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
4122 : 0 : break;
4123 : 0 : default:
4124 : 0 : ERROR_REPORT1(IXGBE_ERROR_ARGUMENT,
4125 : : "Flow control param set incorrectly\n");
4126 : 0 : return IXGBE_ERR_CONFIG;
4127 : : }
4128 : :
4129 : 0 : status = hw->mac.ops.write_iosf_sb_reg(hw,
4130 [ # # ]: 0 : IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
4131 : : IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl);
4132 : :
4133 : : /* Restart auto-negotiation. */
4134 : 0 : status = ixgbe_restart_an_internal_phy_x550em(hw);
4135 : :
4136 : 0 : return status;
4137 : : }
4138 : :
4139 : : /**
4140 : : * ixgbe_set_mux - Set mux for port 1 access with CS4227
4141 : : * @hw: pointer to hardware structure
4142 : : * @state: set mux if 1, clear if 0
4143 : : */
4144 : : STATIC void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state)
4145 : : {
4146 : : u32 esdp;
4147 : :
4148 [ # # # # ]: 0 : if (!hw->bus.lan_id)
4149 : : return;
4150 : 0 : esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
4151 : : if (state)
4152 : 0 : esdp |= IXGBE_ESDP_SDP1;
4153 : : else
4154 : 0 : esdp &= ~IXGBE_ESDP_SDP1;
4155 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
4156 : 0 : IXGBE_WRITE_FLUSH(hw);
4157 : : }
4158 : :
4159 : : /**
4160 : : * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore
4161 : : * @hw: pointer to hardware structure
4162 : : * @mask: Mask to specify which semaphore to acquire
4163 : : *
4164 : : * Acquires the SWFW semaphore and sets the I2C MUX
4165 : : **/
4166 : 0 : s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
4167 : : {
4168 : : s32 status;
4169 : :
4170 : 0 : DEBUGFUNC("ixgbe_acquire_swfw_sync_X550em");
4171 : :
4172 : 0 : status = ixgbe_acquire_swfw_sync_X540(hw, mask);
4173 [ # # ]: 0 : if (status)
4174 : : return status;
4175 : :
4176 [ # # ]: 0 : if (mask & IXGBE_GSSR_I2C_MASK)
4177 : : ixgbe_set_mux(hw, 1);
4178 : :
4179 : : return IXGBE_SUCCESS;
4180 : : }
4181 : :
4182 : : /**
4183 : : * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore
4184 : : * @hw: pointer to hardware structure
4185 : : * @mask: Mask to specify which semaphore to release
4186 : : *
4187 : : * Releases the SWFW semaphore and sets the I2C MUX
4188 : : **/
4189 : 0 : void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
4190 : : {
4191 : 0 : DEBUGFUNC("ixgbe_release_swfw_sync_X550em");
4192 : :
4193 [ # # ]: 0 : if (mask & IXGBE_GSSR_I2C_MASK)
4194 : : ixgbe_set_mux(hw, 0);
4195 : :
4196 : 0 : ixgbe_release_swfw_sync_X540(hw, mask);
4197 : 0 : }
4198 : :
4199 : : /**
4200 : : * ixgbe_acquire_swfw_sync_X550a - Acquire SWFW semaphore
4201 : : * @hw: pointer to hardware structure
4202 : : * @mask: Mask to specify which semaphore to acquire
4203 : : *
4204 : : * Acquires the SWFW semaphore and get the shared phy token as needed
4205 : : */
4206 : 0 : STATIC s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *hw, u32 mask)
4207 : : {
4208 : 0 : u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
4209 : : int retries = FW_PHY_TOKEN_RETRIES;
4210 : : s32 status = IXGBE_SUCCESS;
4211 : :
4212 : 0 : DEBUGFUNC("ixgbe_acquire_swfw_sync_X550a");
4213 : :
4214 : : status = IXGBE_SUCCESS;
4215 [ # # ]: 0 : if (hmask)
4216 : 0 : status = ixgbe_acquire_swfw_sync_X540(hw, hmask);
4217 : :
4218 [ # # ]: 0 : if (status) {
4219 : 0 : DEBUGOUT1("Could not acquire SWFW semaphore, Status = %d\n", status);
4220 : 0 : return status;
4221 : : }
4222 : :
4223 [ # # ]: 0 : if (!(mask & IXGBE_GSSR_TOKEN_SM))
4224 : : return IXGBE_SUCCESS;
4225 : :
4226 [ # # ]: 0 : while (--retries) {
4227 : 0 : status = ixgbe_get_phy_token(hw);
4228 : :
4229 [ # # ]: 0 : if (status == IXGBE_SUCCESS)
4230 : : return IXGBE_SUCCESS;
4231 : :
4232 [ # # ]: 0 : if (status != IXGBE_ERR_TOKEN_RETRY) {
4233 : 0 : DEBUGOUT1("Retry acquiring the PHY token failed, Status = %d\n", status);
4234 [ # # ]: 0 : if (hmask)
4235 : 0 : ixgbe_release_swfw_sync_X540(hw, hmask);
4236 : 0 : return status;
4237 : : }
4238 : :
4239 : : if (status == IXGBE_ERR_TOKEN_RETRY)
4240 : 0 : DEBUGOUT1("Could not acquire PHY token, Status = %d\n",
4241 : : status);
4242 : : }
4243 : :
4244 [ # # ]: 0 : if (hmask)
4245 : 0 : ixgbe_release_swfw_sync_X540(hw, hmask);
4246 : :
4247 : 0 : DEBUGOUT1("Semaphore acquisition retries failed!: PHY ID = 0x%08X\n",
4248 : : hw->phy.id);
4249 : 0 : return status;
4250 : : }
4251 : :
4252 : : /**
4253 : : * ixgbe_release_swfw_sync_X550a - Release SWFW semaphore
4254 : : * @hw: pointer to hardware structure
4255 : : * @mask: Mask to specify which semaphore to release
4256 : : *
4257 : : * Releases the SWFW semaphore and puts the shared phy token as needed
4258 : : */
4259 : 0 : STATIC void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *hw, u32 mask)
4260 : : {
4261 : 0 : u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
4262 : :
4263 : 0 : DEBUGFUNC("ixgbe_release_swfw_sync_X550a");
4264 : :
4265 [ # # ]: 0 : if (mask & IXGBE_GSSR_TOKEN_SM)
4266 : 0 : ixgbe_put_phy_token(hw);
4267 : :
4268 [ # # ]: 0 : if (hmask)
4269 : 0 : ixgbe_release_swfw_sync_X540(hw, hmask);
4270 : 0 : }
4271 : :
4272 : : /**
4273 : : * ixgbe_read_phy_reg_x550a - Reads specified PHY register
4274 : : * @hw: pointer to hardware structure
4275 : : * @reg_addr: 32 bit address of PHY register to read
4276 : : * @device_type: 5 bit device type
4277 : : * @phy_data: Pointer to read data from PHY register
4278 : : *
4279 : : * Reads a value from a specified PHY register using the SWFW lock and PHY
4280 : : * Token. The PHY Token is needed since the MDIO is shared between to MAC
4281 : : * instances.
4282 : : **/
4283 : 0 : s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
4284 : : u32 device_type, u16 *phy_data)
4285 : : {
4286 : : s32 status;
4287 : 0 : u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
4288 : :
4289 : 0 : DEBUGFUNC("ixgbe_read_phy_reg_x550a");
4290 : :
4291 [ # # ]: 0 : if (hw->mac.ops.acquire_swfw_sync(hw, mask))
4292 : : return IXGBE_ERR_SWFW_SYNC;
4293 : :
4294 : 0 : status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data);
4295 : :
4296 : 0 : hw->mac.ops.release_swfw_sync(hw, mask);
4297 : :
4298 : 0 : return status;
4299 : : }
4300 : :
4301 : : /**
4302 : : * ixgbe_write_phy_reg_x550a - Writes specified PHY register
4303 : : * @hw: pointer to hardware structure
4304 : : * @reg_addr: 32 bit PHY register to write
4305 : : * @device_type: 5 bit device type
4306 : : * @phy_data: Data to write to the PHY register
4307 : : *
4308 : : * Writes a value to specified PHY register using the SWFW lock and PHY Token.
4309 : : * The PHY Token is needed since the MDIO is shared between to MAC instances.
4310 : : **/
4311 : 0 : s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
4312 : : u32 device_type, u16 phy_data)
4313 : : {
4314 : : s32 status;
4315 : 0 : u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
4316 : :
4317 : 0 : DEBUGFUNC("ixgbe_write_phy_reg_x550a");
4318 : :
4319 [ # # ]: 0 : if (hw->mac.ops.acquire_swfw_sync(hw, mask) == IXGBE_SUCCESS) {
4320 : 0 : status = hw->phy.ops.write_reg_mdi(hw, reg_addr, device_type,
4321 : : phy_data);
4322 : 0 : hw->mac.ops.release_swfw_sync(hw, mask);
4323 : : } else {
4324 : : status = IXGBE_ERR_SWFW_SYNC;
4325 : : }
4326 : :
4327 : 0 : return status;
4328 : : }
4329 : :
4330 : : /**
4331 : : * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
4332 : : * @hw: pointer to hardware structure
4333 : : *
4334 : : * Handle external Base T PHY interrupt. If high temperature
4335 : : * failure alarm then return error, else if link status change
4336 : : * then setup internal/external PHY link
4337 : : *
4338 : : * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
4339 : : * failure alarm, else return PHY access status.
4340 : : */
4341 : 0 : s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
4342 : : {
4343 : : bool lsc;
4344 : : u32 status;
4345 : :
4346 : 0 : status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
4347 : :
4348 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
4349 : : return status;
4350 : :
4351 [ # # ]: 0 : if (lsc)
4352 : 0 : return ixgbe_setup_internal_phy(hw);
4353 : :
4354 : : return IXGBE_SUCCESS;
4355 : : }
4356 : :
4357 : : /**
4358 : : * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
4359 : : * @hw: pointer to hardware structure
4360 : : * @speed: new link speed
4361 : : * @autoneg_wait_to_complete: true when waiting for completion is needed
4362 : : *
4363 : : * Setup internal/external PHY link speed based on link speed, then set
4364 : : * external PHY auto advertised link speed.
4365 : : *
4366 : : * Returns error status for any failure
4367 : : **/
4368 : 0 : s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
4369 : : ixgbe_link_speed speed,
4370 : : bool autoneg_wait_to_complete)
4371 : : {
4372 : : s32 status;
4373 : : ixgbe_link_speed force_speed;
4374 : : u32 i;
4375 : 0 : bool link_up = false;
4376 : :
4377 : 0 : DEBUGFUNC("ixgbe_setup_mac_link_t_X550em");
4378 : :
4379 : : /* Setup internal/external PHY link speed to iXFI (10G), unless
4380 : : * only 1G is auto advertised then setup KX link.
4381 : : */
4382 [ # # ]: 0 : if (speed & IXGBE_LINK_SPEED_10GB_FULL)
4383 : 0 : force_speed = IXGBE_LINK_SPEED_10GB_FULL;
4384 : : else
4385 : 0 : force_speed = IXGBE_LINK_SPEED_1GB_FULL;
4386 : :
4387 : : /* If X552 and internal link mode is XFI, then setup XFI internal link.
4388 : : */
4389 [ # # ]: 0 : if (hw->mac.type == ixgbe_mac_X550EM_x &&
4390 [ # # ]: 0 : !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
4391 : 0 : status = ixgbe_setup_ixfi_x550em(hw, &force_speed);
4392 : :
4393 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
4394 : : return status;
4395 : :
4396 : : /* Wait for the controller to acquire link */
4397 [ # # ]: 0 : for (i = 0; i < 10; i++) {
4398 : 0 : msec_delay(100);
4399 : :
4400 : 0 : status = ixgbe_check_link(hw, &force_speed, &link_up,
4401 : : false);
4402 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
4403 : 0 : return status;
4404 : :
4405 [ # # ]: 0 : if (link_up)
4406 : : break;
4407 : : }
4408 : : }
4409 : :
4410 : 0 : return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete);
4411 : : }
4412 : :
4413 : : /**
4414 : : * ixgbe_check_link_t_X550em - Determine link and speed status
4415 : : * @hw: pointer to hardware structure
4416 : : * @speed: pointer to link speed
4417 : : * @link_up: true when link is up
4418 : : * @link_up_wait_to_complete: bool used to wait for link up or not
4419 : : *
4420 : : * Check that both the MAC and X557 external PHY have link.
4421 : : **/
4422 : 0 : s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
4423 : : bool *link_up, bool link_up_wait_to_complete)
4424 : : {
4425 : : u32 status;
4426 : 0 : u16 i, autoneg_status = 0;
4427 : :
4428 [ # # ]: 0 : if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
4429 : : return IXGBE_ERR_CONFIG;
4430 : :
4431 : 0 : status = ixgbe_check_mac_link_generic(hw, speed, link_up,
4432 : : link_up_wait_to_complete);
4433 : :
4434 : : /* If check link fails or MAC link is not up, then return */
4435 [ # # # # ]: 0 : if (status != IXGBE_SUCCESS || !(*link_up))
4436 : : return status;
4437 : :
4438 : : /* MAC link is up, so check external PHY link.
4439 : : * X557 PHY. Link status is latching low, and can only be used to detect
4440 : : * link drop, and not the current status of the link without performing
4441 : : * back-to-back reads.
4442 : : */
4443 [ # # ]: 0 : for (i = 0; i < 2; i++) {
4444 : 0 : status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
4445 : : IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
4446 : : &autoneg_status);
4447 : :
4448 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
4449 : 0 : return status;
4450 : : }
4451 : :
4452 : : /* If external PHY link is not up, then indicate link not up */
4453 [ # # ]: 0 : if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
4454 : 0 : *link_up = false;
4455 : :
4456 : : return IXGBE_SUCCESS;
4457 : : }
4458 : :
4459 : : /**
4460 : : * ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI
4461 : : * @hw: pointer to hardware structure
4462 : : **/
4463 : 0 : s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw)
4464 : : {
4465 : : s32 status;
4466 : :
4467 : 0 : status = ixgbe_reset_phy_generic(hw);
4468 : :
4469 [ # # ]: 0 : if (status != IXGBE_SUCCESS)
4470 : : return status;
4471 : :
4472 : : /* Configure Link Status Alarm and Temperature Threshold interrupts */
4473 : 0 : return ixgbe_enable_lasi_ext_t_x550em(hw);
4474 : : }
4475 : :
4476 : : /**
4477 : : * ixgbe_led_on_t_X550em - Turns on the software controllable LEDs.
4478 : : * @hw: pointer to hardware structure
4479 : : * @led_idx: led number to turn on
4480 : : **/
4481 : 0 : s32 ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, u32 led_idx)
4482 : : {
4483 : : u16 phy_data;
4484 : :
4485 : 0 : DEBUGFUNC("ixgbe_led_on_t_X550em");
4486 : :
4487 [ # # ]: 0 : if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
4488 : : return IXGBE_ERR_PARAM;
4489 : :
4490 : : /* To turn on the LED, set mode to ON. */
4491 : 0 : ixgbe_read_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
4492 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
4493 : 0 : phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;
4494 : 0 : ixgbe_write_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
4495 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
4496 : :
4497 : : /* Some designs have the LEDs wired to the MAC */
4498 : 0 : return ixgbe_led_on_generic(hw, led_idx);
4499 : : }
4500 : :
4501 : : /**
4502 : : * ixgbe_led_off_t_X550em - Turns off the software controllable LEDs.
4503 : : * @hw: pointer to hardware structure
4504 : : * @led_idx: led number to turn off
4505 : : **/
4506 : 0 : s32 ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, u32 led_idx)
4507 : : {
4508 : : u16 phy_data;
4509 : :
4510 : 0 : DEBUGFUNC("ixgbe_led_off_t_X550em");
4511 : :
4512 [ # # ]: 0 : if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
4513 : : return IXGBE_ERR_PARAM;
4514 : :
4515 : : /* To turn on the LED, set mode to ON. */
4516 : 0 : ixgbe_read_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
4517 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
4518 : 0 : phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;
4519 : 0 : ixgbe_write_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
4520 : : IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
4521 : :
4522 : : /* Some designs have the LEDs wired to the MAC */
4523 : 0 : return ixgbe_led_off_generic(hw, led_idx);
4524 : : }
4525 : :
4526 : : /**
4527 : : * ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware
4528 : : * @hw: pointer to the HW structure
4529 : : * @maj: driver version major number
4530 : : * @min: driver version minor number
4531 : : * @build: driver version build number
4532 : : * @sub: driver version sub build number
4533 : : * @len: length of driver_ver string
4534 : : * @driver_ver: driver string
4535 : : *
4536 : : * Sends driver version number to firmware through the manageability
4537 : : * block. On success return IXGBE_SUCCESS
4538 : : * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
4539 : : * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
4540 : : **/
4541 : 0 : s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
4542 : : u8 build, u8 sub, u16 len, const char *driver_ver)
4543 : : {
4544 : : struct ixgbe_hic_drv_info2 fw_cmd;
4545 : : s32 ret_val = IXGBE_SUCCESS;
4546 : : int i;
4547 : :
4548 : 0 : DEBUGFUNC("ixgbe_set_fw_drv_ver_x550");
4549 : :
4550 [ # # # # ]: 0 : if ((len == 0) || (driver_ver == NULL) ||
4551 : : (len > sizeof(fw_cmd.driver_string)))
4552 : : return IXGBE_ERR_INVALID_ARGUMENT;
4553 : :
4554 : 0 : fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
4555 : 0 : fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len;
4556 : 0 : fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
4557 : 0 : fw_cmd.port_num = (u8)hw->bus.func;
4558 : 0 : fw_cmd.ver_maj = maj;
4559 : 0 : fw_cmd.ver_min = min;
4560 : 0 : fw_cmd.ver_build = build;
4561 : 0 : fw_cmd.ver_sub = sub;
4562 : 0 : fw_cmd.hdr.checksum = 0;
4563 : 0 : memcpy(fw_cmd.driver_string, driver_ver, len);
4564 : 0 : fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
4565 : 0 : (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
4566 : :
4567 [ # # ]: 0 : for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
4568 : 0 : ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
4569 : : sizeof(fw_cmd),
4570 : : IXGBE_HI_COMMAND_TIMEOUT,
4571 : : true);
4572 [ # # ]: 0 : if (ret_val != IXGBE_SUCCESS)
4573 : : continue;
4574 : :
4575 [ # # ]: 0 : if (fw_cmd.hdr.cmd_or_resp.ret_status ==
4576 : : FW_CEM_RESP_STATUS_SUCCESS)
4577 : : ret_val = IXGBE_SUCCESS;
4578 : : else
4579 : : ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
4580 : :
4581 : : break;
4582 : : }
4583 : :
4584 : : return ret_val;
4585 : : }
4586 : :
4587 : : /**
4588 : : * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode
4589 : : * @hw: pointer t hardware structure
4590 : : *
4591 : : * Returns true if in FW NVM recovery mode.
4592 : : **/
4593 : 0 : bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw)
4594 : : {
4595 : : u32 fwsm;
4596 : :
4597 : 0 : fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
4598 : :
4599 : 0 : return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE);
4600 : : }
|