1
2
3
4
5#include <time.h>
6#include <rte_atomic.h>
7#include <rte_ethdev_driver.h>
8#include "ixgbe_ethdev.h"
9#include "ixgbe_bypass_api.h"
10#include "rte_pmd_ixgbe.h"
11
12#define BYPASS_STATUS_OFF_MASK 3
13
14
15#define FUNC_PTR_OR_ERR_RET(func, retval) do { \
16 if ((func) == NULL) { \
17 PMD_DRV_LOG(ERR, "%s:%d function not supported", \
18 __func__, __LINE__); \
19 return retval; \
20 } \
21} while (0)
22
23#define FUNC_PTR_OR_RET(func) do { \
24 if ((func) == NULL) { \
25 PMD_DRV_LOG(ERR, "%s:%d function not supported", \
26 __func__, __LINE__); \
27 return; \
28 } \
29} while (0)
30
31
32
33
34
35
36
37
38
39
40static void
41ixgbe_bypass_set_time(struct ixgbe_adapter *adapter)
42{
43 u32 mask, value;
44 u32 sec;
45 struct ixgbe_hw *hw = &adapter->hw;
46
47 sec = 0;
48
49
50
51
52
53 mask = BYPASS_CTL1_TIME_M |
54 BYPASS_CTL1_VALID_M |
55 BYPASS_CTL1_OFFTRST_M;
56 value = (sec & BYPASS_CTL1_TIME_M) |
57 BYPASS_CTL1_VALID |
58 BYPASS_CTL1_OFFTRST;
59
60 FUNC_PTR_OR_RET(adapter->bps.ops.bypass_set);
61
62
63 adapter->bps.reset_tm = time(NULL);
64
65
66 adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL1, mask, value);
67}
68
69
70
71
72
73
74
75
76
77void
78ixgbe_bypass_init(struct rte_eth_dev *dev)
79{
80 struct ixgbe_adapter *adapter;
81 struct ixgbe_hw *hw;
82
83 adapter = IXGBE_DEV_TO_ADPATER(dev);
84 hw = &adapter->hw;
85
86
87 if (hw->device_id != IXGBE_DEV_ID_82599_BYPASS ||
88 hw->bus.func != 0) {
89 PMD_DRV_LOG(ERR, "bypass function is not supported on that device");
90 return;
91 }
92
93
94 adapter->bps.ops.bypass_rw = &ixgbe_bypass_rw_generic;
95 adapter->bps.ops.bypass_valid_rd = &ixgbe_bypass_valid_rd_generic;
96 adapter->bps.ops.bypass_set = &ixgbe_bypass_set_generic;
97 adapter->bps.ops.bypass_rd_eep = &ixgbe_bypass_rd_eep_generic;
98
99
100 ixgbe_bypass_set_time(adapter);
101
102
103 hw->mac.ops.disable_tx_laser = NULL;
104 hw->mac.ops.enable_tx_laser = NULL;
105 hw->mac.ops.flap_tx_laser = NULL;
106}
107
108s32
109ixgbe_bypass_state_show(struct rte_eth_dev *dev, u32 *state)
110{
111 struct ixgbe_hw *hw;
112 s32 ret_val;
113 u32 cmd;
114 u32 by_ctl = 0;
115 struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
116
117 hw = &adapter->hw;
118 FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP);
119
120 cmd = BYPASS_PAGE_CTL0;
121 ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &by_ctl);
122
123
124
125
126 *state = (by_ctl >> BYPASS_STATUS_OFF_SHIFT) & BYPASS_STATUS_OFF_MASK;
127
128 return ret_val;
129}
130
131
132s32
133ixgbe_bypass_state_store(struct rte_eth_dev *dev, u32 *new_state)
134{
135 struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
136 struct ixgbe_hw *hw;
137 s32 ret_val;
138
139 hw = &adapter->hw;
140 FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_set, -ENOTSUP);
141
142
143 ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
144 BYPASS_MODE_OFF_M, *new_state);
145 if (ret_val)
146 goto exit;
147
148
149 ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
150 BYPASS_MODE_OFF_M, BYPASS_AUTO);
151
152exit:
153 return ret_val;
154
155}
156
157s32
158ixgbe_bypass_event_show(struct rte_eth_dev *dev, u32 event,
159 u32 *state)
160{
161 struct ixgbe_hw *hw;
162 s32 ret_val;
163 u32 shift;
164 u32 cmd;
165 u32 by_ctl = 0;
166 struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
167
168 hw = &adapter->hw;
169 FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP);
170
171 cmd = BYPASS_PAGE_CTL0;
172 ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &by_ctl);
173
174
175
176
177 switch (event) {
178 case BYPASS_EVENT_WDT_TO:
179 shift = BYPASS_WDTIMEOUT_SHIFT;
180 break;
181 case BYPASS_EVENT_MAIN_ON:
182 shift = BYPASS_MAIN_ON_SHIFT;
183 break;
184 case BYPASS_EVENT_MAIN_OFF:
185 shift = BYPASS_MAIN_OFF_SHIFT;
186 break;
187 case BYPASS_EVENT_AUX_ON:
188 shift = BYPASS_AUX_ON_SHIFT;
189 break;
190 case BYPASS_EVENT_AUX_OFF:
191 shift = BYPASS_AUX_OFF_SHIFT;
192 break;
193 default:
194 return EINVAL;
195 }
196
197 *state = (by_ctl >> shift) & 0x3;
198
199 return ret_val;
200}
201
202s32
203ixgbe_bypass_event_store(struct rte_eth_dev *dev, u32 event,
204 u32 state)
205{
206 struct ixgbe_hw *hw;
207 u32 status;
208 u32 off;
209 s32 ret_val;
210 struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
211
212 hw = &adapter->hw;
213 FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_set, -ENOTSUP);
214
215 switch (event) {
216 case BYPASS_EVENT_WDT_TO:
217 off = BYPASS_WDTIMEOUT_M;
218 status = state << BYPASS_WDTIMEOUT_SHIFT;
219 break;
220 case BYPASS_EVENT_MAIN_ON:
221 off = BYPASS_MAIN_ON_M;
222 status = state << BYPASS_MAIN_ON_SHIFT;
223 break;
224 case BYPASS_EVENT_MAIN_OFF:
225 off = BYPASS_MAIN_OFF_M;
226 status = state << BYPASS_MAIN_OFF_SHIFT;
227 break;
228 case BYPASS_EVENT_AUX_ON:
229 off = BYPASS_AUX_ON_M;
230 status = state << BYPASS_AUX_ON_SHIFT;
231 break;
232 case BYPASS_EVENT_AUX_OFF:
233 off = BYPASS_AUX_OFF_M;
234 status = state << BYPASS_AUX_OFF_SHIFT;
235 break;
236 default:
237 return EINVAL;
238 }
239
240 ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
241 off, status);
242
243 return ret_val;
244}
245
246s32
247ixgbe_bypass_wd_timeout_store(struct rte_eth_dev *dev, u32 timeout)
248{
249 struct ixgbe_hw *hw;
250 u32 status;
251 u32 mask;
252 s32 ret_val;
253 struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
254
255 hw = &adapter->hw;
256 FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_set, -ENOTSUP);
257
258
259 if (timeout == RTE_PMD_IXGBE_BYPASS_TMT_OFF) {
260 status = 0x0;
261 mask = BYPASS_WDT_ENABLE_M;
262 } else {
263
264 mask = BYPASS_WDT_VALUE_M;
265
266
267 status = timeout << BYPASS_WDT_TIME_SHIFT;
268 status |= 0x1 << BYPASS_WDT_ENABLE_SHIFT;
269 mask |= BYPASS_WDT_ENABLE_M;
270 }
271
272 ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
273 mask, status);
274
275 return ret_val;
276}
277
278s32
279ixgbe_bypass_ver_show(struct rte_eth_dev *dev, u32 *ver)
280{
281 struct ixgbe_hw *hw;
282 u32 cmd;
283 u32 status;
284 s32 ret_val;
285 struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
286
287 hw = &adapter->hw;
288 FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP);
289
290 cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
291 cmd |= (BYPASS_EEPROM_VER_ADD << BYPASS_CTL2_OFFSET_SHIFT) &
292 BYPASS_CTL2_OFFSET_M;
293 ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &status);
294 if (ret_val)
295 goto exit;
296
297
298 msleep(100);
299
300
301 cmd &= ~BYPASS_WE;
302 ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &status);
303 if (ret_val)
304 goto exit;
305
306 *ver = status & BYPASS_CTL2_DATA_M;
307
308exit:
309 return ret_val;
310}
311
312s32
313ixgbe_bypass_wd_timeout_show(struct rte_eth_dev *dev, u32 *wd_timeout)
314{
315 struct ixgbe_hw *hw;
316 u32 by_ctl = 0;
317 u32 cmd;
318 u32 wdg;
319 s32 ret_val;
320 struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
321
322 hw = &adapter->hw;
323 FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP);
324
325 cmd = BYPASS_PAGE_CTL0;
326 ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &by_ctl);
327
328 wdg = by_ctl & BYPASS_WDT_ENABLE_M;
329 if (!wdg)
330 *wd_timeout = RTE_PMD_IXGBE_BYPASS_TMT_OFF;
331 else
332 *wd_timeout = (by_ctl >> BYPASS_WDT_TIME_SHIFT) &
333 BYPASS_WDT_MASK;
334
335 return ret_val;
336}
337
338s32
339ixgbe_bypass_wd_reset(struct rte_eth_dev *dev)
340{
341 u32 cmd;
342 u32 status;
343 u32 sec;
344 u32 count = 0;
345 s32 ret_val;
346 struct ixgbe_hw *hw;
347 struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
348
349 hw = &adapter->hw;
350
351 FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP);
352 FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_valid_rd, -ENOTSUP);
353
354
355
356
357
358
359 cmd = BYPASS_PAGE_CTL1 | BYPASS_WE | BYPASS_CTL1_WDT_PET;
360
361
362 adapter->bps.reset_tm = time(NULL);
363 sec = 0;
364
365 cmd |= (sec & BYPASS_CTL1_TIME_M) | BYPASS_CTL1_VALID;
366
367
368 cmd |= BYPASS_CTL1_OFFTRST;
369
370 ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &status);
371
372
373 do {
374 if (count++ > 10) {
375 ret_val = IXGBE_BYPASS_FW_WRITE_FAILURE;
376 break;
377 }
378
379 if (adapter->bps.ops.bypass_rw(hw, BYPASS_PAGE_CTL1, &status)) {
380 ret_val = IXGBE_ERR_INVALID_ARGUMENT;
381 break;
382 }
383 } while (!adapter->bps.ops.bypass_valid_rd(cmd, status));
384
385 return ret_val;
386}
387