]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/dpdk/drivers/net/ixgbe/ixgbe_82599_bypass.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / dpdk / drivers / net / ixgbe / ixgbe_82599_bypass.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2015 Intel Corporation
3 */
4
5 #include "base/ixgbe_type.h"
6 #include "base/ixgbe_82599.h"
7 #include "base/ixgbe_api.h"
8 #include "base/ixgbe_common.h"
9 #include "base/ixgbe_phy.h"
10 #include "ixgbe_bypass_defines.h"
11 #include "ixgbe_bypass.h"
12
13 /**
14 * ixgbe_set_fiber_fixed_speed - Set module link speed for fixed fiber
15 * @hw: pointer to hardware structure
16 * @speed: link speed to set
17 *
18 * We set the module speed differently for fixed fiber. For other
19 * multi-speed devices we don't have an error value so here if we
20 * detect an error we just log it and exit.
21 */
22 static void
23 ixgbe_set_fiber_fixed_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed)
24 {
25 s32 status;
26 u8 rs, eeprom_data;
27
28 switch (speed) {
29 case IXGBE_LINK_SPEED_10GB_FULL:
30 /* one bit mask same as setting on */
31 rs = IXGBE_SFF_SOFT_RS_SELECT_10G;
32 break;
33 case IXGBE_LINK_SPEED_1GB_FULL:
34 rs = IXGBE_SFF_SOFT_RS_SELECT_1G;
35 break;
36 default:
37 PMD_DRV_LOG(ERR, "Invalid fixed module speed");
38 return;
39 }
40
41 /* Set RS0 */
42 status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
43 IXGBE_I2C_EEPROM_DEV_ADDR2,
44 &eeprom_data);
45 if (status) {
46 PMD_DRV_LOG(ERR, "Failed to read Rx Rate Select RS0");
47 goto out;
48 }
49
50 eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs;
51
52 status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
53 IXGBE_I2C_EEPROM_DEV_ADDR2,
54 eeprom_data);
55 if (status) {
56 PMD_DRV_LOG(ERR, "Failed to write Rx Rate Select RS0");
57 goto out;
58 }
59
60 /* Set RS1 */
61 status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
62 IXGBE_I2C_EEPROM_DEV_ADDR2,
63 &eeprom_data);
64 if (status) {
65 PMD_DRV_LOG(ERR, "Failed to read Rx Rate Select RS1");
66 goto out;
67 }
68
69 eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs;
70
71 status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
72 IXGBE_I2C_EEPROM_DEV_ADDR2,
73 eeprom_data);
74 if (status) {
75 PMD_DRV_LOG(ERR, "Failed to write Rx Rate Select RS1");
76 goto out;
77 }
78 out:
79 return;
80 }
81
82 /**
83 * ixgbe_setup_mac_link_multispeed_fixed_fiber - Set MAC link speed
84 * @hw: pointer to hardware structure
85 * @speed: new link speed
86 * @autoneg_wait_to_complete: true when waiting for completion is needed
87 *
88 * Set the link speed in the AUTOC register and restarts link.
89 **/
90 static s32
91 ixgbe_setup_mac_link_multispeed_fixed_fiber(struct ixgbe_hw *hw,
92 ixgbe_link_speed speed,
93 bool autoneg_wait_to_complete)
94 {
95 s32 status = IXGBE_SUCCESS;
96 ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
97 ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
98 u32 speedcnt = 0;
99 u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
100 u32 i = 0;
101 bool link_up = false;
102 bool negotiation;
103
104 PMD_INIT_FUNC_TRACE();
105
106 /* Mask off requested but non-supported speeds */
107 status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation);
108 if (status != IXGBE_SUCCESS)
109 return status;
110
111 speed &= link_speed;
112
113 /*
114 * Try each speed one by one, highest priority first. We do this in
115 * software because 10gb fiber doesn't support speed autonegotiation.
116 */
117 if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
118 speedcnt++;
119 highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
120
121 /* If we already have link at this speed, just jump out */
122 status = ixgbe_check_link(hw, &link_speed, &link_up, false);
123 if (status != IXGBE_SUCCESS)
124 return status;
125
126 if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
127 goto out;
128 /* Set the module link speed */
129 ixgbe_set_fiber_fixed_speed(hw, IXGBE_LINK_SPEED_10GB_FULL);
130
131 /* Set the module link speed */
132 esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
133 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
134 IXGBE_WRITE_FLUSH(hw);
135
136 /* Allow module to change analog characteristics (1G->10G) */
137 msec_delay(40);
138
139 status = ixgbe_setup_mac_link_82599(hw,
140 IXGBE_LINK_SPEED_10GB_FULL,
141 autoneg_wait_to_complete);
142 if (status != IXGBE_SUCCESS)
143 return status;
144
145 /* Flap the tx laser if it has not already been done */
146 ixgbe_flap_tx_laser(hw);
147
148 /*
149 * Wait for the controller to acquire link. Per IEEE 802.3ap,
150 * Section 73.10.2, we may have to wait up to 500ms if KR is
151 * attempted. 82599 uses the same timing for 10g SFI.
152 */
153 for (i = 0; i < 5; i++) {
154 /* Wait for the link partner to also set speed */
155 msec_delay(100);
156
157 /* If we have link, just jump out */
158 status = ixgbe_check_link(hw, &link_speed,
159 &link_up, false);
160 if (status != IXGBE_SUCCESS)
161 return status;
162
163 if (link_up)
164 goto out;
165 }
166 }
167
168 if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
169 speedcnt++;
170 if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
171 highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
172
173 /* If we already have link at this speed, just jump out */
174 status = ixgbe_check_link(hw, &link_speed, &link_up, false);
175 if (status != IXGBE_SUCCESS)
176 return status;
177
178 if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
179 goto out;
180
181 /* Set the module link speed */
182 ixgbe_set_fiber_fixed_speed(hw, IXGBE_LINK_SPEED_1GB_FULL);
183
184 /* Allow module to change analog characteristics (10G->1G) */
185 msec_delay(40);
186
187 status = ixgbe_setup_mac_link_82599(hw,
188 IXGBE_LINK_SPEED_1GB_FULL,
189 autoneg_wait_to_complete);
190 if (status != IXGBE_SUCCESS)
191 return status;
192
193 /* Flap the tx laser if it has not already been done */
194 ixgbe_flap_tx_laser(hw);
195
196 /* Wait for the link partner to also set speed */
197 msec_delay(100);
198
199 /* If we have link, just jump out */
200 status = ixgbe_check_link(hw, &link_speed, &link_up, false);
201 if (status != IXGBE_SUCCESS)
202 return status;
203
204 if (link_up)
205 goto out;
206 }
207
208 /*
209 * We didn't get link. Configure back to the highest speed we tried,
210 * (if there was more than one). We call ourselves back with just the
211 * single highest speed that the user requested.
212 */
213 if (speedcnt > 1)
214 status = ixgbe_setup_mac_link_multispeed_fixed_fiber(hw,
215 highest_link_speed, autoneg_wait_to_complete);
216
217 out:
218 /* Set autoneg_advertised value based on input link speed */
219 hw->phy.autoneg_advertised = 0;
220
221 if (speed & IXGBE_LINK_SPEED_10GB_FULL)
222 hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
223
224 if (speed & IXGBE_LINK_SPEED_1GB_FULL)
225 hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
226
227 return status;
228 }
229
230 static enum ixgbe_media_type
231 ixgbe_bypass_get_media_type(struct ixgbe_hw *hw)
232 {
233 enum ixgbe_media_type media_type;
234
235 PMD_INIT_FUNC_TRACE();
236
237 if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
238 media_type = ixgbe_media_type_fiber;
239 } else {
240 media_type = ixgbe_get_media_type_82599(hw);
241 }
242 return media_type;
243 }
244
245 /*
246 * Wrapper around shared code (base driver) to support BYPASS nic.
247 */
248 s32
249 ixgbe_bypass_init_shared_code(struct ixgbe_hw *hw)
250 {
251 s32 ret_val;
252
253 if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
254 hw->mac.type = ixgbe_mac_82599EB;
255 }
256
257 ret_val = ixgbe_init_shared_code(hw);
258 if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
259 hw->mac.ops.get_media_type = &ixgbe_bypass_get_media_type;
260 ixgbe_init_mac_link_ops_82599(hw);
261 }
262
263 return ret_val;
264 }
265
266 s32
267 ixgbe_bypass_init_hw(struct ixgbe_hw *hw)
268 {
269 int rc;
270
271 rc = ixgbe_init_hw(hw);
272 if (rc == 0 && hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
273
274 hw->mac.ops.setup_link =
275 &ixgbe_setup_mac_link_multispeed_fixed_fiber;
276
277 hw->mac.ops.get_media_type = &ixgbe_bypass_get_media_type;
278
279 hw->mac.ops.disable_tx_laser = NULL;
280 hw->mac.ops.enable_tx_laser = NULL;
281 hw->mac.ops.flap_tx_laser = NULL;
282 }
283
284 return rc;
285 }