4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <rte_atomic.h>
36 #include <rte_ethdev.h>
37 #include "ixgbe_ethdev.h"
38 #include "ixgbe_bypass_api.h"
40 #define BYPASS_STATUS_OFF_MASK 3
42 /* Macros to check for invlaid function pointers. */
43 #define FUNC_PTR_OR_ERR_RET(func, retval) do { \
44 if ((func) == NULL) { \
45 PMD_DRV_LOG(ERR, "%s:%d function not supported", \
46 __func__, __LINE__); \
51 #define FUNC_PTR_OR_RET(func) do { \
52 if ((func) == NULL) { \
53 PMD_DRV_LOG(ERR, "%s:%d function not supported", \
54 __func__, __LINE__); \
61 * ixgbe_bypass_set_time - Set bypass FW time epoc.
63 * @hw: pointer to hardware structure
65 * This function with sync the FW date stamp with that of the
69 ixgbe_bypass_set_time(struct ixgbe_adapter
*adapter
)
73 struct ixgbe_hw
*hw
= &adapter
->hw
;
78 * Send the FW our current time and turn on time_valid and
81 mask
= BYPASS_CTL1_TIME_M
|
83 BYPASS_CTL1_OFFTRST_M
;
84 value
= (sec
& BYPASS_CTL1_TIME_M
) |
88 FUNC_PTR_OR_RET(adapter
->bps
.ops
.bypass_set
);
90 /* Store FW reset time (in seconds from epoch). */
91 adapter
->bps
.reset_tm
= time(NULL
);
94 adapter
->bps
.ops
.bypass_set(hw
, BYPASS_PAGE_CTL1
, mask
, value
);
98 * ixgbe_bypass_init - Make some environment changes for bypass
100 * @adapter: pointer to ixgbe_adapter structure for access to state bits
102 * This function collects all the modifications needed by the bypass
106 ixgbe_bypass_init(struct rte_eth_dev
*dev
)
108 struct ixgbe_adapter
*adapter
;
111 adapter
= IXGBE_DEV_TO_ADPATER(dev
);
114 /* Only allow BYPASS ops on the first port */
115 if (hw
->device_id
!= IXGBE_DEV_ID_82599_BYPASS
||
117 PMD_DRV_LOG(ERR
, "bypass function is not supported on that device");
121 /* set bypass ops. */
122 adapter
->bps
.ops
.bypass_rw
= &ixgbe_bypass_rw_generic
;
123 adapter
->bps
.ops
.bypass_valid_rd
= &ixgbe_bypass_valid_rd_generic
;
124 adapter
->bps
.ops
.bypass_set
= &ixgbe_bypass_set_generic
;
125 adapter
->bps
.ops
.bypass_rd_eep
= &ixgbe_bypass_rd_eep_generic
;
127 /* set the time for logging. */
128 ixgbe_bypass_set_time(adapter
);
130 /* Don't have the SDP to the laser */
131 hw
->mac
.ops
.disable_tx_laser
= NULL
;
132 hw
->mac
.ops
.enable_tx_laser
= NULL
;
133 hw
->mac
.ops
.flap_tx_laser
= NULL
;
137 ixgbe_bypass_state_show(struct rte_eth_dev
*dev
, u32
*state
)
143 struct ixgbe_adapter
*adapter
= IXGBE_DEV_TO_ADPATER(dev
);
146 FUNC_PTR_OR_ERR_RET(adapter
->bps
.ops
.bypass_rw
, -ENOTSUP
);
148 cmd
= BYPASS_PAGE_CTL0
;
149 ret_val
= adapter
->bps
.ops
.bypass_rw(hw
, cmd
, &by_ctl
);
151 /* Assume bypass_rw didn't error out, if it did state will
154 *state
= (by_ctl
>> BYPASS_STATUS_OFF_SHIFT
) & BYPASS_STATUS_OFF_MASK
;
161 ixgbe_bypass_state_store(struct rte_eth_dev
*dev
, u32
*new_state
)
163 struct ixgbe_adapter
*adapter
= IXGBE_DEV_TO_ADPATER(dev
);
168 FUNC_PTR_OR_ERR_RET(adapter
->bps
.ops
.bypass_set
, -ENOTSUP
);
170 /* Set the new state */
171 ret_val
= adapter
->bps
.ops
.bypass_set(hw
, BYPASS_PAGE_CTL0
,
172 BYPASS_MODE_OFF_M
, *new_state
);
176 /* Set AUTO back on so FW can receive events */
177 ret_val
= adapter
->bps
.ops
.bypass_set(hw
, BYPASS_PAGE_CTL0
,
178 BYPASS_MODE_OFF_M
, BYPASS_AUTO
);
186 ixgbe_bypass_event_show(struct rte_eth_dev
*dev
, u32 event
,
194 struct ixgbe_adapter
*adapter
= IXGBE_DEV_TO_ADPATER(dev
);
197 FUNC_PTR_OR_ERR_RET(adapter
->bps
.ops
.bypass_rw
, -ENOTSUP
);
199 cmd
= BYPASS_PAGE_CTL0
;
200 ret_val
= adapter
->bps
.ops
.bypass_rw(hw
, cmd
, &by_ctl
);
202 /* Assume bypass_rw didn't error out, if it did event will
206 case BYPASS_EVENT_WDT_TO
:
207 shift
= BYPASS_WDTIMEOUT_SHIFT
;
209 case BYPASS_EVENT_MAIN_ON
:
210 shift
= BYPASS_MAIN_ON_SHIFT
;
212 case BYPASS_EVENT_MAIN_OFF
:
213 shift
= BYPASS_MAIN_OFF_SHIFT
;
215 case BYPASS_EVENT_AUX_ON
:
216 shift
= BYPASS_AUX_ON_SHIFT
;
218 case BYPASS_EVENT_AUX_OFF
:
219 shift
= BYPASS_AUX_OFF_SHIFT
;
225 *state
= (by_ctl
>> shift
) & 0x3;
231 ixgbe_bypass_event_store(struct rte_eth_dev
*dev
, u32 event
,
238 struct ixgbe_adapter
*adapter
= IXGBE_DEV_TO_ADPATER(dev
);
241 FUNC_PTR_OR_ERR_RET(adapter
->bps
.ops
.bypass_set
, -ENOTSUP
);
244 case BYPASS_EVENT_WDT_TO
:
245 off
= BYPASS_WDTIMEOUT_M
;
246 status
= state
<< BYPASS_WDTIMEOUT_SHIFT
;
248 case BYPASS_EVENT_MAIN_ON
:
249 off
= BYPASS_MAIN_ON_M
;
250 status
= state
<< BYPASS_MAIN_ON_SHIFT
;
252 case BYPASS_EVENT_MAIN_OFF
:
253 off
= BYPASS_MAIN_OFF_M
;
254 status
= state
<< BYPASS_MAIN_OFF_SHIFT
;
256 case BYPASS_EVENT_AUX_ON
:
257 off
= BYPASS_AUX_ON_M
;
258 status
= state
<< BYPASS_AUX_ON_SHIFT
;
260 case BYPASS_EVENT_AUX_OFF
:
261 off
= BYPASS_AUX_OFF_M
;
262 status
= state
<< BYPASS_AUX_OFF_SHIFT
;
268 ret_val
= adapter
->bps
.ops
.bypass_set(hw
, BYPASS_PAGE_CTL0
,
275 ixgbe_bypass_wd_timeout_store(struct rte_eth_dev
*dev
, u32 timeout
)
281 struct ixgbe_adapter
*adapter
= IXGBE_DEV_TO_ADPATER(dev
);
284 FUNC_PTR_OR_ERR_RET(adapter
->bps
.ops
.bypass_set
, -ENOTSUP
);
286 /* disable the timer with timeout of zero */
287 if (timeout
== RTE_BYPASS_TMT_OFF
) {
288 status
= 0x0; /* WDG enable off */
289 mask
= BYPASS_WDT_ENABLE_M
;
291 /* set time out value */
292 mask
= BYPASS_WDT_VALUE_M
;
294 /* enable the timer */
295 status
= timeout
<< BYPASS_WDT_TIME_SHIFT
;
296 status
|= 0x1 << BYPASS_WDT_ENABLE_SHIFT
;
297 mask
|= BYPASS_WDT_ENABLE_M
;
300 ret_val
= adapter
->bps
.ops
.bypass_set(hw
, BYPASS_PAGE_CTL0
,
307 ixgbe_bypass_ver_show(struct rte_eth_dev
*dev
, u32
*ver
)
313 struct ixgbe_adapter
*adapter
= IXGBE_DEV_TO_ADPATER(dev
);
316 FUNC_PTR_OR_ERR_RET(adapter
->bps
.ops
.bypass_rw
, -ENOTSUP
);
318 cmd
= BYPASS_PAGE_CTL2
| BYPASS_WE
;
319 cmd
|= (BYPASS_EEPROM_VER_ADD
<< BYPASS_CTL2_OFFSET_SHIFT
) &
320 BYPASS_CTL2_OFFSET_M
;
321 ret_val
= adapter
->bps
.ops
.bypass_rw(hw
, cmd
, &status
);
325 /* wait for the write to stick */
328 /* Now read the results */
330 ret_val
= adapter
->bps
.ops
.bypass_rw(hw
, cmd
, &status
);
334 *ver
= status
& BYPASS_CTL2_DATA_M
; /* only one byte of date */
341 ixgbe_bypass_wd_timeout_show(struct rte_eth_dev
*dev
, u32
*wd_timeout
)
348 struct ixgbe_adapter
*adapter
= IXGBE_DEV_TO_ADPATER(dev
);
351 FUNC_PTR_OR_ERR_RET(adapter
->bps
.ops
.bypass_rw
, -ENOTSUP
);
353 cmd
= BYPASS_PAGE_CTL0
;
354 ret_val
= adapter
->bps
.ops
.bypass_rw(hw
, cmd
, &by_ctl
);
356 wdg
= by_ctl
& BYPASS_WDT_ENABLE_M
;
358 *wd_timeout
= RTE_BYPASS_TMT_OFF
;
360 *wd_timeout
= (by_ctl
>> BYPASS_WDT_TIME_SHIFT
) &
367 ixgbe_bypass_wd_reset(struct rte_eth_dev
*dev
)
375 struct ixgbe_adapter
*adapter
= IXGBE_DEV_TO_ADPATER(dev
);
379 FUNC_PTR_OR_ERR_RET(adapter
->bps
.ops
.bypass_rw
, -ENOTSUP
);
380 FUNC_PTR_OR_ERR_RET(adapter
->bps
.ops
.bypass_valid_rd
, -ENOTSUP
);
382 /* Use the lower level bit-bang functions since we don't need
383 * to read the register first to get it's current state as we
384 * are setting every thing in this write.
387 cmd
= BYPASS_PAGE_CTL1
| BYPASS_WE
| BYPASS_CTL1_WDT_PET
;
389 /* Resync the FW time while writing to CTL1 anyway */
390 adapter
->bps
.reset_tm
= time(NULL
);
393 cmd
|= (sec
& BYPASS_CTL1_TIME_M
) | BYPASS_CTL1_VALID
;
395 /* reset FW timer offset since we are resetting the clock */
396 cmd
|= BYPASS_CTL1_OFFTRST
;
398 ret_val
= adapter
->bps
.ops
.bypass_rw(hw
, cmd
, &status
);
400 /* Read until it matches what we wrote, or we time out */
403 ret_val
= IXGBE_BYPASS_FW_WRITE_FAILURE
;
407 if (adapter
->bps
.ops
.bypass_rw(hw
, BYPASS_PAGE_CTL1
, &status
)) {
408 ret_val
= IXGBE_ERR_INVALID_ARGUMENT
;
411 } while (!adapter
->bps
.ops
.bypass_valid_rd(cmd
, status
));